aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/hs_apps/http_cli.c34
-rw-r--r--src/plugins/hs_apps/http_client.c33
-rw-r--r--src/plugins/hs_apps/http_client_cli.c16
-rw-r--r--src/plugins/hs_apps/http_tps.c35
-rw-r--r--src/plugins/hs_apps/proxy.c42
-rw-r--r--src/plugins/hs_apps/proxy.h3
-rw-r--r--src/plugins/hs_apps/vcl/vcl_test_protos.c13
-rw-r--r--src/plugins/http/http.c152
-rw-r--r--src/plugins/http/http.h110
-rw-r--r--src/plugins/http/http_plugin.rst54
-rw-r--r--src/plugins/http_static/http_static.h6
-rw-r--r--src/plugins/http_static/static_server.c63
12 files changed, 289 insertions, 272 deletions
diff --git a/src/plugins/hs_apps/http_cli.c b/src/plugins/hs_apps/http_cli.c
index d670ae6b369..531e2750c1e 100644
--- a/src/plugins/hs_apps/http_cli.c
+++ b/src/plugins/hs_apps/http_cli.c
@@ -52,7 +52,8 @@ typedef struct
u32 tx_offset;
u32 vpp_session_index;
http_header_table_t req_headers;
- http_header_t *resp_headers;
+ http_headers_ctx_t resp_headers;
+ u8 *resp_headers_buf;
} hcs_session_t;
typedef struct
@@ -92,6 +93,7 @@ hcs_session_alloc (u32 thread_index)
memset (hs, 0, sizeof (*hs));
hs->session_index = hs - hcm->sessions[thread_index];
hs->thread_index = thread_index;
+ vec_validate (hs->resp_headers_buf, 255);
return hs;
}
@@ -172,21 +174,10 @@ start_send_data (hcs_session_t *hs, http_status_code_t status)
{
http_msg_t msg;
session_t *ts;
- u8 *headers_buf = 0;
int rv;
- if (vec_len (hs->resp_headers))
- {
- headers_buf = http_serialize_headers (hs->resp_headers);
- vec_reset_length (hs->resp_headers);
- msg.data.headers_offset = 0;
- msg.data.headers_len = vec_len (headers_buf);
- }
- else
- {
- msg.data.headers_offset = 0;
- msg.data.headers_len = 0;
- }
+ msg.data.headers_offset = 0;
+ msg.data.headers_len = hs->resp_headers.tail_offset;
msg.type = HTTP_MSG_REPLY;
msg.code = status;
@@ -201,9 +192,9 @@ start_send_data (hcs_session_t *hs, http_status_code_t status)
if (msg.data.headers_len)
{
- rv = svm_fifo_enqueue (ts->tx_fifo, vec_len (headers_buf), headers_buf);
+ rv = svm_fifo_enqueue (ts->tx_fifo, msg.data.headers_len,
+ hs->resp_headers.buf);
ASSERT (rv == msg.data.headers_len);
- vec_free (headers_buf);
}
if (!msg.data.body_len)
@@ -245,8 +236,7 @@ send_data_to_http (void *rpc_args)
if (args->plain_text)
type = HTTP_CONTENT_TEXT_PLAIN;
- http_add_header (&hs->resp_headers,
- http_header_name_token (HTTP_HEADER_CONTENT_TYPE),
+ http_add_header (&hs->resp_headers, HTTP_HEADER_CONTENT_TYPE,
http_content_type_token (type));
start_send_data (hs, HTTP_STATUS_OK);
@@ -371,7 +361,8 @@ hcs_ts_rx_callback (session_t *ts)
hs = hcs_session_get (ts->thread_index, ts->opaque);
hs->tx_buf = 0;
- vec_reset_length (hs->resp_headers);
+ http_init_headers_ctx (&hs->resp_headers, hs->resp_headers_buf,
+ vec_len (hs->resp_headers_buf));
http_reset_header_table (&hs->req_headers);
/* Read the http message header */
@@ -380,8 +371,7 @@ hcs_ts_rx_callback (session_t *ts)
if (msg.type != HTTP_MSG_REQUEST || msg.method_type != HTTP_REQ_GET)
{
- http_add_header (&hs->resp_headers,
- http_header_name_token (HTTP_HEADER_ALLOW),
+ http_add_header (&hs->resp_headers, HTTP_HEADER_ALLOW,
http_token_lit ("GET"));
start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED);
goto done;
@@ -540,7 +530,7 @@ hcs_ts_cleanup_callback (session_t *s, session_cleanup_ntf_t ntf)
return;
vec_free (hs->tx_buf);
- vec_free (hs->resp_headers);
+ vec_free (hs->resp_headers_buf);
http_free_header_table (&hs->req_headers);
hcs_session_free (hs);
}
diff --git a/src/plugins/hs_apps/http_client.c b/src/plugins/hs_apps/http_client.c
index 91ac6cf0032..20271fc4aea 100644
--- a/src/plugins/hs_apps/http_client.c
+++ b/src/plugins/hs_apps/http_client.c
@@ -6,7 +6,6 @@
#include <vnet/session/application_interface.h>
#include <vnet/session/session.h>
#include <http/http.h>
-#include <http/http_header_names.h>
#include <http/http_content_types.h>
#include <http/http_status_codes.h>
#include <vppinfra/unix.h>
@@ -34,7 +33,7 @@ typedef struct
u32 thread_index;
vlib_main_t *vlib_main;
u8 *headers_buf;
- http_header_t *req_headers;
+ http_headers_ctx_t req_headers;
http_msg_t msg;
} hc_worker_t;
@@ -155,9 +154,9 @@ hc_request (session_t *s, session_error_t err)
rv = svm_fifo_enqueue (s->tx_fifo, vec_len (hcm->target), hcm->target);
ASSERT (rv == vec_len (hcm->target));
- rv = svm_fifo_enqueue (s->tx_fifo, vec_len (wrk->headers_buf),
+ rv = svm_fifo_enqueue (s->tx_fifo, wrk->req_headers.tail_offset,
wrk->headers_buf);
- ASSERT (rv == wrk->msg.data.headers_len);
+ ASSERT (rv == wrk->req_headers.tail_offset);
if (hcm->req_method == HTTP_REQ_POST)
{
@@ -214,22 +213,22 @@ hc_session_connected_callback (u32 app_index, u32 hc_session_index,
{
if (hcm->is_file)
http_add_header (
- &wrk->req_headers, http_header_name_token (HTTP_HEADER_CONTENT_TYPE),
+ &wrk->req_headers, HTTP_HEADER_CONTENT_TYPE,
http_content_type_token (HTTP_CONTENT_APP_OCTET_STREAM));
else
http_add_header (
- &wrk->req_headers, http_header_name_token (HTTP_HEADER_CONTENT_TYPE),
+ &wrk->req_headers, HTTP_HEADER_CONTENT_TYPE,
http_content_type_token (HTTP_CONTENT_APP_X_WWW_FORM_URLENCODED));
}
+ http_add_header (&wrk->req_headers, HTTP_HEADER_ACCEPT, "*", 1);
vec_foreach (header, hcm->custom_header)
- http_add_header (&wrk->req_headers, (const char *) header->name,
- vec_len (header->name), (const char *) header->value,
- vec_len (header->value));
-
- wrk->headers_buf = http_serialize_headers (wrk->req_headers);
- vec_free (wrk->req_headers);
+ http_add_custom_header (
+ &wrk->req_headers, (const char *) header->name, vec_len (header->name),
+ (const char *) header->value, vec_len (header->value));
+ clib_warning ("%U", format_http_bytes, wrk->headers_buf,
+ wrk->req_headers.tail_offset);
wrk->msg.method_type = hcm->req_method;
if (hcm->req_method == HTTP_REQ_POST)
wrk->msg.data.body_len = vec_len (hcm->data);
@@ -240,7 +239,7 @@ hc_session_connected_callback (u32 app_index, u32 hc_session_index,
/* request target */
wrk->msg.data.target_path_len = vec_len (hcm->target);
/* custom headers */
- wrk->msg.data.headers_len = vec_len (wrk->headers_buf);
+ wrk->msg.data.headers_len = wrk->req_headers.tail_offset;
/* total length */
wrk->msg.data.len = wrk->msg.data.target_path_len +
wrk->msg.data.headers_len + wrk->msg.data.body_len;
@@ -621,7 +620,13 @@ hc_run (vlib_main_t *vm)
num_threads = 1 /* main thread */ + vtm->n_threads;
vec_validate (hcm->wrk, num_threads - 1);
vec_foreach (wrk, hcm->wrk)
- wrk->thread_index = wrk - hcm->wrk;
+ {
+ wrk->thread_index = wrk - hcm->wrk;
+ /* 4k for headers should be enough */
+ vec_validate (wrk->headers_buf, 4095);
+ http_init_headers_ctx (&wrk->req_headers, wrk->headers_buf,
+ vec_len (wrk->headers_buf));
+ }
if ((err = hc_attach ()))
return clib_error_return (0, "http client attach: %U", format_clib_error,
diff --git a/src/plugins/hs_apps/http_client_cli.c b/src/plugins/hs_apps/http_client_cli.c
index 3c50e24c9fd..4ee3b49444c 100644
--- a/src/plugins/hs_apps/http_client_cli.c
+++ b/src/plugins/hs_apps/http_client_cli.c
@@ -16,7 +16,6 @@
#include <vnet/session/application_interface.h>
#include <vnet/session/session.h>
#include <http/http.h>
-#include <http/http_header_names.h>
#include <http/http_content_types.h>
#include <http/http_status_codes.h>
@@ -37,7 +36,6 @@ typedef struct
u32 vpp_session_index;
u64 to_recv;
u8 is_closed;
- http_header_t *req_headers;
} hcc_session_t;
typedef struct
@@ -131,9 +129,10 @@ hcc_ts_connected_callback (u32 app_index, u32 hc_index, session_t *as,
hcc_session_t *hs, *new_hs;
hcc_worker_t *wrk;
http_msg_t msg;
- u8 *headers_buf;
+ u8 *headers_buf = 0;
u32 new_hs_index;
int rv;
+ http_headers_ctx_t headers;
HCC_DBG ("ho hc_index: %d", hc_index);
@@ -157,11 +156,10 @@ hcc_ts_connected_callback (u32 app_index, u32 hc_index, session_t *as,
HCC_DBG ("new hc_index: %d", new_hs->session_index);
as->opaque = new_hs_index;
- http_add_header (&new_hs->req_headers,
- http_header_name_token (HTTP_HEADER_ACCEPT),
+ vec_validate (headers_buf, 63);
+ http_init_headers_ctx (&headers, headers_buf, vec_len (headers_buf));
+ http_add_header (&headers, HTTP_HEADER_ACCEPT,
http_content_type_token (HTTP_CONTENT_TEXT_HTML));
- headers_buf = http_serialize_headers (new_hs->req_headers);
- vec_free (new_hs->req_headers);
msg.type = HTTP_MSG_REQUEST;
msg.method_type = HTTP_REQ_GET;
@@ -170,7 +168,7 @@ hcc_ts_connected_callback (u32 app_index, u32 hc_index, session_t *as,
msg.data.target_path_len = vec_len (hcm->http_query);
/* custom headers */
msg.data.headers_offset = msg.data.target_path_len;
- msg.data.headers_len = vec_len (headers_buf);
+ msg.data.headers_len = headers.tail_offset;
/* request body */
msg.data.body_len = 0;
/* data type and total length */
@@ -180,7 +178,7 @@ hcc_ts_connected_callback (u32 app_index, u32 hc_index, session_t *as,
svm_fifo_seg_t segs[3] = { { (u8 *) &msg, sizeof (msg) },
{ hcm->http_query, vec_len (hcm->http_query) },
- { headers_buf, vec_len (headers_buf) } };
+ { headers_buf, msg.data.headers_len } };
rv = svm_fifo_enqueue_segments (as->tx_fifo, segs, 3, 0 /* allow partial */);
vec_free (headers_buf);
diff --git a/src/plugins/hs_apps/http_tps.c b/src/plugins/hs_apps/http_tps.c
index f4ef808e410..59a0309e363 100644
--- a/src/plugins/hs_apps/http_tps.c
+++ b/src/plugins/hs_apps/http_tps.c
@@ -17,7 +17,6 @@
#include <vnet/session/application_interface.h>
#include <vnet/session/session.h>
#include <http/http.h>
-#include <http/http_header_names.h>
#include <http/http_content_types.h>
#define HTS_RX_BUF_SIZE (64 << 10)
@@ -41,7 +40,8 @@ typedef struct
};
u8 *uri;
u8 *rx_buf;
- http_header_t *resp_headers;
+ http_headers_ctx_t resp_headers;
+ u8 *resp_headers_buf;
} hts_session_t;
typedef struct hts_listen_cfg_
@@ -86,6 +86,7 @@ hts_session_alloc (u32 thread_index)
pool_get_zero (htm->sessions[thread_index], hs);
hs->session_index = hs - htm->sessions[thread_index];
hs->thread_index = thread_index;
+ vec_validate (hs->resp_headers_buf, 255);
return hs;
}
@@ -111,6 +112,7 @@ hts_session_free (hts_session_t *hs)
clib_warning ("Freeing session %u", hs->session_index);
vec_free (hs->rx_buf);
+ vec_free (hs->resp_headers_buf);
if (CLIB_DEBUG)
clib_memset (hs, 0xfa, sizeof (*hs));
@@ -233,26 +235,20 @@ hts_start_send_data (hts_session_t *hs, http_status_code_t status)
{
http_msg_t msg;
session_t *ts;
- u8 *headers_buf = 0;
u32 n_segs = 1;
svm_fifo_seg_t seg[2];
int rv;
- if (vec_len (hs->resp_headers))
+ msg.data.headers_offset = 0;
+ msg.data.headers_len = 0;
+
+ if (hs->resp_headers.tail_offset)
{
- headers_buf = http_serialize_headers (hs->resp_headers);
- vec_free (hs->resp_headers);
- msg.data.headers_offset = 0;
- msg.data.headers_len = vec_len (headers_buf);
- seg[1].data = headers_buf;
+ msg.data.headers_len = hs->resp_headers.tail_offset;
+ seg[1].data = hs->resp_headers_buf;
seg[1].len = msg.data.headers_len;
n_segs = 2;
}
- else
- {
- msg.data.headers_offset = 0;
- msg.data.headers_len = 0;
- }
msg.type = HTTP_MSG_REPLY;
msg.code = status;
@@ -266,7 +262,6 @@ hts_start_send_data (hts_session_t *hs, http_status_code_t status)
ts = session_get (hs->vpp_session_index, hs->thread_index);
rv = svm_fifo_enqueue_segments (ts->tx_fifo, seg, n_segs,
0 /* allow partial */);
- vec_free (headers_buf);
ASSERT (rv == (sizeof (msg) + msg.data.headers_len));
if (!msg.data.body_len)
@@ -320,8 +315,7 @@ try_test_file (hts_session_t *hs, u8 *target)
}
}
- http_add_header (&hs->resp_headers,
- http_header_name_token (HTTP_HEADER_CONTENT_TYPE),
+ http_add_header (&hs->resp_headers, HTTP_HEADER_CONTENT_TYPE,
http_content_type_token (HTTP_CONTENT_APP_OCTET_STREAM));
hts_start_send_data (hs, HTTP_STATUS_OK);
@@ -380,9 +374,9 @@ hts_ts_rx_callback (session_t *ts)
if (hs->left_recv == 0)
{
hs->data_len = 0;
- hs->resp_headers = 0;
hs->rx_buf = 0;
-
+ http_init_headers_ctx (&hs->resp_headers, hs->resp_headers_buf,
+ vec_len (hs->resp_headers_buf));
/* Read the http message header */
rv = svm_fifo_dequeue (ts->rx_fifo, sizeof (msg), (u8 *) &msg);
ASSERT (rv == sizeof (msg));
@@ -394,8 +388,7 @@ hts_ts_rx_callback (session_t *ts)
}
if (msg.method_type != HTTP_REQ_GET && msg.method_type != HTTP_REQ_POST)
{
- http_add_header (&hs->resp_headers,
- http_header_name_token (HTTP_HEADER_ALLOW),
+ http_add_header (&hs->resp_headers, HTTP_HEADER_ALLOW,
http_token_lit ("GET, POST"));
hts_start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED);
goto done;
diff --git a/src/plugins/hs_apps/proxy.c b/src/plugins/hs_apps/proxy.c
index 38d96bbf5ac..1bcc1e85a17 100644
--- a/src/plugins/hs_apps/proxy.c
+++ b/src/plugins/hs_apps/proxy.c
@@ -63,32 +63,39 @@ proxy_session_side_ctx_get (proxy_worker_t *wrk, u32 ctx_index)
}
static_always_inline void
-proxy_send_http_resp (session_t *s, http_status_code_t sc, u8 *headers_buf)
+proxy_send_http_resp (session_t *s, http_status_code_t sc,
+ http_headers_ctx_t *headers)
{
http_msg_t msg;
int rv;
uword headers_ptr;
+ svm_fifo_seg_t seg[2];
+ u32 n_segs = 1;
ASSERT (s->thread_index == vlib_get_thread_index ());
+ msg.data.headers_len = 0;
+ if (headers)
+ {
+ msg.data.headers_len = headers->tail_offset;
+ headers_ptr = pointer_to_uword (headers->buf);
+ seg[1].data = (u8 *) &headers_ptr;
+ seg[1].len = sizeof (headers_ptr);
+ n_segs = 2;
+ }
msg.type = HTTP_MSG_REPLY;
msg.code = sc;
msg.data.type = HTTP_MSG_DATA_PTR;
- msg.data.headers_len = vec_len (headers_buf);
msg.data.len = msg.data.headers_len;
msg.data.headers_offset = 0;
msg.data.body_len = 0;
msg.data.body_offset = 0;
+ seg[0].data = (u8 *) &msg;
+ seg[0].len = sizeof (msg);
- headers_ptr = pointer_to_uword (headers_buf);
- svm_fifo_seg_t seg[2] = {
- { (u8 *) &msg, sizeof (msg) },
- { (u8 *) &headers_ptr, sizeof (headers_ptr) },
- };
-
- rv = svm_fifo_enqueue_segments (s->tx_fifo, seg, msg.data.len ? 2 : 1,
- 0 /* allow partial */);
- ASSERT (rv == (sizeof (msg) + (msg.data.len ? sizeof (headers_ptr) : 0)));
+ rv =
+ svm_fifo_enqueue_segments (s->tx_fifo, seg, n_segs, 0 /* allow partial */);
+ ASSERT (rv == (sizeof (msg) + (n_segs == 2 ? sizeof (headers_ptr) : 0)));
if (svm_fifo_set_event (s->tx_fifo))
session_program_tx_io_evt (s->handle, SESSION_IO_EVT_TX);
@@ -872,7 +879,7 @@ active_open_send_http_resp_rpc (void *arg)
session_get_from_handle (ps->ao.session_handle));
if (ao_tp == TRANSPORT_PROTO_UDP)
proxy_send_http_resp (po_s, HTTP_STATUS_SWITCHING_PROTOCOLS,
- pm->capsule_proto_header);
+ &pm->capsule_proto_header);
else
proxy_send_http_resp (po_s, HTTP_STATUS_OK, 0);
}
@@ -1469,8 +1476,6 @@ VLIB_CLI_COMMAND (proxy_create_command, static) = {
clib_error_t *
proxy_main_init (vlib_main_t * vm)
{
- http_header_t *headers = 0;
-
proxy_main_t *pm = &proxy_main;
pm->server_client_index = ~0;
pm->active_open_client_index = ~0;
@@ -1478,11 +1483,12 @@ proxy_main_init (vlib_main_t * vm)
pm->idle_timeout = 600; /* connect-proxy default idle timeout 10 minutes */
vec_validate (pm->client_sep, TRANSPORT_N_PROTOS - 1);
- http_add_header (&headers,
- http_header_name_token (HTTP_HEADER_CAPSULE_PROTOCOL),
+ vec_validate (pm->capsule_proto_header_buf, 10);
+ http_init_headers_ctx (&pm->capsule_proto_header,
+ pm->capsule_proto_header_buf,
+ vec_len (pm->capsule_proto_header_buf));
+ http_add_header (&pm->capsule_proto_header, HTTP_HEADER_CAPSULE_PROTOCOL,
http_token_lit (HTTP_BOOLEAN_TRUE));
- pm->capsule_proto_header = http_serialize_headers (headers);
- vec_free (headers);
return 0;
}
diff --git a/src/plugins/hs_apps/proxy.h b/src/plugins/hs_apps/proxy.h
index 814bebfe6cb..f26f4bf0ea2 100644
--- a/src/plugins/hs_apps/proxy.h
+++ b/src/plugins/hs_apps/proxy.h
@@ -90,7 +90,8 @@ typedef struct
u32 active_open_app_index; /**< active open index after attach */
u32 ckpair_index; /**< certkey pair index for tls */
- u8 *capsule_proto_header;
+ http_headers_ctx_t capsule_proto_header;
+ u8 *capsule_proto_header_buf;
/*
* Configuration params
diff --git a/src/plugins/hs_apps/vcl/vcl_test_protos.c b/src/plugins/hs_apps/vcl/vcl_test_protos.c
index da4b6997ec1..fd17c7b2c54 100644
--- a/src/plugins/hs_apps/vcl/vcl_test_protos.c
+++ b/src/plugins/hs_apps/vcl/vcl_test_protos.c
@@ -15,7 +15,6 @@
#include <hs_apps/vcl/vcl_test.h>
#include <http/http.h>
-#include <http/http_header_names.h>
#include <http/http_content_types.h>
typedef enum vcl_test_http_state_
@@ -1162,7 +1161,7 @@ vt_process_http_client_write_msg (vcl_test_session_t *ts, void *buf,
uint32_t nbytes)
{
http_msg_t msg;
- http_header_t *req_headers = 0;
+ http_headers_ctx_t req_headers;
u8 *headers_buf = 0;
u8 *target;
vcl_test_http_ctx_t *vcl_test_http_ctx = (vcl_test_http_ctx_t *) ts->opaque;
@@ -1207,11 +1206,11 @@ vt_process_http_client_write_msg (vcl_test_session_t *ts, void *buf,
else if (PREDICT_FALSE (vcl_test_http_ctx->test_state == VCL_TEST_HTTP_IDLE))
{
+ vec_validate (headers_buf, 63);
+ http_init_headers_ctx (&req_headers, headers_buf, vec_len (headers_buf));
http_add_header (
- &req_headers, http_header_name_token (HTTP_HEADER_CONTENT_TYPE),
+ &req_headers, HTTP_HEADER_CONTENT_TYPE,
http_content_type_token (HTTP_CONTENT_APP_OCTET_STREAM));
- headers_buf = http_serialize_headers (req_headers);
- vec_free (req_headers);
memset (&msg, 0, sizeof (http_msg_t));
msg.type = HTTP_MSG_REQUEST;
@@ -1223,7 +1222,7 @@ vt_process_http_client_write_msg (vcl_test_session_t *ts, void *buf,
/* headers */
msg.data.headers_offset = msg.data.target_path_len;
- msg.data.headers_len = vec_len (headers_buf);
+ msg.data.headers_len = req_headers.tail_offset;
/* body */
msg.data.body_offset = msg.data.headers_offset + msg.data.headers_len;
@@ -1236,7 +1235,7 @@ vt_process_http_client_write_msg (vcl_test_session_t *ts, void *buf,
vppcom_data_segment_t segs[3] = { { (u8 *) &msg, sizeof (msg) },
{ target, strlen ((char *) target) },
{ headers_buf,
- vec_len (headers_buf) } };
+ msg.data.headers_len } };
do
{
diff --git a/src/plugins/http/http.c b/src/plugins/http/http.c
index 666f45c7d8f..69b661d0611 100644
--- a/src/plugins/http/http.c
+++ b/src/plugins/http/http.c
@@ -468,14 +468,12 @@ static const char *connection_upgrade_template = "Connection: upgrade\r\n"
*/
static const char *http_get_request_template = "GET %s HTTP/1.1\r\n"
"Host: %v\r\n"
- "User-Agent: %v\r\n"
- "%s";
+ "User-Agent: %v\r\n";
static const char *http_post_request_template = "POST %s HTTP/1.1\r\n"
"Host: %v\r\n"
"User-Agent: %v\r\n"
- "Content-Length: %llu\r\n"
- "%s";
+ "Content-Length: %llu\r\n";
static u32
http_send_data (http_conn_t *hc, u8 *data, u32 length)
@@ -1368,6 +1366,76 @@ error:
return HTTP_SM_ERROR;
}
+static void
+http_write_app_headers (http_conn_t *hc, http_msg_t *msg, u8 **tx_buf)
+{
+ http_main_t *hm = &http_main;
+ session_t *as;
+ u8 *app_headers, *p, *end;
+ u32 *tmp;
+ int rv;
+
+ as = session_get_from_handle (hc->h_pa_session_handle);
+
+ /* read app header list */
+ if (msg->data.type == HTTP_MSG_DATA_PTR)
+ {
+ uword app_headers_ptr;
+ rv = svm_fifo_dequeue (as->tx_fifo, sizeof (app_headers_ptr),
+ (u8 *) &app_headers_ptr);
+ ASSERT (rv == sizeof (app_headers_ptr));
+ app_headers = uword_to_pointer (app_headers_ptr, u8 *);
+ }
+ else
+ {
+ app_headers = hm->app_header_lists[hc->c_thread_index];
+ rv = svm_fifo_dequeue (as->tx_fifo, msg->data.headers_len, app_headers);
+ ASSERT (rv == msg->data.headers_len);
+ }
+
+ /* serialize app headers to tx_buf */
+ end = app_headers + msg->data.headers_len;
+ while (app_headers < end)
+ {
+ /* custom header name? */
+ tmp = (u32 *) app_headers;
+ if (PREDICT_FALSE (*tmp & HTTP_CUSTOM_HEADER_NAME_BIT))
+ {
+ http_custom_token_t *name, *value;
+ name = (http_custom_token_t *) app_headers;
+ u32 name_len = name->len & ~HTTP_CUSTOM_HEADER_NAME_BIT;
+ app_headers += sizeof (http_custom_token_t) + name_len;
+ value = (http_custom_token_t *) app_headers;
+ app_headers += sizeof (http_custom_token_t) + value->len;
+ vec_add2 (*tx_buf, p, name_len + value->len + 4);
+ clib_memcpy (p, name->token, name_len);
+ p += name_len;
+ *p++ = ':';
+ *p++ = ' ';
+ clib_memcpy (p, value->token, value->len);
+ p += value->len;
+ *p++ = '\r';
+ *p++ = '\n';
+ }
+ else
+ {
+ http_app_header_t *header;
+ header = (http_app_header_t *) app_headers;
+ app_headers += sizeof (http_app_header_t) + header->value.len;
+ http_token_t name = { http_header_name_token (header->name) };
+ vec_add2 (*tx_buf, p, name.len + header->value.len + 4);
+ clib_memcpy (p, name.base, name.len);
+ p += name.len;
+ *p++ = ':';
+ *p++ = ' ';
+ clib_memcpy (p, header->value.token, header->value.len);
+ p += header->value.len;
+ *p++ = '\r';
+ *p++ = '\n';
+ }
+ }
+}
+
static http_sm_result_t
http_req_state_wait_app_reply (http_conn_t *hc, transport_send_params_t *sp)
{
@@ -1407,6 +1475,8 @@ http_req_state_wait_app_reply (http_conn_t *hc, transport_send_params_t *sp)
return HTTP_SM_ERROR;
}
+ response = hm->tx_bufs[hc->c_thread_index];
+ vec_reset_length (response);
/*
* Add "protocol layer" headers:
* - current time
@@ -1414,11 +1484,12 @@ http_req_state_wait_app_reply (http_conn_t *hc, transport_send_params_t *sp)
* - data length
*/
now = clib_timebase_now (&hm->timebase);
- response = format (0, http_response_template, http_status_code_str[msg.code],
- /* Date */
- format_clib_timebase_time, now,
- /* Server */
- hc->app_name);
+ response =
+ format (response, http_response_template, http_status_code_str[msg.code],
+ /* Date */
+ format_clib_timebase_time, now,
+ /* Server */
+ hc->app_name);
/* RFC9110 8.6: A server MUST NOT send Content-Length header field in a
* 2xx (Successful) response to CONNECT or with a status code of 101
@@ -1449,28 +1520,10 @@ http_req_state_wait_app_reply (http_conn_t *hc, transport_send_params_t *sp)
if (msg.data.headers_len)
{
HTTP_DBG (0, "got headers from app, len %d", msg.data.headers_len);
- if (msg.data.type == HTTP_MSG_DATA_PTR)
- {
- uword app_headers_ptr;
- rv = svm_fifo_dequeue (as->tx_fifo, sizeof (app_headers_ptr),
- (u8 *) &app_headers_ptr);
- ASSERT (rv == sizeof (app_headers_ptr));
- vec_append (response, uword_to_pointer (app_headers_ptr, u8 *));
- }
- else
- {
- u32 orig_len = vec_len (response);
- vec_resize (response, msg.data.headers_len);
- u8 *p = response + orig_len;
- rv = svm_fifo_dequeue (as->tx_fifo, msg.data.headers_len, p);
- ASSERT (rv == msg.data.headers_len);
- }
- }
- else
- {
- /* No headers from app */
- response = format (response, "\r\n");
+ http_write_app_headers (hc, &msg, &response);
}
+ /* Add empty line after headers */
+ response = format (response, "\r\n");
HTTP_DBG (3, "%v", response);
sent = http_send_data (hc, response, vec_len (response));
@@ -1478,10 +1531,8 @@ http_req_state_wait_app_reply (http_conn_t *hc, transport_send_params_t *sp)
{
clib_warning ("sending status-line and headers failed!");
sc = HTTP_STATUS_INTERNAL_ERROR;
- vec_free (response);
goto error;
}
- vec_free (response);
if (msg.data.body_len)
{
@@ -1513,6 +1564,7 @@ error:
static http_sm_result_t
http_req_state_wait_app_method (http_conn_t *hc, transport_send_params_t *sp)
{
+ http_main_t *hm = &http_main;
http_msg_t msg;
session_t *as;
u8 *target_buff = 0, *request = 0, *target;
@@ -1556,6 +1608,8 @@ http_req_state_wait_app_method (http_conn_t *hc, transport_send_params_t *sp)
target = target_buff;
}
+ request = hm->tx_bufs[hc->c_thread_index];
+ vec_reset_length (request);
/* currently we support only GET and POST method */
if (msg.method_type == HTTP_REQ_GET)
{
@@ -1569,15 +1623,13 @@ http_req_state_wait_app_method (http_conn_t *hc, transport_send_params_t *sp)
* - host
* - user agent
*/
- request = format (0, http_get_request_template,
+ request = format (request, http_get_request_template,
/* target */
target,
/* Host */
hc->host,
/* User-Agent */
- hc->app_name,
- /* Any headers from app? */
- msg.data.headers_len ? "" : "\r\n");
+ hc->app_name);
next_state = HTTP_REQ_STATE_WAIT_TRANSPORT_REPLY;
sm_result = HTTP_SM_STOP;
@@ -1595,7 +1647,7 @@ http_req_state_wait_app_method (http_conn_t *hc, transport_send_params_t *sp)
* - user agent
* - content length
*/
- request = format (0, http_post_request_template,
+ request = format (request, http_post_request_template,
/* target */
target,
/* Host */
@@ -1603,9 +1655,7 @@ http_req_state_wait_app_method (http_conn_t *hc, transport_send_params_t *sp)
/* User-Agent */
hc->app_name,
/* Content-Length */
- msg.data.body_len,
- /* Any headers from app? */
- msg.data.headers_len ? "" : "\r\n");
+ msg.data.body_len);
http_buffer_init (&hc->req.tx_buf, msg_to_buf_type[msg.data.type],
as->tx_fifo, msg.data.body_len);
@@ -1623,23 +1673,10 @@ http_req_state_wait_app_method (http_conn_t *hc, transport_send_params_t *sp)
if (msg.data.headers_len)
{
HTTP_DBG (0, "got headers from app, len %d", msg.data.headers_len);
- if (msg.data.type == HTTP_MSG_DATA_PTR)
- {
- uword app_headers_ptr;
- rv = svm_fifo_dequeue (as->tx_fifo, sizeof (app_headers_ptr),
- (u8 *) &app_headers_ptr);
- ASSERT (rv == sizeof (app_headers_ptr));
- vec_append (request, uword_to_pointer (app_headers_ptr, u8 *));
- }
- else
- {
- u32 orig_len = vec_len (request);
- vec_resize (request, msg.data.headers_len);
- u8 *p = request + orig_len;
- rv = svm_fifo_dequeue (as->tx_fifo, msg.data.headers_len, p);
- ASSERT (rv == msg.data.headers_len);
- }
+ http_write_app_headers (hc, &msg, &request);
}
+ /* Add empty line after headers */
+ request = format (request, "\r\n");
HTTP_DBG (3, "%v", request);
sent = http_send_data (hc, request, vec_len (request));
@@ -1661,7 +1698,6 @@ error:
done:
vec_free (target_buff);
- vec_free (request);
return sm_result;
}
@@ -2297,6 +2333,7 @@ http_transport_enable (vlib_main_t *vm, u8 is_en)
vec_validate (hm->wrk, num_threads - 1);
vec_validate (hm->rx_bufs, num_threads - 1);
vec_validate (hm->tx_bufs, num_threads - 1);
+ vec_validate (hm->app_header_lists, num_threads - 1);
for (i = 0; i < num_threads; i++)
{
vec_validate (hm->rx_bufs[i],
@@ -2305,6 +2342,7 @@ http_transport_enable (vlib_main_t *vm, u8 is_en)
vec_validate (hm->tx_bufs[i],
HTTP_UDP_PAYLOAD_MAX_LEN +
HTTP_UDP_PROXY_DATAGRAM_CAPSULE_OVERHEAD);
+ vec_validate (hm->app_header_lists[i], 32 << 10);
}
clib_timebase_init (&hm->timebase, 0 /* GMT */, CLIB_TIMEBASE_DAYLIGHT_NONE,
diff --git a/src/plugins/http/http.h b/src/plugins/http/http.h
index 637452e0474..d61ac0b08c7 100644
--- a/src/plugins/http/http.h
+++ b/src/plugins/http/http.h
@@ -525,6 +525,7 @@ typedef struct http_main_
u8 **rx_bufs;
u8 **tx_bufs;
+ u8 **app_header_lists;
clib_timebase_t timebase;
@@ -1135,65 +1136,72 @@ http_get_header (http_header_table_t *header_table, const char *name,
return 0;
}
-/**
- * Add header to the list.
- *
- * @param headers Header list.
- * @param name Pointer to header's name buffer.
- * @param name_len Length of the name.
- * @param value Pointer to header's value buffer.
- * @param value_len Length of the value.
- *
- * @note Headers added at protocol layer: Date, Server, Content-Length
- */
+typedef struct
+{
+ u32 len; /**< length of the header data buffer */
+ u32 tail_offset; /**< current tail in header data */
+ u8 *buf; /**< start of header data */
+} http_headers_ctx_t;
+
+typedef struct
+{
+ u32 len;
+ u8 token[0];
+} http_custom_token_t;
+
+typedef struct
+{
+ u32 name;
+ http_custom_token_t value;
+} http_app_header_t;
+
+/* Use high bit of header name length as custom header name bit. */
+#define HTTP_CUSTOM_HEADER_NAME_BIT (1 << 31)
+
always_inline void
-http_add_header (http_header_t **headers, const char *name, uword name_len,
- const char *value, uword value_len)
+http_init_headers_ctx (http_headers_ctx_t *ctx, u8 *buf, u32 len)
{
- http_header_t *header;
- vec_add2 (*headers, header, 1);
- header->name.base = (char *) name;
- header->name.len = name_len;
- header->value.base = (char *) value;
- header->value.len = value_len;
+ ctx->len = len;
+ ctx->tail_offset = 0;
+ ctx->buf = buf;
}
-/**
- * Serialize the header list.
- *
- * @param headers Header list to serialize.
- *
- * @return New vector with serialized headers.
- *
- * The caller is always responsible to free the returned vector.
- */
-always_inline u8 *
-http_serialize_headers (http_header_t *headers)
+always_inline void
+http_add_header (http_headers_ctx_t *ctx, http_header_name_t name,
+ const char *value, uword value_len)
{
- u8 *headers_buf = 0, *dst;
- u32 headers_buf_len = 2;
- http_header_t *header;
+ http_app_header_t *header;
- vec_foreach (header, headers)
- headers_buf_len += header->name.len + header->value.len + 4;
+ ASSERT ((ctx->tail_offset + sizeof (http_app_header_t) + value_len) <
+ ctx->len);
- vec_validate (headers_buf, headers_buf_len - 1);
- dst = headers_buf;
+ header = (http_app_header_t *) (ctx->buf + ctx->tail_offset);
+ header->name = (u32) name;
+ header->value.len = (u32) value_len;
+ clib_memcpy (header->value.token, (u8 *) value, value_len);
+ ctx->tail_offset += sizeof (http_app_header_t) + value_len;
+}
- vec_foreach (header, headers)
- {
- clib_memcpy (dst, header->name.base, header->name.len);
- dst += header->name.len;
- *dst++ = ':';
- *dst++ = ' ';
- clib_memcpy (dst, header->value.base, header->value.len);
- dst += header->value.len;
- *dst++ = '\r';
- *dst++ = '\n';
- }
- *dst++ = '\r';
- *dst = '\n';
- return headers_buf;
+always_inline void
+http_add_custom_header (http_headers_ctx_t *ctx, const char *name,
+ uword name_len, const char *value, uword value_len)
+{
+ http_custom_token_t *token;
+
+ ASSERT ((ctx->tail_offset + 2 * sizeof (http_custom_token_t) + name_len +
+ value_len) < ctx->len);
+
+ /* name */
+ token = (http_custom_token_t *) (ctx->buf + ctx->tail_offset);
+ token->len = (u32) name_len;
+ clib_memcpy (token->token, (u8 *) name, token->len);
+ token->len |= HTTP_CUSTOM_HEADER_NAME_BIT;
+ ctx->tail_offset += sizeof (http_custom_token_t) + name_len;
+ /* value */
+ token = (http_custom_token_t *) (ctx->buf + ctx->tail_offset);
+ token->len = (u32) value_len;
+ clib_memcpy (token->token, (u8 *) value, token->len);
+ ctx->tail_offset += sizeof (http_custom_token_t) + value_len;
}
typedef enum http_uri_host_type_
diff --git a/src/plugins/http/http_plugin.rst b/src/plugins/http/http_plugin.rst
index 55c5afc3a2d..995e55e6f0f 100644
--- a/src/plugins/http/http_plugin.rst
+++ b/src/plugins/http/http_plugin.rst
@@ -16,10 +16,10 @@ Usage
The plugin exposes following inline functions: ``http_validate_abs_path_syntax``, ``http_validate_query_syntax``,
``http_percent_decode``, ``http_path_remove_dot_segments``, ``http_build_header_table``, ``http_get_header``,
-``http_reset_header_table``, ``http_free_header_table``, ``http_add_header``, ``http_validate_target_syntax``,
-``http_serialize_headers``, ``http_parse_authority``, ``http_serialize_authority``, ``http_parse_masque_host_port``,
-``http_decap_udp_payload_datagram``, ``http_encap_udp_payload_datagram``. ``http_token_is``, ``http_token_is_case``,
-``http_token_contains``
+``http_reset_header_table``, ``http_free_header_table``, ``http_init_headers_ctx``, ``http_add_header``,
+``http_add_custom_header``, ``http_validate_target_syntax``, ``http_parse_authority``, ``http_serialize_authority``,
+``http_parse_masque_host_port``, ``http_decap_udp_payload_datagram``, ``http_encap_udp_payload_datagram``,
+``http_token_is``, ``http_token_is_case``, ``http_token_contains``
It relies on the hoststack constructs and uses ``http_msg_data_t`` data structure for passing metadata to/from applications.
@@ -253,10 +253,9 @@ Application should set following items:
* header section offset and length
* body offset and length
-Application could pass headers back to HTTP layer. Header list is created dynamically as vector of ``http_header_t``,
-where we store only pointers to buffers (zero copy).
-Well known header names are predefined.
-The list is serialized just before you send buffer to HTTP layer.
+Application could pass headers back to HTTP layer. Header list is created dynamically using ``http_headers_ctx_t``, which must be initialized with preallocated buffer.
+Well known header names are predefined and are added using ``http_add_header``, for headers with custom names use ``http_add_custom_header``.
+Header list buffer is sent buffer to HTTP layer in raw, current length is stored ``tail_offset`` member of ``http_headers_ctx_t``.
.. note::
Following headers are added at protocol layer and **MUST NOT** be set by application: Date, Server, Content-Length, Connection, Upgrade
@@ -268,18 +267,20 @@ Following example shows how to create headers section:
#include <http/http.h>
#include <http/http_header_names.h>
#include <http/http_content_types.h>
- http_header_t *resp_headers = 0;
+ http_headers_ctx_t resp_headers;
u8 *headers_buf = 0;
- http_add_header (resp_headers,
- http_header_name_token (HTTP_HEADER_CONTENT_TYPE),
+ /* allocate buffer for response header list */
+ vec_validate (headers_buf, 1023);
+ /* initialize header list context */
+ http_init_headers_ctx (&resp_headers, headers_buf, vec_len (headers_buf));
+ /* add headers to the list */
+ http_add_header (&resp_headers, HTTP_HEADER_CONTENT_TYPE,
http_content_type_token (HTTP_CONTENT_TEXT_HTML));
- http_add_header (resp_headers,
- http_header_name_token (HTTP_HEADER_CACHE_CONTROL),
+ http_add_header (&resp_headers, HTTP_HEADER_CACHE_CONTROL,
http_token_lit ("max-age=600"));
- http_add_header (resp_headers,
- http_header_name_token (HTTP_HEADER_LOCATION),
- (const char *) redirect, vec_len (redirect));
- headers_buf = http_serialize_headers (resp_headers);
+ http_add_custom_header (&resp_headers,
+ http_token_lit ("X-Frame-Options"),
+ (const char *) x_frame_opt, vec_len (x_frame_opt));
The example below show how to create and send response HTTP message metadata:
@@ -289,7 +290,7 @@ The example below show how to create and send response HTTP message metadata:
msg.type = HTTP_MSG_REPLY;
msg.code = HTTP_STATUS_MOVED
msg.data.headers_offset = 0;
- msg.data.headers_len = vec_len (headers_buf);
+ msg.data.headers_len = resp_headers.tail_offset;
msg.data.type = HTTP_MSG_DATA_INLINE;
msg.data.body_len = vec_len (tx_buf);
msg.data.body_offset = msg.data.headers_len;
@@ -298,11 +299,11 @@ The example below show how to create and send response HTTP message metadata:
rv = svm_fifo_enqueue (ts->tx_fifo, sizeof (msg), (u8 *) &msg);
ASSERT (rv == sizeof (msg));
-Next you will send your serialized headers:
+Next you will send your headers:
.. code-block:: C
- rv = svm_fifo_enqueue (ts->tx_fifo, vec_len (headers_buf), headers_buf);
+ rv = svm_fifo_enqueue (ts->tx_fifo, msg.data.headers_len, headers_buf);
ASSERT (rv == msg.data.headers_len);
vec_free (headers_buf);
@@ -377,13 +378,12 @@ The example below shows how to create headers section:
#include <http/http.h>
#include <http/http_header_names.h>
#include <http/http_content_types.h>
- http_header_t *req_headers = 0;
+ http_headers_ctx_t *req_headers;
u8 *headers_buf = 0;
- http_add_header (req_headers,
- http_header_name_token (HTTP_HEADER_ACCEPT),
+ vec_validate (headers_buf, 63);
+ http_init_headers_ctx (&eq_headers, headers_buf, vec_len (headers_buf));
+ http_add_header (req_headers, HTTP_HEADER_ACCEPT,
http_content_type_token (HTTP_CONTENT_TEXT_HTML));
- headers_buf = http_serialize_headers (req_headers);
- vec_free (hs->req_headers);
Following example shows how to set message metadata:
@@ -398,7 +398,7 @@ Following example shows how to set message metadata:
msg.data.target_path_len = vec_len (target);
/* custom headers */
msg.data.headers_offset = msg.data.target_path_len;
- msg.data.headers_len = vec_len (headers_buf);
+ msg.data.headers_len = headers.tail_offset;
/* no request body because we are doing GET request */
msg.data.body_len = 0;
/* data type and total length */
@@ -411,7 +411,7 @@ Finally application sends everything to HTTP layer:
svm_fifo_seg_t segs[3] = { { (u8 *) &msg, sizeof (msg) }, /* message metadata */
{ target, vec_len (target) }, /* request target */
- { headers_buf, vec_len (headers_buf) } }; /* serialized headers */
+ { headers_buf, msg.data.headers_len } }; /* headers */
rv = svm_fifo_enqueue_segments (as->tx_fifo, segs, 3, 0 /* allow partial */);
vec_free (headers_buf);
if (rv < 0 || rv != sizeof (msg) + msg.data.len)
diff --git a/src/plugins/http_static/http_static.h b/src/plugins/http_static/http_static.h
index 5e0654fae24..88b0002c971 100644
--- a/src/plugins/http_static/http_static.h
+++ b/src/plugins/http_static/http_static.h
@@ -53,9 +53,9 @@ typedef struct
int free_data;
/** File cache pool index */
u32 cache_pool_index;
- /** Response header list */
- http_header_t *resp_headers;
- /** Serialized headers to send */
+ /** Response header ctx */
+ http_headers_ctx_t resp_headers;
+ /** Response header buffer */
u8 *headers_buf;
} hss_session_t;
diff --git a/src/plugins/http_static/static_server.c b/src/plugins/http_static/static_server.c
index fe5718b7e0f..7c8c65bb9bd 100644
--- a/src/plugins/http_static/static_server.c
+++ b/src/plugins/http_static/static_server.c
@@ -19,7 +19,6 @@
#include <sys/stat.h>
#include <unistd.h>
-#include <http/http_header_names.h>
#include <http/http_content_types.h>
/** @file static_server.c
@@ -41,6 +40,8 @@ hss_session_alloc (u32 thread_index)
hs->session_index = hs - hsm->sessions[thread_index];
hs->thread_index = thread_index;
hs->cache_pool_index = ~0;
+ /* 1kB for headers should be enough for now */
+ vec_validate (hs->headers_buf, 1023);
return hs;
}
@@ -86,29 +87,17 @@ start_send_data (hss_session_t *hs, http_status_code_t status)
{
http_msg_t msg;
session_t *ts;
- u8 *headers_buf = 0;
u32 n_enq;
u64 to_send;
int rv;
ts = session_get (hs->vpp_session_index, hs->thread_index);
- if (vec_len (hs->resp_headers))
- {
- headers_buf = http_serialize_headers (hs->resp_headers);
- vec_free (hs->resp_headers);
- msg.data.headers_offset = 0;
- msg.data.headers_len = vec_len (headers_buf);
- }
- else
- {
- msg.data.headers_offset = 0;
- msg.data.headers_len = 0;
- }
-
msg.type = HTTP_MSG_REPLY;
msg.code = status;
msg.data.body_len = hs->data_len;
+ msg.data.headers_offset = 0;
+ msg.data.headers_len = hs->resp_headers.tail_offset;
msg.data.len = msg.data.body_len + msg.data.headers_len;
if (msg.data.len > hss_main.use_ptr_thresh)
@@ -119,7 +108,6 @@ start_send_data (hss_session_t *hs, http_status_code_t status)
if (msg.data.headers_len)
{
- hs->headers_buf = headers_buf;
uword headers = pointer_to_uword (hs->headers_buf);
rv =
svm_fifo_enqueue (ts->tx_fifo, sizeof (headers), (u8 *) &headers);
@@ -144,9 +132,9 @@ start_send_data (hss_session_t *hs, http_status_code_t status)
if (msg.data.headers_len)
{
- rv = svm_fifo_enqueue (ts->tx_fifo, vec_len (headers_buf), headers_buf);
+ rv =
+ svm_fifo_enqueue (ts->tx_fifo, msg.data.headers_len, hs->headers_buf);
ASSERT (rv == msg.data.headers_len);
- vec_free (headers_buf);
}
if (!msg.data.body_len)
@@ -187,11 +175,8 @@ hss_session_send_data (hss_url_handler_args_t *args)
/* Set content type only if we have some response data */
if (hs->data_len)
- {
- http_add_header (&hs->resp_headers,
- http_header_name_token (HTTP_HEADER_CONTENT_TYPE),
- http_content_type_token (args->ct));
- }
+ http_add_header (&hs->resp_headers, HTTP_HEADER_CONTENT_TYPE,
+ http_content_type_token (args->ct));
start_send_data (hs, args->sc);
}
@@ -320,11 +305,8 @@ try_url_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
/* Set content type only if we have some response data */
if (hs->data_len)
- {
- http_add_header (&hs->resp_headers,
- http_header_name_token (HTTP_HEADER_CONTENT_TYPE),
- http_content_type_token (args.ct));
- }
+ http_add_header (&hs->resp_headers, HTTP_HEADER_CONTENT_TYPE,
+ http_content_type_token (args.ct));
start_send_data (hs, sc);
@@ -401,10 +383,9 @@ try_index_file (hss_main_t *hsm, hss_session_t *hs, u8 *path)
vec_free (port_str);
- http_add_header (&hs->resp_headers,
- http_header_name_token (HTTP_HEADER_LOCATION),
+ http_add_header (&hs->resp_headers, HTTP_HEADER_LOCATION,
(const char *) redirect, vec_len (redirect));
- hs->data = redirect; /* TODO: find better way */
+ vec_free (redirect);
hs->data_len = 0;
hs->free_data = 1;
@@ -479,16 +460,15 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
/* Set following headers only for happy path:
* Content-Type
* Cache-Control max-age
+ * Last-Modified
*/
type = content_type_from_request (target);
- http_add_header (&hs->resp_headers,
- http_header_name_token (HTTP_HEADER_CONTENT_TYPE),
+ http_add_header (&hs->resp_headers, HTTP_HEADER_CONTENT_TYPE,
http_content_type_token (type));
- http_add_header (
- &hs->resp_headers, http_header_name_token (HTTP_HEADER_CACHE_CONTROL),
- (const char *) hsm->max_age_formatted, vec_len (hsm->max_age_formatted));
- http_add_header (&hs->resp_headers,
- http_header_name_token (HTTP_HEADER_LAST_MODIFIED),
+ http_add_header (&hs->resp_headers, HTTP_HEADER_CACHE_CONTROL,
+ (const char *) hsm->max_age_formatted,
+ vec_len (hsm->max_age_formatted));
+ http_add_header (&hs->resp_headers, HTTP_HEADER_LAST_MODIFIED,
(const char *) last_modified, vec_len (last_modified));
done:
@@ -529,8 +509,8 @@ hss_ts_rx_callback (session_t *ts)
if (hs->free_data)
vec_free (hs->data);
hs->data = 0;
- hs->resp_headers = 0;
- vec_free (hs->headers_buf);
+ http_init_headers_ctx (&hs->resp_headers, hs->headers_buf,
+ vec_len (hs->headers_buf));
/* Read the http message header */
rv = svm_fifo_dequeue (ts->rx_fifo, sizeof (msg), (u8 *) &msg);
@@ -539,8 +519,7 @@ hss_ts_rx_callback (session_t *ts)
if (msg.type != HTTP_MSG_REQUEST ||
(msg.method_type != HTTP_REQ_GET && msg.method_type != HTTP_REQ_POST))
{
- http_add_header (&hs->resp_headers,
- http_header_name_token (HTTP_HEADER_ALLOW),
+ http_add_header (&hs->resp_headers, HTTP_HEADER_ALLOW,
http_token_lit ("GET, POST"));
start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED);
goto done;