summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_http_set_headers.c
diff options
context:
space:
mode:
authorZhidao HONG <z.hong@f5.com>2023-08-09 14:37:16 +0800
committerZhidao HONG <z.hong@f5.com>2023-08-09 14:37:16 +0800
commita28bef097cd63da3bbb375ef0283e65be41a88ff (patch)
tree8553e74c050a9747bdba928cbaec82ee6d15cb5d /src/nxt_http_set_headers.c
parent9f04d6db630a22658581cbe7a9d28ecdb13d8de9 (diff)
downloadunit-a28bef097cd63da3bbb375ef0283e65be41a88ff.tar.gz
unit-a28bef097cd63da3bbb375ef0283e65be41a88ff.tar.bz2
HTTP: controlling response headers support.
Diffstat (limited to 'src/nxt_http_set_headers.c')
-rw-r--r--src/nxt_http_set_headers.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/nxt_http_set_headers.c b/src/nxt_http_set_headers.c
new file mode 100644
index 00000000..25dd7478
--- /dev/null
+++ b/src/nxt_http_set_headers.c
@@ -0,0 +1,176 @@
+
+/*
+ * Copyright (C) Zhidao HONG
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_router.h>
+#include <nxt_http.h>
+
+
+typedef struct {
+ nxt_str_t name;
+ nxt_tstr_t *value;
+} nxt_http_header_val_t;
+
+
+nxt_int_t
+nxt_http_set_headers_init(nxt_router_conf_t *rtcf, nxt_http_action_t *action,
+ nxt_http_action_conf_t *acf)
+ {
+ uint32_t next;
+ nxt_str_t str, name;
+ nxt_array_t *headers;
+ nxt_conf_value_t *value;
+ nxt_http_header_val_t *hv;
+
+ headers = nxt_array_create(rtcf->mem_pool, 4,
+ sizeof(nxt_http_header_val_t));
+ if (nxt_slow_path(headers == NULL)) {
+ return NXT_ERROR;
+ }
+
+ action->set_headers = headers;
+
+ next = 0;
+
+ for ( ;; ) {
+ value = nxt_conf_next_object_member(acf->set_headers, &name, &next);
+ if (value == NULL) {
+ break;
+ }
+
+ hv = nxt_array_zero_add(headers);
+ if (nxt_slow_path(hv == NULL)) {
+ return NXT_ERROR;
+ }
+
+ hv->name.length = name.length;
+
+ hv->name.start = nxt_mp_nget(rtcf->mem_pool, name.length);
+ if (nxt_slow_path(hv->name.start == NULL)) {
+ return NXT_ERROR;
+ }
+
+ nxt_memcpy(hv->name.start, name.start, name.length);
+
+ if (nxt_conf_type(value) == NXT_CONF_STRING) {
+ nxt_conf_get_string(value, &str);
+
+ hv->value = nxt_tstr_compile(rtcf->tstr_state, &str, 0);
+ if (nxt_slow_path(hv->value == NULL)) {
+ return NXT_ERROR;
+ }
+ }
+ }
+
+ return NXT_OK;
+}
+
+
+static nxt_http_field_t *
+nxt_http_resp_header_find(nxt_http_request_t *r, u_char *name, size_t length)
+{
+ nxt_http_field_t *f;
+
+ nxt_list_each(f, r->resp.fields) {
+
+ if (f->skip) {
+ continue;
+ }
+
+ if (length == f->name_length
+ && nxt_memcasecmp(name, f->name, f->name_length) == 0)
+ {
+ return f;
+ }
+
+ } nxt_list_loop;
+
+ return NULL;
+}
+
+
+nxt_int_t
+nxt_http_set_headers(nxt_http_request_t *r)
+{
+ nxt_int_t ret;
+ nxt_uint_t i, n;
+ nxt_str_t *value;
+ nxt_http_field_t *f;
+ nxt_router_conf_t *rtcf;
+ nxt_http_action_t *action;
+ nxt_http_header_val_t *hv, *header;
+
+ action = r->action;
+
+ if (action == NULL || action->set_headers == NULL) {
+ return NXT_OK;
+ }
+
+ if ((r->status < NXT_HTTP_OK || r->status >= NXT_HTTP_BAD_REQUEST)) {
+ return NXT_OK;
+ }
+
+ rtcf = r->conf->socket_conf->router_conf;
+
+ header = action->set_headers->elts;
+ n = action->set_headers->nelts;
+
+ value = nxt_mp_zalloc(r->mem_pool, sizeof(nxt_str_t) * n);
+ if (nxt_slow_path(value == NULL)) {
+ return NXT_ERROR;
+ }
+
+ for (i = 0; i < n; i++) {
+ hv = &header[i];
+
+ if (hv->value == NULL) {
+ continue;
+ }
+
+ if (nxt_tstr_is_const(hv->value)) {
+ nxt_tstr_str(hv->value, &value[i]);
+
+ } else {
+ ret = nxt_tstr_query_init(&r->tstr_query, rtcf->tstr_state,
+ &r->tstr_cache, r, r->mem_pool);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+
+ nxt_tstr_query(&r->task, r->tstr_query, hv->value, &value[i]);
+
+ if (nxt_slow_path(nxt_tstr_query_failed(r->tstr_query))) {
+ return NXT_ERROR;
+ }
+ }
+ }
+
+ for (i = 0; i < n; i++) {
+ hv = &header[i];
+
+ f = nxt_http_resp_header_find(r, hv->name.start, hv->name.length);
+
+ if (value[i].start != NULL) {
+
+ if (f == NULL) {
+ f = nxt_list_zero_add(r->resp.fields);
+ if (nxt_slow_path(f == NULL)) {
+ return NXT_ERROR;
+ }
+
+ f->name = hv->name.start;
+ f->name_length = hv->name.length;
+ }
+
+ f->value = value[i].start;
+ f->value_length = value[i].length;
+
+ } else if (f != NULL) {
+ f->skip = 1;
+ }
+ }
+
+ return NXT_OK;
+}