From 610d5c03ab99c604f2e5b109a8067a821713f469 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Mon, 29 Oct 2018 03:44:24 -0400 Subject: [PATCH] [multiple] perf: write headers to backend write cq write headers directly to dynamic backend write chunkqueue (mod_proxy, mod_fastcgi, mod_scgi) --- src/mod_fastcgi.c | 28 +++++++++++------------ src/mod_proxy.c | 6 ++--- src/mod_scgi.c | 57 +++++++++++++++++++++++++---------------------- 3 files changed, 45 insertions(+), 46 deletions(-) diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c index 351ac5c3..961e07cc 100644 --- a/src/mod_fastcgi.c +++ b/src/mod_fastcgi.c @@ -103,7 +103,7 @@ static int fcgi_env_add(void *venv, const char *key, size_t key_len, const char len += key_len > 127 ? 4 : 1; len += val_len > 127 ? 4 : 1; - if (buffer_string_length(env) + len >= FCGI_MAX_LENGTH) { + if (buffer_string_length(env) + len >= FCGI_MAX_LENGTH + sizeof(FCGI_BeginRequestRecord) + sizeof(FCGI_Header)) { /** * we can't append more headers, ignore it */ @@ -210,7 +210,7 @@ static handler_t fcgi_create_env(server *srv, handler_ctx *hctx) { FCGI_Header header; int request_id; - buffer *fcgi_env = buffer_init(); + buffer *b = chunkqueue_prepend_buffer_open(hctx->wb); gw_host *host = hctx->host; connection *con = hctx->remote_conn; @@ -238,30 +238,28 @@ static handler_t fcgi_create_env(server *srv, handler_ctx *hctx) { beginRecord.body.flags = 0; memset(beginRecord.body.reserved, 0, sizeof(beginRecord.body.reserved)); + buffer_copy_string_len(b, (const char *)&beginRecord, sizeof(beginRecord)); + fcgi_header(&header, FCGI_PARAMS, request_id, 0, 0); /*(set aside space to fill in later)*/ + buffer_append_string_len(b, (const char *)&header, sizeof(header)); + /* send FCGI_PARAMS */ - buffer_string_prepare_copy(fcgi_env, 1023); - if (0 != http_cgi_headers(srv, con, &opts, fcgi_env_add, fcgi_env)) { + if (0 != http_cgi_headers(srv, con, &opts, fcgi_env_add, b)) { con->http_status = 400; con->mode = DIRECT; - buffer_free(fcgi_env); + buffer_string_set_length(b, 0); + chunkqueue_remove_finished_chunks(hctx->wb); return HANDLER_FINISHED; } else { - buffer *b = buffer_init(); - - buffer_copy_string_len(b, (const char *)&beginRecord, sizeof(beginRecord)); - - fcgi_header(&(header), FCGI_PARAMS, request_id, buffer_string_length(fcgi_env), 0); - buffer_append_string_len(b, (const char *)&header, sizeof(header)); - buffer_append_string_buffer(b, fcgi_env); - buffer_free(fcgi_env); + fcgi_header(&(header), FCGI_PARAMS, request_id, + buffer_string_length(b) - sizeof(FCGI_BeginRequestRecord) - sizeof(FCGI_Header), 0); + memcpy(b->ptr+sizeof(FCGI_BeginRequestRecord), (const char *)&header, sizeof(header)); fcgi_header(&(header), FCGI_PARAMS, request_id, 0, 0); buffer_append_string_len(b, (const char *)&header, sizeof(header)); hctx->wb_reqlen = buffer_string_length(b); - chunkqueue_append_buffer(hctx->wb, b); - buffer_free(b); + chunkqueue_prepend_buffer_commit(hctx->wb); } if (con->request.content_length) { diff --git a/src/mod_proxy.c b/src/mod_proxy.c index 4d02b1f1..5ca2b757 100644 --- a/src/mod_proxy.c +++ b/src/mod_proxy.c @@ -708,12 +708,11 @@ static void proxy_set_Forwarded(connection *con, const unsigned int flags) { static handler_t proxy_create_env(server *srv, gw_handler_ctx *gwhctx) { handler_ctx *hctx = (handler_ctx *)gwhctx; connection *con = hctx->gw.remote_conn; - buffer *b = buffer_init(); + buffer *b = chunkqueue_prepend_buffer_open(hctx->gw.wb); const int remap_headers = (NULL != hctx->conf.header.urlpaths || NULL != hctx->conf.header.hosts_request); const int upgrade = hctx->conf.header.upgrade && (NULL != http_header_request_get(con, HTTP_HEADER_UPGRADE, CONST_STR_LEN("Upgrade"))); - buffer_string_prepare_copy(b, 8192-1); /* build header */ @@ -832,8 +831,7 @@ static handler_t proxy_create_env(server *srv, gw_handler_ctx *gwhctx) { buffer_append_string_len(b, CONST_STR_LEN("Connection: close, upgrade\r\n\r\n")); hctx->gw.wb_reqlen = buffer_string_length(b); - chunkqueue_append_buffer(hctx->gw.wb, b); - buffer_free(b); + chunkqueue_prepend_buffer_commit(hctx->gw.wb); if (con->request.content_length) { chunkqueue_append_chunkqueue(hctx->gw.wb, con->request_content_queue); diff --git a/src/mod_scgi.c b/src/mod_scgi.c index fdc04673..0cd10544 100644 --- a/src/mod_scgi.c +++ b/src/mod_scgi.c @@ -142,58 +142,61 @@ static int scgi_env_add_uwsgi(void *venv, const char *key, size_t key_len, const static handler_t scgi_create_env(server *srv, handler_ctx *hctx) { - buffer *b; - - buffer *scgi_env = buffer_init(); + buffer *b = chunkqueue_prepend_buffer_open(hctx->wb); gw_host *host = hctx->host; - - connection *con = hctx->remote_conn; - + connection *con = hctx->remote_conn; http_cgi_opts opts = { 0, 0, host->docroot, NULL }; - http_cgi_header_append_cb scgi_env_add = hctx->conf.proto == LI_PROTOCOL_SCGI ? scgi_env_add_scgi : scgi_env_add_uwsgi; + size_t offset; - buffer_string_prepare_copy(scgi_env, 1023); + /* save space for 9 digits (plus ':'), though incoming HTTP request + * currently limited to 64k (65535, so 5 chars) */ + buffer_copy_string_len(b, CONST_STR_LEN(" ")); - if (0 != http_cgi_headers(srv, con, &opts, scgi_env_add, scgi_env)) { - buffer_free(scgi_env); + if (0 != http_cgi_headers(srv, con, &opts, scgi_env_add, b)) { con->http_status = 400; con->mode = DIRECT; + buffer_string_set_length(b, 0); + chunkqueue_remove_finished_chunks(hctx->wb); return HANDLER_FINISHED; } if (hctx->conf.proto == LI_PROTOCOL_SCGI) { - scgi_env_add(scgi_env, CONST_STR_LEN("SCGI"), CONST_STR_LEN("1")); - b = buffer_init(); - buffer_append_int(b, buffer_string_length(scgi_env)); - buffer_append_string_len(b, CONST_STR_LEN(":")); - buffer_append_string_buffer(b, scgi_env); + size_t len; + scgi_env_add(b, CONST_STR_LEN("SCGI"), CONST_STR_LEN("1")); + buffer_string_set_length(srv->tmp_buf, 0); + buffer_append_int(srv->tmp_buf, buffer_string_length(b)-10); + buffer_append_string_len(srv->tmp_buf, CONST_STR_LEN(":")); + len = buffer_string_length(srv->tmp_buf); + offset = 10 - len; + memcpy(b->ptr+offset, srv->tmp_buf->ptr, len); buffer_append_string_len(b, CONST_STR_LEN(",")); - buffer_free(scgi_env); } else { /* LI_PROTOCOL_UWSGI */ /* http://uwsgi-docs.readthedocs.io/en/latest/Protocol.html */ - size_t len = buffer_string_length(scgi_env); + size_t len = buffer_string_length(b)-10; uint32_t uwsgi_header; if (len > USHRT_MAX) { - buffer_free(scgi_env); con->http_status = 431; /* Request Header Fields Too Large */ con->mode = DIRECT; + buffer_string_set_length(b, 0); + chunkqueue_remove_finished_chunks(hctx->wb); return HANDLER_FINISHED; } - b = buffer_init(); - buffer_string_prepare_copy(b, 4 + len); + offset = 10 - 4; uwsgi_header = ((uint32_t)uwsgi_htole16((uint16_t)len)) << 8; - memcpy(b->ptr, (char *)&uwsgi_header, 4); - buffer_commit(b, 4); - buffer_append_string_buffer(b, scgi_env); - buffer_free(scgi_env); + memcpy(b->ptr+offset, (char *)&uwsgi_header, 4); } - hctx->wb_reqlen = buffer_string_length(b); - chunkqueue_append_buffer(hctx->wb, b); - buffer_free(b); + hctx->wb_reqlen = buffer_string_length(b) - offset; + chunkqueue_prepend_buffer_commit(hctx->wb); + #if 0 + hctx->wb->first->offset += (off_t)offset; + hctx->wb->bytes_in -= (off_t)offset; + #else + chunkqueue_mark_written(hctx->wb, offset); + #endif if (con->request.content_length) { chunkqueue_append_chunkqueue(hctx->wb, con->request_content_queue);