http_response_backend_error()

consolidate repeated code in dynamic handlers which manipulates
con->file_finished.  Centralize calls to http_chunk_close().

(mod_cgi, mod_fastcgi, mod_scgi, mod_proxy)
This commit is contained in:
Glenn Strauss 2016-06-18 20:39:00 -04:00
parent 923688d2da
commit 4ef4baa59d
8 changed files with 27 additions and 77 deletions

View File

@ -169,6 +169,7 @@ static void connection_handle_errdoc_init(server *srv, connection *con) {
}
}
con->response.transfer_encoding = 0;
buffer_reset(con->physical.path);
array_reset(con->response.headers);
chunkqueue_reset(con->write_queue);
@ -291,7 +292,6 @@ static int connection_handle_write_prepare(server *srv, connection *con) {
http_chunk_append_buffer(srv, con, b);
buffer_free(b);
http_chunk_close(srv, con);
response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
}
@ -1031,7 +1031,9 @@ int connection_state_machine(server *srv, connection *con) {
switch (r = http_response_prepare(srv, con)) {
case HANDLER_WAIT_FOR_EVENT:
if (!con->file_started || 0 == con->conf.stream_response_body) break; /* come back here */
if (!con->file_finished && (!con->file_started || 0 == con->conf.stream_response_body)) {
break; /* come back here */
}
/* response headers received from backend; fall through to start response */
case HANDLER_FINISHED:
if (con->error_handler_saved_status > 0) {

View File

@ -727,6 +727,17 @@ void http_response_xsendfile (server *srv, connection *con, buffer *path, const
}
}
void http_response_backend_error (server *srv, connection *con) {
UNUSED(srv);
if (con->file_started) {
/*(response might have been already started, kill the connection)*/
/*(mode == DIRECT to avoid later call to http_response_backend_done())*/
con->mode = DIRECT; /*(avoid sending final chunked block)*/
con->keep_alive = 0; /*(no keep-alive; final chunked block not sent)*/
con->file_finished = 1;
} /*(else error status set later by http_response_backend_done())*/
}
void http_response_backend_done (server *srv, connection *con) {
/* (not CON_STATE_ERROR and not CON_STATE_RESPONSE_END,
* i.e. not called from handle_connection_close or connection_reset

View File

@ -410,12 +410,6 @@ static int cgi_demux_response(server *srv, handler_ctx *hctx) {
if (n == 0) {
/* read finished */
con->file_finished = 1;
/* send final chunk */
http_chunk_close(srv, con);
return FDEVENT_HANDLED_FINISHED;
}
@ -1589,7 +1583,7 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) {
}
/* if not done, wait for CGI to close stdout, so we read EOF on pipe */
return con->file_finished ? HANDLER_FINISHED : HANDLER_WAIT_FOR_EVENT;
return HANDLER_WAIT_FOR_EVENT;
}

View File

@ -1863,7 +1863,6 @@ static connection_result_t fcgi_establish_connection(server *srv, handler_ctx *h
#define FCGI_ENV_ADD_CHECK(ret, con) \
if (ret == -1) { \
con->http_status = 400; \
con->file_finished = 1; \
return -1; \
};
static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
@ -2677,15 +2676,6 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
break;
case FCGI_END_REQUEST:
con->file_finished = 1;
if (host->mode != FCGI_AUTHORIZER ||
!(con->http_status == 0 ||
con->http_status == 200)) {
/* send chunk-end if necessary */
http_chunk_close(srv, con);
}
fin = 1;
break;
default:
@ -3357,21 +3347,15 @@ static handler_t fcgi_recv_response(server *srv, handler_ctx *hctx) {
"response not received, request sent:", hctx->wb->bytes_out,
"on socket:", proc->connection_name,
"for", con->uri.path, "?", con->uri.query, ", closing connection");
fcgi_connection_close(srv, hctx);
} else {
/* response might have been already started, kill the connection */
log_error_write(srv, __FILE__, __LINE__, "ssbsBSBs",
"response already sent out, but backend returned error",
"on socket:", proc->connection_name,
"for", con->uri.path, "?", con->uri.query, ", terminating connection");
con->keep_alive = 0;
con->file_finished = 1;
con->mode = DIRECT; /*(avoid sending final chunked block)*/
fcgi_connection_close(srv, hctx);
}
http_response_backend_error(srv, con);
fcgi_connection_close(srv, hctx);
return HANDLER_FINISHED;
}
@ -3432,11 +3416,7 @@ static handler_t fcgi_handle_fdevent(server *srv, void *ctx, int revents) {
log_error_write(srv, __FILE__, __LINE__, "s",
"fcgi: got a FDEVENT_ERR. Don't know why.");
if (con->file_started) {
con->keep_alive = 0;
con->file_finished = 1;
con->mode = DIRECT; /*(avoid sending final chunked block)*/
}
http_response_backend_error(srv, con);
fcgi_connection_close(srv, hctx);
}

