mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
http proxy: support POST
This commit is contained in:
parent
f7860b6ac6
commit
da3d8cb593
7 changed files with 135 additions and 10 deletions
|
@ -326,6 +326,11 @@ __lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason,
|
|||
|
||||
just_kill_connection:
|
||||
|
||||
#if defined(LWS_WITH_HTTP_PROXY)
|
||||
if (wsi->http.buflist_post_body)
|
||||
lws_buflist_destroy_all_segments(&wsi->http.buflist_post_body);
|
||||
#endif
|
||||
|
||||
if (wsi->role_ops->close_kill_connection)
|
||||
wsi->role_ops->close_kill_connection(wsi, reason);
|
||||
|
||||
|
|
|
@ -250,13 +250,29 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
break;
|
||||
#if !defined(LWS_NO_SERVER)
|
||||
case LWS_CALLBACK_HTTP_BODY_COMPLETION:
|
||||
#if defined(LWS_WITH_HTTP_PROXY)
|
||||
if (wsi->child_list)
|
||||
lwsl_user("%s: LWS_CALLBACK_HTTP_BODY_COMPLETION: %d\n", __func__, (int)len);
|
||||
break;
|
||||
#endif
|
||||
case LWS_CALLBACK_HTTP_FILE_COMPLETION:
|
||||
if (lws_http_transaction_completed(wsi))
|
||||
return -1;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_HTTP_PROXY)
|
||||
case LWS_CALLBACK_HTTP_BODY:
|
||||
if (wsi->child_list) {
|
||||
lwsl_user("%s: LWS_CALLBACK_HTTP_BODY: stashing %d\n", __func__, (int)len);
|
||||
lws_buflist_append_segment(&wsi->http.buflist_post_body, in, len);
|
||||
lws_callback_on_writable(wsi->child_list);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case LWS_CALLBACK_HTTP_WRITEABLE:
|
||||
// lwsl_err("%s: LWS_CALLBACK_HTTP_WRITEABLE\n", __func__);
|
||||
#ifdef LWS_WITH_CGI
|
||||
if (wsi->reason_bf & (LWS_CB_REASON_AUX_BF__CGI_HEADERS |
|
||||
LWS_CB_REASON_AUX_BF__CGI)) {
|
||||
|
@ -317,6 +333,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
}
|
||||
|
@ -494,6 +511,13 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
|
||||
lwsl_debug("%s: LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: "
|
||||
"prepared headers\n", __func__);
|
||||
|
||||
/*
|
||||
* so at this point, the onward client connection can bear
|
||||
* traffic. We might be doing a POST and have pending cached
|
||||
* inbound stuff to send, it can go now.
|
||||
*/
|
||||
|
||||
lws_callback_on_writable(parent);
|
||||
|
||||
break; }
|
||||
|
@ -518,7 +542,6 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
|
||||
case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
|
||||
parent = lws_get_parent(wsi);
|
||||
|
||||
if (!parent)
|
||||
break;
|
||||
|
||||
|
@ -550,7 +573,6 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
|
|||
return -1;
|
||||
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LWS_WITH_CGI
|
||||
|
|
|
@ -654,8 +654,51 @@ rops_handle_POLLIN_h1(struct lws_context_per_thread *pt, struct lws *wsi,
|
|||
static int
|
||||
rops_handle_POLLOUT_h1(struct lws *wsi)
|
||||
{
|
||||
if (lwsi_state(wsi) == LRS_ISSUE_HTTP_BODY)
|
||||
|
||||
if (lwsi_state(wsi) == LRS_ISSUE_HTTP_BODY) {
|
||||
#if defined(LWS_WITH_HTTP_PROXY)
|
||||
if (wsi->http.proxy_clientside) {
|
||||
unsigned char *buf;
|
||||
size_t len = lws_buflist_next_segment_len(
|
||||
&wsi->parent->http.buflist_post_body, &buf);
|
||||
int n;
|
||||
|
||||
lwsl_debug("%s: %p: proxying body %d %d %d %d %d\n",
|
||||
__func__, wsi, (int)len,
|
||||
(int)wsi->http.tx_content_length,
|
||||
(int)wsi->http.tx_content_remain,
|
||||
(int)wsi->http.rx_content_length,
|
||||
(int)wsi->http.rx_content_remain
|
||||
);
|
||||
|
||||
n = lws_write(wsi, buf, len, LWS_WRITE_HTTP);
|
||||
if (n < 0) {
|
||||
lwsl_err("%s: PROXY_BODY: write failed\n",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lws_buflist_use_segment(&wsi->parent->http.buflist_post_body, len);
|
||||
|
||||
if (wsi->parent->http.buflist_post_body)
|
||||
lws_callback_on_writable(wsi);
|
||||
else {
|
||||
#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
|
||||
/* prepare ourselves to do the parsing */
|
||||
wsi->http.ah->parser_state = WSI_TOKEN_NAME_PART;
|
||||
wsi->http.ah->lextable_pos = 0;
|
||||
#if defined(LWS_WITH_CUSTOM_HEADERS)
|
||||
wsi->http.ah->unk_pos = 0;
|
||||
#endif
|
||||
#endif
|
||||
lwsi_set_state(wsi, LRS_WAITING_SERVER_REPLY);
|
||||
lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
|
||||
wsi->context->timeout_secs);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return LWS_HP_RET_USER_SERVICE;
|
||||
}
|
||||
|
||||
if (lwsi_role_client(wsi))
|
||||
return LWS_HP_RET_USER_SERVICE;
|
||||
|
|
|
@ -979,6 +979,9 @@ rops_perform_user_POLLOUT_h2(struct lws *wsi)
|
|||
|
||||
lwsl_info(" h2 action start...\n");
|
||||
n = lws_http_action(w);
|
||||
if (n < 0)
|
||||
lwsl_info (" h2 action result %d\n", n);
|
||||
else
|
||||
lwsl_info(" h2 action result %d "
|
||||
"(wsi->http.rx_content_remain %lld)\n",
|
||||
n, w->http.rx_content_remain);
|
||||
|
@ -989,7 +992,7 @@ rops_perform_user_POLLOUT_h2(struct lws *wsi)
|
|||
* states. In those cases we will hear about
|
||||
* END_STREAM going out in the POLLOUT handler.
|
||||
*/
|
||||
if (!w->h2.pending_status_body &&
|
||||
if (n >= 0 && !w->h2.pending_status_body &&
|
||||
(n || w->h2.send_END_STREAM)) {
|
||||
lwsl_info("closing stream after h2 action\n");
|
||||
lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS,
|
||||
|
@ -997,6 +1000,9 @@ rops_perform_user_POLLOUT_h2(struct lws *wsi)
|
|||
wa = &wsi->h2.child_list;
|
||||
}
|
||||
|
||||
if (n < 0)
|
||||
wa = &wsi->h2.child_list;
|
||||
|
||||
goto next_child;
|
||||
}
|
||||
|
||||
|
|
|
@ -403,10 +403,15 @@ start_ws_handshake:
|
|||
}
|
||||
|
||||
if (wsi->client_http_body_pending) {
|
||||
lwsl_debug("body pending\n");
|
||||
lwsi_set_state(wsi, LRS_ISSUE_HTTP_BODY);
|
||||
lws_set_timeout(wsi,
|
||||
PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD,
|
||||
context->timeout_secs);
|
||||
#if defined(LWS_WITH_HTTP_PROXY)
|
||||
if (wsi->http.proxy_clientside)
|
||||
lws_callback_on_writable(wsi);
|
||||
#endif
|
||||
/* user code must ask for writable callback */
|
||||
break;
|
||||
}
|
||||
|
@ -436,6 +441,12 @@ start_ws_handshake:
|
|||
goto client_http_body_sent;
|
||||
|
||||
case LRS_ISSUE_HTTP_BODY:
|
||||
#if defined(LWS_WITH_HTTP_PROXY)
|
||||
if (wsi->http.proxy_clientside) {
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (wsi->client_http_body_pending) {
|
||||
//lws_set_timeout(wsi,
|
||||
// PENDING_TIMEOUT_CLIENT_ISSUE_PAYLOAD,
|
||||
|
@ -1083,6 +1094,22 @@ lws_generate_client_handshake(struct lws *wsi, char *pkt)
|
|||
lws_hdr_simple_ptr(wsi,
|
||||
_WSI_TOKEN_CLIENT_ORIGIN));
|
||||
}
|
||||
|
||||
#if defined(LWS_WITH_HTTP_PROXY)
|
||||
if (wsi->parent &&
|
||||
lws_hdr_total_length(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
|
||||
p += snprintf(p, 128, "Content-Length: %s\x0d\x0a",
|
||||
lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH));
|
||||
if (atoi(lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_LENGTH)))
|
||||
wsi->client_http_body_pending = 1;
|
||||
}
|
||||
if (wsi->parent &&
|
||||
lws_hdr_total_length(wsi->parent, WSI_TOKEN_HTTP_CONTENT_TYPE)) {
|
||||
p += snprintf(p, 128, "Content-Type: %s\x0d\x0a",
|
||||
lws_hdr_simple_ptr(wsi->parent, WSI_TOKEN_HTTP_CONTENT_TYPE));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(LWS_ROLE_WS)
|
||||
if (wsi->do_ws) {
|
||||
const char *conn1 = "";
|
||||
|
|
|
@ -215,6 +215,7 @@ struct _lws_http_mode_related {
|
|||
|
||||
#if defined(LWS_WITH_HTTP_PROXY)
|
||||
struct lws_rewrite *rw;
|
||||
struct lws_buflist *buflist_post_body;
|
||||
#endif
|
||||
struct allocated_headers *ah;
|
||||
struct lws *ah_wait_list;
|
||||
|
|
|
@ -746,6 +746,7 @@ lws_find_mount(struct lws *wsi, const char *uri_ptr, int uri_len)
|
|||
if (hm->origin_protocol == LWSMPRO_CALLBACK ||
|
||||
((hm->origin_protocol == LWSMPRO_CGI ||
|
||||
lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) ||
|
||||
lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI) ||
|
||||
(wsi->http2_substream &&
|
||||
lws_hdr_total_length(wsi,
|
||||
WSI_TOKEN_HTTP_COLON_PATH)) ||
|
||||
|
@ -1095,8 +1096,19 @@ lws_http_proxy_start(struct lws *wsi, const struct lws_http_mount *hit,
|
|||
else
|
||||
i.host = lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST);
|
||||
i.origin = NULL;
|
||||
if (!ws)
|
||||
i.method = "GET";
|
||||
if (!ws) {
|
||||
if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_POST_URI)
|
||||
#if defined(LWS_WITH_HTTP2)
|
||||
|| (
|
||||
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD) &&
|
||||
!strcmp(lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_COLON_METHOD), "post")
|
||||
)
|
||||
#endif
|
||||
)
|
||||
i.method = "POST";
|
||||
else
|
||||
i.method = "GET";
|
||||
}
|
||||
|
||||
lws_snprintf(host, sizeof(host), "%s:%d", i.address, i.port);
|
||||
i.host = host;
|
||||
|
@ -1402,11 +1414,20 @@ lws_http_action(struct lws *wsi)
|
|||
* The mount is a reverse proxy?
|
||||
*/
|
||||
|
||||
// if (hit)
|
||||
// lwsl_notice("%s: origin_protocol: %d\n", __func__, hit->origin_protocol);
|
||||
//else
|
||||
// lwsl_notice("%s: no hit\n", __func__);
|
||||
|
||||
if (hit->origin_protocol == LWSMPRO_HTTPS ||
|
||||
hit->origin_protocol == LWSMPRO_HTTP)
|
||||
return lws_http_proxy_start(wsi, hit, uri_ptr, 0);
|
||||
hit->origin_protocol == LWSMPRO_HTTP) {
|
||||
n = lws_http_proxy_start(wsi, hit, uri_ptr, 0);
|
||||
lwsl_notice("proxy start says %d\n", n);
|
||||
if (n)
|
||||
return n;
|
||||
|
||||
goto deal_body;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -1534,7 +1555,7 @@ after:
|
|||
return 1;
|
||||
}
|
||||
|
||||
#ifdef LWS_WITH_CGI
|
||||
#if defined(LWS_WITH_CGI) || defined(LWS_WITH_HTTP_PROXY)
|
||||
deal_body:
|
||||
#endif
|
||||
/*
|
||||
|
@ -1547,7 +1568,7 @@ deal_body:
|
|||
*/
|
||||
if (lwsi_state(wsi) != LRS_ISSUING_FILE) {
|
||||
/* Prepare to read body if we have a content length: */
|
||||
lwsl_debug("wsi->http.rx_content_length %lld %d %d\n",
|
||||
lwsl_notice("wsi->http.rx_content_length %lld %d %d\n",
|
||||
(long long)wsi->http.rx_content_length,
|
||||
wsi->upgraded_to_http2, wsi->http2_substream);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue