diff --git a/changelog b/changelog index f8608571..fc87206a 100644 --- a/changelog +++ b/changelog @@ -161,6 +161,11 @@ There are 4 new related callbacks if non-NULL, the client wsi is set to be a child of parent_wsi. This ensures if parent_wsi closes, then the client child is closed just before. +7) If you're using SSL, there's a new context creation-time option flag +LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS. If you give this, non-ssl +connections to the server listen port are accepted and receive a 301 +redirect to / on the same host and port using https:// + v1.7.0 ====== diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 3126e847..63442d2b 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -300,6 +300,8 @@ enum lws_context_options { LWS_SERVER_OPTION_VALIDATE_UTF8 = (1 << 8), LWS_SERVER_OPTION_SSL_ECDH = (1 << 9), LWS_SERVER_OPTION_LIBUV = (1 << 10), + LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS = (1 << 11) | + (1 << 3), /****** add new things just above ---^ ******/ }; diff --git a/lib/parsers.c b/lib/parsers.c index 8e1312e8..e284afee 100644 --- a/lib/parsers.c +++ b/lib/parsers.c @@ -1354,9 +1354,10 @@ ping_drop: eff_buf.token_len = wsi->u.ws.rx_ubuf_head; if (lws_ext_cb_active(wsi, LWS_EXT_CB_EXTENDED_PAYLOAD_RX, - &eff_buf, 0) <= 0) /* not handle or fail */ + &eff_buf, 0) <= 0) + /* not handle or fail */ lwsl_ext("ext opc opcode 0x%x unknown\n", - wsi->u.ws.opcode); + wsi->u.ws.opcode); wsi->u.ws.rx_ubuf_head = 0; return 0; diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index a83ab8bc..70dfeaf8 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -1139,6 +1139,9 @@ struct lws { #ifdef _WIN32 unsigned int sock_send_blocking:1; #endif +#ifdef LWS_OPENSSL_SUPPORT + unsigned int redirect_to_https:1; +#endif /* chars */ #ifndef LWS_NO_EXTENSIONS diff --git a/lib/server.c b/lib/server.c index 32ef0410..7ca997e7 100644 --- a/lib/server.c +++ b/lib/server.c @@ -146,6 +146,7 @@ _lws_server_listen_accept_flow_control(struct lws *twsi, int on) int lws_http_action(struct lws *wsi) { + struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; enum http_connection_type connection_type; enum http_version request_version; char content_length_str[32]; @@ -264,6 +265,33 @@ lws_http_action(struct lws *wsi) lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT, wsi->context->timeout_secs); + if (wsi->redirect_to_https) { + /* + * we accepted http:// only so we could redirect to + * https://, so issue the redirect. Create the redirection + * URI from the host: header and ignore the path part + */ + unsigned char *start = pt->serv_buf + LWS_PRE, *p = start, + *end = p + 512; + + if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST)) + goto bail_nuke_ah; + if (lws_add_http_header_status(wsi, 301, &p, end)) + goto bail_nuke_ah; + n = sprintf((char *)end, "https://%s/", + lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST)); + if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_LOCATION, + end, n, &p, end)) + goto bail_nuke_ah; + if (lws_finalize_http_header(wsi, &p, end)) + goto bail_nuke_ah; + n = lws_write(wsi, start, p - start, LWS_WRITE_HTTP_HEADERS); + if (n < 0) + goto bail_nuke_ah; + + return lws_http_transaction_completed(wsi); + } + n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP, wsi->user_space, uri_ptr, uri_len); if (n) { diff --git a/lib/ssl.c b/lib/ssl.c index 2a94f153..c817a9a2 100644 --- a/lib/ssl.c +++ b/lib/ssl.c @@ -757,6 +757,9 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) SSL_shutdown(wsi->ssl); SSL_free(wsi->ssl); wsi->ssl = NULL; + if (context->options & + LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS) + wsi->redirect_to_https = 1; goto accepted; } if (!n) /* diff --git a/test-server/test-server.c b/test-server/test-server.c index 09f70464..58f3d7ca 100644 --- a/test-server/test-server.c +++ b/test-server/test-server.c @@ -349,6 +349,11 @@ int main(int argc, char **argv) "!DHE-RSA-AES256-SHA256:" "!AES256-GCM-SHA384:" "!AES256-SHA256"; + + if (use_ssl) + /* redirect guys coming on http */ + info.options |= LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS; + context = lws_create_context(&info); if (context == NULL) { lwsl_err("libwebsocket init failed\n");