View File

@ -240,7 +240,6 @@ URIHANDLER_FUNC(mod_flv_streaming_path_handler) {
chunkqueue_reset(con->write_queue);
return HANDLER_GO_ON;
}
http_chunk_close(srv, con);
response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("video/x-flv"));

View File

@ -742,13 +742,8 @@ static int proxy_demux_response(server *srv, handler_ctx *hctx) {
}
buffer_reset(hctx->response);
}
} else {
/* reading from upstream done */
con->file_finished = 1;
http_chunk_close(srv, con);
fin = 1;
}
@ -1003,26 +998,14 @@ static handler_t proxy_recv_response(server *srv, handler_ctx *hctx) {
switch (proxy_demux_response(srv, hctx)) {
case 0:
break;
case -1:
http_response_backend_error(srv, hctx->remote_conn);
/* fall through */
case 1:
/* we are done */
proxy_connection_close(srv, hctx);
return HANDLER_FINISHED;
case -1: {
connection *con = hctx->remote_conn;
if (con->file_started == 0) {
/* reading response headers failed */
} else {
/* response might have been already started, kill the connection */
con->keep_alive = 0;
con->file_finished = 1;
con->mode = DIRECT; /*(avoid sending final chunked block)*/
}
proxy_connection_close(srv, hctx);
return HANDLER_FINISHED;
}
}
return HANDLER_GO_ON;
@ -1135,11 +1118,7 @@ static handler_t proxy_handle_fdevent(server *srv, void *ctx, int revents) {
} else if (revents & FDEVENT_ERR) {
log_error_write(srv, __FILE__, __LINE__, "sd", "proxy-FDEVENT_ERR, but no HUP", revents);
if (con->file_started) {
con->keep_alive = 0;
con->file_finished = 1;
con->mode = DIRECT; /*(avoid sending final chunked block)*/
}
http_response_backend_error(srv, con);
proxy_connection_close(srv, hctx);
}

View File

@ -1869,12 +1869,6 @@ static int scgi_demux_response(server *srv, handler_ctx *hctx) {
if (n == 0) {
/* read finished */
con->file_finished = 1;
/* send final chunk */
http_chunk_close(srv, con);
return 1;
}
@ -2678,21 +2672,15 @@ static handler_t scgi_recv_response(server *srv, handler_ctx *hctx) {
"response not sent, request sent:", hctx->wb->bytes_out,
"connection-fd:", con->fd,
"fcgi-fd:", hctx->fd);
scgi_connection_close(srv, hctx);
} else {
/* response might have been already started, kill the connection */
log_error_write(srv, __FILE__, __LINE__, "ssdsd",
"response already sent out, termination connection",
"connection-fd:", con->fd,
"fcgi-fd:", hctx->fd);
con->keep_alive = 0;
con->file_finished = 1;
con->mode = DIRECT; /*(avoid sending final chunked block)*/
scgi_connection_close(srv, hctx);
}
http_response_backend_error(srv, con);
scgi_connection_close(srv, hctx);
return HANDLER_FINISHED;
}
}
@ -2758,11 +2746,7 @@ static handler_t scgi_handle_fdevent(server *srv, void *ctx, int revents) {
log_error_write(srv, __FILE__, __LINE__, "s",
"fcgi: got a FDEVENT_ERR. Don't know why.");
if (con->file_started) {
con->keep_alive = 0;
con->file_finished = 1;
con->mode = DIRECT; /*(avoid sending final chunked block)*/
}
http_response_backend_error(srv, con);
scgi_connection_close(srv, hctx);
}

View File

@ -19,6 +19,7 @@ int http_response_handle_cachable(server *srv, connection *con, buffer * mtime);
void http_response_send_file (server *srv, connection *con, buffer *path);
void http_response_xsendfile (server *srv, connection *con, buffer *path, const array *xdocroot);
void http_response_backend_done (server *srv, connection *con);
void http_response_backend_error (server *srv, connection *con);
buffer * strftime_cache_get(server *srv, time_t last_mod);
#endif