diff --git a/README.coding.md b/README.coding.md index d03b613a..fb135033 100644 --- a/README.coding.md +++ b/README.coding.md @@ -416,3 +416,46 @@ The extension may decide to alter or disallow the change, in the example above permessage-deflate restricts the size of his rx output buffer also considering the protocol's rx_buf_size member. +Client connections as HTTP[S] rather than WS[S] +----------------------------------------------- + +You may open a generic http client connection using the same +struct lws_client_connect_info used to create client ws[s] +connections. + +To stay in http[s], set the optional info member "method" to +point to the string "GET" instead of the default NULL. + +After the server headers are processed, when payload from the +server is available the callback LWS_CALLBACK_RECEIVE_CLIENT_HTTP +will be made. + +You can choose whether to process the data immediately, or +queue a callback when an outgoing socket is writeable to provide +flow control, and process the data in the writable callback. + +Either way you use the api lws_http_client_read() to access the +data, eg + + + case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: + { + char buffer[1024 + LWS_PRE]; + char *px = buffer + LWS_PRE; + int lenx = sizeof(buffer) - LWS_PRE; + + lwsl_notice("LWS_CALLBACK_RECEIVE_CLIENT_HTTP\n"); + + /* + * Often you need to flow control this by something + * else being writable. In that case call the api + * to get a callback when writable here, and do the + * pending client read in the writeable callback of + * the output. + */ + if (lws_http_client_read(wsi, &px, &lenx) < 0) + return -1; + while (lenx--) + putchar(*px++); + } + break; diff --git a/lib/client.c b/lib/client.c index e49f1e89..15579426 100644 --- a/lib/client.c +++ b/lib/client.c @@ -440,12 +440,12 @@ lws_client_interpret_server_handshake(struct lws *wsi) } #ifdef LWS_WITH_HTTP_PROXY - wsi->perform_rewrite = 0; - if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) { - if (!strncmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE), - "text/html", 9)) - wsi->perform_rewrite = 1; - } + wsi->perform_rewrite = 0; + if (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE)) { + if (!strncmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE), + "text/html", 9)) + wsi->perform_rewrite = 1; + } #endif /* allocate the per-connection user memory (if any) */ @@ -491,7 +491,7 @@ lws_client_interpret_server_handshake(struct lws *wsi) /* call him back to inform him he is up */ if (wsi->protocol->callback(wsi, - LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP, + LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP, wsi->user_space, NULL, 0)) goto bail3; diff --git a/lib/handshake.c b/lib/handshake.c index 584b34b5..1d362109 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -95,6 +95,9 @@ lws_read(struct lws *wsi, unsigned char *buf, size_t len) break; #endif + case LWSS_CLIENT_HTTP_ESTABLISHED: + break; + case LWSS_HTTP: wsi->hdr_parsing_completed = 0; /* fallthru */ @@ -104,6 +107,7 @@ lws_read(struct lws *wsi, unsigned char *buf, size_t len) wsi->u.hdr.lextable_pos = 0; /* fallthru */ case LWSS_HTTP_HEADERS: + assert(wsi->u.hdr.ah); lwsl_parser("issuing %d bytes to parser\n", (int)len); @@ -227,7 +231,7 @@ postbody_completion: } break; default: - lwsl_err("%s: Unhandled state\n", __func__); + lwsl_err("%s: Unhandled state %d\n", __func__, wsi->state); break; } diff --git a/lib/service.c b/lib/service.c index 6ebe7140..48e7a09d 100644 --- a/lib/service.c +++ b/lib/service.c @@ -492,6 +492,8 @@ lws_http_client_read(struct lws *wsi, char **buf, int *len) { int rlen, n; + + rlen = lws_ssl_capable_read(wsi, (unsigned char *)*buf, *len); if (rlen < 0) return -1; @@ -911,7 +913,8 @@ drain: /* let user code know, he'll usually ask for writeable * callback and drain / reenable it there */ - if (user_callback_handle_rxflow(wsi->protocol->callback, + if (user_callback_handle_rxflow( + wsi->protocol->callback, wsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP, wsi->user_space, NULL, 0)) goto close_and_handled; diff --git a/lwsws/http.c b/lwsws/http.c index 6e005871..7f086339 100644 --- a/lwsws/http.c +++ b/lwsws/http.c @@ -243,6 +243,8 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, pss->reason_bf &= ~1; break; } + + #endif #ifndef LWS_NO_CLIENT if (pss->reason_bf & 2) { @@ -269,6 +271,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, break; #ifndef LWS_NO_CLIENT + case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: { char ctype[64], ctlen = 0; lwsl_err("LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP\n"); diff --git a/test-server/test-client.c b/test-server/test-client.c index c21f0330..086d52a3 100644 --- a/test-server/test-client.c +++ b/test-server/test-client.c @@ -83,8 +83,6 @@ static int callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { - char *buf = (char *)in; - switch (reason) { case LWS_CALLBACK_CLIENT_ESTABLISHED: @@ -126,8 +124,25 @@ callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason, break; case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: - while (len--) - putchar(*buf++); + { + char buffer[1024 + LWS_PRE]; + char *px = buffer + LWS_PRE; + int lenx = sizeof(buffer) - LWS_PRE; + + lwsl_notice("LWS_CALLBACK_RECEIVE_CLIENT_HTTP\n"); + + /* + * Often you need to flow control this by something + * else being writable. In that case call the api + * to get a callback when writable here, and do the + * pending client read in the writeable callback of + * the output. + */ + if (lws_http_client_read(wsi, &px, &lenx) < 0) + return -1; + while (lenx--) + putchar(*px++); + } break; case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: