From 7ce6d497c1cab2bed8f78f6eda7d508c644f5754 Mon Sep 17 00:00:00 2001 From: Jessie Murray Date: Tue, 16 Nov 2021 17:48:16 -0800 Subject: [PATCH] Add HEADER_CHECK_DUPE to bypass duplicate check Almost all header entries are guaranteed to be added only once, so we don't need to check for duplicates all the time. In the current code base only Content-Length has the potential for being added twice, and even then it seems highly unlikely. For all others, we can now bypass this check. This commit also changes the header_copy flags to be 1-bit flags, so that they can be combined. --- src/http.c | 24 +++++++++++++----------- src/http.h | 8 +++++--- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/http.c b/src/http.c index 83d764f..d750d6a 100644 --- a/src/http.c +++ b/src/http.c @@ -97,13 +97,15 @@ http_response_set_header(struct http_response *r, const char *k, const char *v, size_t key_sz = strlen(k); size_t val_sz = strlen(v); - for(i = 0; i < r->header_count; ++i) { - if(strncmp(r->headers[i].key, k, key_sz) == 0) { - pos = i; - /* free old value before replacing it. */ - if(r->headers[i].copy == HEADER_COPY_KEY) free(r->headers[i].key); - if(r->headers[i].copy == HEADER_COPY_VALUE) free(r->headers[i].val); - break; + if(copy & HEADER_CHECK_DUPE) { + for(i = 0; i < r->header_count; ++i) { + if(strncmp(r->headers[i].key, k, key_sz) == 0) { + pos = i; + /* free old value before replacing it. */ + if(r->headers[i].copy & HEADER_COPY_KEY) free(r->headers[i].key); + if(r->headers[i].copy & HEADER_COPY_VALUE) free(r->headers[i].val); + break; + } } } @@ -117,7 +119,7 @@ http_response_set_header(struct http_response *r, const char *k, const char *v, r->header_count++; /* copy key if needed */ - if(copy == HEADER_COPY_KEY) { + if(copy & HEADER_COPY_KEY) { r->headers[pos].key = calloc(key_sz + 1, 1); memcpy(r->headers[pos].key, k, key_sz); } else { @@ -126,7 +128,7 @@ http_response_set_header(struct http_response *r, const char *k, const char *v, r->headers[pos].key_sz = key_sz; /* copy val */ - if(copy == HEADER_COPY_VALUE) { + if(copy & HEADER_COPY_VALUE) { r->headers[pos].val = calloc(val_sz + 1, 1); memcpy(r->headers[pos].val, v, val_sz); } else { @@ -243,9 +245,9 @@ http_response_write(struct http_response *r, int fd) { if(r->code == 200 && r->body) { char content_length[22]; sprintf(content_length, "%zd", r->body_len); - http_response_set_header(r, "Content-Length", content_length, HEADER_COPY_VALUE); + http_response_set_header(r, "Content-Length", content_length, HEADER_COPY_VALUE | HEADER_CHECK_DUPE); } else { - http_response_set_header(r, "Content-Length", "0", HEADER_COPY_NONE); + http_response_set_header(r, "Content-Length", "0", HEADER_COPY_NONE | HEADER_CHECK_DUPE); } } diff --git a/src/http.h b/src/http.h index 0310f1d..20d8d8a 100644 --- a/src/http.h +++ b/src/http.h @@ -7,10 +7,12 @@ struct http_client; struct worker; +/* bit flags */ typedef enum { - HEADER_COPY_NONE = 0, - HEADER_COPY_KEY = 1, - HEADER_COPY_VALUE = 2 + HEADER_COPY_NONE = 0, /* don't strdup key or value */ + HEADER_COPY_KEY = 1, /* strdup key only */ + HEADER_COPY_VALUE = 2, /* strdup value only */ + HEADER_CHECK_DUPE = 4 /* replace duplicate when adding header */ } header_copy; struct http_header {