Index: modules/proxy/mod_proxy_wstunnel.c =================================================================== --- modules/proxy/mod_proxy_wstunnel.c (revision 1801041) +++ modules/proxy/mod_proxy_wstunnel.c (working copy) @@ -39,7 +39,9 @@ typedef struct ws_baton_t { static void proxy_wstunnel_callback(void *b); -static int proxy_wstunnel_pump(ws_baton_t *baton, apr_time_t timeout, int try_poll) { +static int proxy_wstunnel_pump(ws_baton_t *baton, apr_time_t timeout, + int try_poll, int *replied) +{ request_rec *r = baton->r; conn_rec *c = r->connection; proxy_conn_rec *conn = baton->proxy_connrec; @@ -53,7 +55,7 @@ static void proxy_wstunnel_callback(void *b); apr_status_t rv; apr_bucket_brigade *bb_i = baton->bb_i; apr_bucket_brigade *bb_o = baton->bb_o; - int done = 0, replied = 0; + int done = 0; do { rv = apr_pollset_poll(pollset, timeout, &pollcnt, &signalled); @@ -91,7 +93,7 @@ static void proxy_wstunnel_callback(void *b); done |= ap_proxy_transfer_between_connections(r, backconn, c, bb_i, bb_o, "backend", - &replied, + replied, AP_IOBUFSIZE, 0) != APR_SUCCESS; @@ -143,13 +145,7 @@ static void proxy_wstunnel_callback(void *b); ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "finished with poll() - cleaning up"); - - if (!replied) { - return HTTP_BAD_GATEWAY; - } - else { - return OK; - } + return OK; } static void proxy_wstunnel_finish(ws_baton_t *baton) { @@ -181,12 +177,14 @@ static void proxy_wstunnel_cancel_callback(void *b * We don't need the invoke_mtx, since we never put multiple callback events * in the queue. */ -static void proxy_wstunnel_callback(void *b) { +static void proxy_wstunnel_callback(void *b) +{ int status; ws_baton_t *baton = (ws_baton_t*)b; proxyws_dir_conf *dconf = ap_get_module_config(baton->r->per_dir_config, &proxy_wstunnel_module); apr_pool_clear(baton->subpool); - status = proxy_wstunnel_pump(baton, dconf->async_delay, dconf->mpm_can_poll); + status = proxy_wstunnel_pump(baton, dconf->async_delay, + dconf->mpm_can_poll, NULL); if (status == SUSPENDED) { apr_pollfd_t *pfd; @@ -315,6 +313,8 @@ static int proxy_wstunnel_request(apr_pool_t *p, r int status; proxyws_dir_conf *dconf = ap_get_module_config(r->per_dir_config, &proxy_wstunnel_module); const char *upgrade_method = *worker->s->upgrade ? worker->s->upgrade : "WebSocket"; + ap_filter_t *saved_output_filters, *saved_proto_output_filters; + int replied = 0; header_brigade = apr_brigade_create(p, backconn->bucket_alloc); @@ -367,6 +367,8 @@ static int proxy_wstunnel_request(apr_pool_t *p, r pollfd.desc.s = client_socket; apr_pollset_add(pollset, &pollfd); + saved_output_filters = r->output_filters; + saved_proto_output_filters = r->proto_output_filters; ap_remove_input_filter_byhandle(c->input_filters, "reqtimeout"); r->output_filters = c->output_filters; @@ -389,10 +391,12 @@ static int proxy_wstunnel_request(apr_pool_t *p, r apr_pool_create(&baton->subpool, r->pool); if (!dconf->mpm_can_poll) { - status = proxy_wstunnel_pump(baton, dconf->idle_timeout, dconf->mpm_can_poll); + status = proxy_wstunnel_pump(baton, dconf->idle_timeout, + dconf->mpm_can_poll, &replied); } else { - status = proxy_wstunnel_pump(baton, dconf->async_delay, dconf->mpm_can_poll); + status = proxy_wstunnel_pump(baton, dconf->async_delay, + dconf->mpm_can_poll, &replied); apr_pool_clear(baton->subpool); if (status == SUSPENDED) { apr_pollfd_t *pfd; @@ -420,19 +424,31 @@ static int proxy_wstunnel_request(apr_pool_t *p, r return SUSPENDED; } else if (APR_STATUS_IS_ENOTIMPL(rv)) { - ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(02544) "No async support"); - status = proxy_wstunnel_pump(baton, dconf->idle_timeout, 0); /* force no async */ + ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, + APLOGNO(02544) "No async support"); + status = proxy_wstunnel_pump(baton, dconf->idle_timeout, + 0, /* force no async */ + &replied); } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02543) "error creating websockets tunnel"); - return HTTP_INTERNAL_SERVER_ERROR; + if (!replied) { + status = HTTP_INTERNAL_SERVER_ERROR; + } } } } - if (status != OK) { - /* Avoid sending error pages down an upgraded connection */ + /* Avoid sending error pages down an upgraded connection */ + if (!replied) { + r->output_filters = saved_output_filters; + r->proto_output_filters = saved_proto_output_filters; + if (status == OK) { + status = HTTP_BAD_GATEWAY; + } + } + else if (status != OK) { if (status != HTTP_REQUEST_TIME_OUT) { r->status = status; }