diff --git a/src/array.h b/src/array.h index 359fbbcd..dcb98533 100644 --- a/src/array.h +++ b/src/array.h @@ -37,7 +37,6 @@ typedef struct { } data_string; data_string *data_string_init(void); -data_string *data_response_init(void); typedef struct { DATA_UNSET; diff --git a/src/data_string.c b/src/data_string.c index f9e50d39..e60232fa 100644 --- a/src/data_string.c +++ b/src/data_string.c @@ -49,25 +49,6 @@ static int data_string_insert_dup(data_unset *dst, data_unset *src) { return 0; } -static int data_response_insert_dup(data_unset *dst, data_unset *src) { - data_string *ds_dst = (data_string *)dst; - data_string *ds_src = (data_string *)src; - - if (!buffer_is_empty(ds_dst->value)) { - buffer_append_string_len(ds_dst->value, CONST_STR_LEN("\r\n")); - buffer_append_string_buffer(ds_dst->value, ds_dst->key); - buffer_append_string_len(ds_dst->value, CONST_STR_LEN(": ")); - buffer_append_string_buffer(ds_dst->value, ds_src->value); - } else { - buffer_copy_buffer(ds_dst->value, ds_src->value); - } - - src->free(src); - - return 0; -} - - static void data_string_print(const data_unset *d, int depth) { data_string *ds = (data_string *)d; size_t i, len; @@ -112,12 +93,3 @@ data_string *data_string_init(void) { return ds; } - -data_string *data_response_init(void) { - data_string *ds; - - ds = data_string_init(); - ds->insert_dup = data_response_insert_dup; - - return ds; -} diff --git a/src/http-header-glue.c b/src/http-header-glue.c index 5d4f1f5f..d590ff24 100644 --- a/src/http-header-glue.c +++ b/src/http-header-glue.c @@ -27,14 +27,18 @@ int response_header_insert(server *srv, connection *con, const char *key, size_t UNUSED(srv); - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { - ds = data_response_init(); - } - buffer_copy_string_len(ds->key, key, keylen); - buffer_copy_string_len(ds->value, value, vallen); + if (0 == vallen) return 0; - array_insert_unique(con->response.headers, (data_unset *)ds); + /* if there already is a key by this name append the value */ + if (NULL != (ds = (data_string *)array_get_element_klen(con->response.headers, key, keylen))) { + buffer_append_string_len(ds->value, CONST_STR_LEN("\r\n")); + buffer_append_string_len(ds->value, key, keylen); + buffer_append_string_len(ds->value, CONST_STR_LEN(": ")); + buffer_append_string_len(ds->value, value, vallen); + return 0; + } + array_set_key_value(con->response.headers, key, keylen, value, vallen); return 0; } @@ -1031,13 +1035,7 @@ static int http_response_process_headers(server *srv, connection *con, http_resp break; } - ds = (data_string *) - array_get_unused_element(con->response.headers, TYPE_STRING); - if (NULL == ds) ds = data_response_init(); - buffer_copy_string_len(ds->key, key, key_len); - buffer_copy_string(ds->value, value); - - array_insert_unique(con->response.headers, (data_unset *)ds); + response_header_insert(srv, con, key, key_len, value, strlen(value)); } /* CGI/1.1 rev 03 - 7.2.1.2 */ diff --git a/src/mod_usertrack.c b/src/mod_usertrack.c index e24672f3..028a87c3 100644 --- a/src/mod_usertrack.c +++ b/src/mod_usertrack.c @@ -4,6 +4,7 @@ #include "log.h" #include "buffer.h" #include "rand.h" +#include "response.h" #include "plugin.h" @@ -182,6 +183,7 @@ static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_d URIHANDLER_FUNC(mod_usertrack_uri_handler) { plugin_data *p = p_d; + buffer *cookie; data_string *ds; unsigned char h[16]; li_MD5_CTX Md5Ctx; @@ -219,12 +221,9 @@ URIHANDLER_FUNC(mod_usertrack_uri_handler) { } /* set a cookie */ - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { - ds = data_response_init(); - } - buffer_copy_string_len(ds->key, CONST_STR_LEN("Set-Cookie")); - buffer_copy_buffer(ds->value, p->conf.cookie_name); - buffer_append_string_len(ds->value, CONST_STR_LEN("=")); + cookie = srv->tmp_buf; + buffer_copy_buffer(cookie, p->conf.cookie_name); + buffer_append_string_len(cookie, CONST_STR_LEN("=")); /* taken from mod_auth.c */ @@ -241,29 +240,29 @@ URIHANDLER_FUNC(mod_usertrack_uri_handler) { li_MD5_Final(h, &Md5Ctx); - buffer_append_string_encoded_hex_lc(ds->value, (char *)h, 16); + buffer_append_string_encoded_hex_lc(cookie, (char *)h, 16); /* usertrack.cookie-attrs, if set, replaces all other attrs */ if (!buffer_string_is_empty(p->conf.cookie_attrs)) { - buffer_append_string_buffer(ds->value, p->conf.cookie_attrs); - array_insert_unique(con->response.headers, (data_unset *)ds); + buffer_append_string_buffer(cookie, p->conf.cookie_attrs); + response_header_insert(srv, con, CONST_STR_LEN("Set-Cookie"), CONST_BUF_LEN(cookie)); return HANDLER_GO_ON; } - buffer_append_string_len(ds->value, CONST_STR_LEN("; Path=/")); - buffer_append_string_len(ds->value, CONST_STR_LEN("; Version=1")); + buffer_append_string_len(cookie, CONST_STR_LEN("; Path=/")); + buffer_append_string_len(cookie, CONST_STR_LEN("; Version=1")); if (!buffer_string_is_empty(p->conf.cookie_domain)) { - buffer_append_string_len(ds->value, CONST_STR_LEN("; Domain=")); - buffer_append_string_encoded(ds->value, CONST_BUF_LEN(p->conf.cookie_domain), ENCODING_REL_URI); + buffer_append_string_len(cookie, CONST_STR_LEN("; Domain=")); + buffer_append_string_encoded(cookie, CONST_BUF_LEN(p->conf.cookie_domain), ENCODING_REL_URI); } if (p->conf.cookie_max_age) { - buffer_append_string_len(ds->value, CONST_STR_LEN("; max-age=")); - buffer_append_int(ds->value, p->conf.cookie_max_age); + buffer_append_string_len(cookie, CONST_STR_LEN("; max-age=")); + buffer_append_int(cookie, p->conf.cookie_max_age); } - array_insert_unique(con->response.headers, (data_unset *)ds); + response_header_insert(srv, con, CONST_STR_LEN("Set-Cookie"), CONST_BUF_LEN(cookie)); return HANDLER_GO_ON; } diff --git a/src/mod_wstunnel.c b/src/mod_wstunnel.c index cff378a6..3f959e18 100644 --- a/src/mod_wstunnel.c +++ b/src/mod_wstunnel.c @@ -759,8 +759,7 @@ static int create_MD5_sum(connection *con) { static int create_response_ietf_00(handler_ctx *hctx) { connection *con = hctx->gw.remote_conn; - array * const hdrs = con->response.headers; - data_string *ds; + buffer *value = hctx->srv->tmp_buf; /* "Origin" header is preferred * ("Sec-WebSocket-Origin" is from older drafts of websocket spec) */ @@ -803,16 +802,13 @@ static int create_response_ietf_00(handler_ctx *hctx) { CONST_BUF_LEN(origin->value)); #endif - ds = (data_string *)array_get_unused_element(hdrs, TYPE_STRING); - if (NULL == ds) ds = data_string_init(); - buffer_copy_string_len(ds->key, CONST_STR_LEN("Sec-WebSocket-Location")); if (buffer_is_equal_string(con->uri.scheme, CONST_STR_LEN("https"))) - buffer_copy_string_len(ds->value, CONST_STR_LEN("wss://")); + buffer_copy_string_len(value, CONST_STR_LEN("wss://")); else - buffer_copy_string_len(ds->value, CONST_STR_LEN("ws://")); - buffer_append_string_buffer(ds->value, con->request.http_host); - buffer_append_string_buffer(ds->value, con->uri.path); - array_insert_unique(hdrs, (data_unset *)ds); + buffer_copy_string_len(value, CONST_STR_LEN("ws://")); + buffer_append_string_buffer(value, con->request.http_host); + buffer_append_string_buffer(value, con->uri.path); + response_header_insert(hctx->srv, con, CONST_STR_LEN("Sec-WebSocket-Location"), CONST_BUF_LEN(value)); return 0; } @@ -827,6 +823,7 @@ static int create_response_ietf_00(handler_ctx *hctx) { static int create_response_rfc_6455(handler_ctx *hctx) { connection *con = hctx->gw.remote_conn; + buffer *value = hctx->srv->tmp_buf; array * const hdrs = con->response.headers; data_string *ds; SHA_CTX sha; @@ -856,11 +853,9 @@ static int create_response_rfc_6455(handler_ctx *hctx) { CONST_STR_LEN("upgrade")); #endif - ds = (data_string *)array_get_unused_element(hdrs, TYPE_STRING); - if (NULL == ds) ds = data_string_init(); - buffer_copy_string_len(ds->key, CONST_STR_LEN("Sec-WebSocket-Accept")); - buffer_append_base64_encode(ds->value, sha_digest, SHA_DIGEST_LENGTH, BASE64_STANDARD); - array_insert_unique(hdrs, (data_unset *)ds); + buffer_string_set_length(value, 0); + buffer_append_base64_encode(value, sha_digest, SHA_DIGEST_LENGTH, BASE64_STANDARD); + response_header_insert(hctx->srv, con, CONST_STR_LEN("Sec-WebSocket-Accept"), CONST_BUF_LEN(value)); if (hctx->frame.type == MOD_WEBSOCKET_FRAME_TYPE_BIN) array_set_key_value(hdrs, CONST_STR_LEN("Sec-WebSocket-Protocol"),