summaryrefslogtreecommitdiffstats
path: root/web/server/h2o/libh2o/lib/handler/headers_util.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 02:57:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 02:57:58 +0000
commitbe1c7e50e1e8809ea56f2c9d472eccd8ffd73a97 (patch)
tree9754ff1ca740f6346cf8483ec915d4054bc5da2d /web/server/h2o/libh2o/lib/handler/headers_util.c
parentInitial commit. (diff)
downloadnetdata-be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97.tar.xz
netdata-be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97.zip
Adding upstream version 1.44.3.upstream/1.44.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'web/server/h2o/libh2o/lib/handler/headers_util.c')
-rw-r--r--web/server/h2o/libh2o/lib/handler/headers_util.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/web/server/h2o/libh2o/lib/handler/headers_util.c b/web/server/h2o/libh2o/lib/handler/headers_util.c
new file mode 100644
index 00000000..5ecacfa5
--- /dev/null
+++ b/web/server/h2o/libh2o/lib/handler/headers_util.c
@@ -0,0 +1,114 @@
+#include "h2o.h"
+
+static h2o_header_t *find_header(h2o_headers_t *headers, h2o_headers_command_t *cmd)
+{
+ size_t index;
+
+ if (h2o_iovec_is_token(cmd->name)) {
+ index = h2o_find_header(headers, (void *)cmd->name, SIZE_MAX);
+ } else {
+ index = h2o_find_header_by_str(headers, cmd->name->base, cmd->name->len, SIZE_MAX);
+ }
+ if (index == SIZE_MAX)
+ return NULL;
+ return headers->entries + index;
+}
+
+static void remove_header(h2o_headers_t *headers, h2o_headers_command_t *cmd)
+{
+ size_t src, dst = 0;
+
+ for (src = 0; src != headers->size; ++src) {
+ if (h2o_iovec_is_token(cmd->name)) {
+ if (headers->entries[src].name == cmd->name)
+ continue;
+ } else {
+ if (h2o_memis(headers->entries[src].name->base, headers->entries[src].name->len, cmd->name->base, cmd->name->len))
+ continue;
+ }
+ /* not matched */
+ if (dst != src)
+ headers->entries[dst] = headers->entries[src];
+ ++dst;
+ }
+ headers->size = dst;
+}
+
+void h2o_headers_append_command(h2o_headers_command_t **cmds, int cmd, h2o_iovec_t *name, h2o_iovec_t value)
+{
+ h2o_headers_command_t *new_cmds;
+ size_t cnt;
+
+ if (*cmds != NULL) {
+ for (cnt = 0; (*cmds)[cnt].cmd != H2O_HEADERS_CMD_NULL; ++cnt)
+ ;
+ } else {
+ cnt = 0;
+ }
+
+ new_cmds = h2o_mem_alloc_shared(NULL, (cnt + 2) * sizeof(*new_cmds), NULL);
+ if (*cmds != NULL)
+ memcpy(new_cmds, *cmds, cnt * sizeof(*new_cmds));
+ new_cmds[cnt] = (h2o_headers_command_t){cmd, name, value};
+ new_cmds[cnt + 1] = (h2o_headers_command_t){H2O_HEADERS_CMD_NULL};
+
+ if (*cmds != NULL)
+ h2o_mem_release_shared(*cmds);
+ *cmds = new_cmds;
+}
+
+void h2o_rewrite_headers(h2o_mem_pool_t *pool, h2o_headers_t *headers, h2o_headers_command_t *cmd)
+{
+ h2o_header_t *target;
+
+ switch (cmd->cmd) {
+ case H2O_HEADERS_CMD_ADD:
+ goto AddHeader;
+ case H2O_HEADERS_CMD_APPEND:
+ if ((target = find_header(headers, cmd)) == NULL)
+ goto AddHeader;
+ goto AppendToken;
+ case H2O_HEADERS_CMD_MERGE:
+ if ((target = find_header(headers, cmd)) == NULL)
+ goto AddHeader;
+ if (h2o_contains_token(target->value.base, target->value.len, cmd->value.base, cmd->value.len, ','))
+ return;
+ goto AppendToken;
+ case H2O_HEADERS_CMD_SET:
+ remove_header(headers, cmd);
+ goto AddHeader;
+ case H2O_HEADERS_CMD_SETIFEMPTY:
+ if (find_header(headers, cmd) != NULL)
+ return;
+ goto AddHeader;
+ case H2O_HEADERS_CMD_UNSET:
+ remove_header(headers, cmd);
+ return;
+ }
+
+ assert(!"FIXME");
+ return;
+
+AddHeader:
+ if (h2o_iovec_is_token(cmd->name)) {
+ h2o_add_header(pool, headers, (void *)cmd->name, NULL, cmd->value.base, cmd->value.len);
+ } else {
+ h2o_add_header_by_str(pool, headers, cmd->name->base, cmd->name->len, 0, NULL, cmd->value.base, cmd->value.len);
+ }
+ return;
+
+AppendToken:
+ if (target->value.len != 0) {
+ h2o_iovec_t v;
+ v.len = target->value.len + 2 + cmd->value.len;
+ v.base = h2o_mem_alloc_pool(pool, v.len);
+ memcpy(v.base, target->value.base, target->value.len);
+ v.base[target->value.len] = ',';
+ v.base[target->value.len + 1] = ' ';
+ memcpy(v.base + target->value.len + 2, cmd->value.base, cmd->value.len);
+ target->value = v;
+ } else {
+ target->value = cmd->value;
+ }
+ return;
+}