diff options
author | 2024-06-20 17:08:26 +0200 | |
---|---|---|
committer | 2024-07-23 15:22:34 +0000 | |
commit | 8ca6ce6fe1e65c8b57b9c0910dfd1243db0e49b9 (patch) | |
tree | da860f9fdeab192a4f90cc96c55bace986fef2a8 /src/plugins/http/http_plugin.rst | |
parent | 1f870c9bdc4f2ce4076b1faeb42878a41125fd76 (diff) |
http: return more than data from server app
Server app could return headers in front of body/data buffer.
Offers apis for building and serialization of headers section.
HTTP layer now only add Date, Server and Content-Lengths headers,
rest is up to app. Well known header names are predefined.
Type: improvement
Change-Id: If778bdfc9acf6b0d11a48f0a745a3a56c96c2436
Signed-off-by: Matus Fabian <matfabia@cisco.com>
Diffstat (limited to 'src/plugins/http/http_plugin.rst')
-rw-r--r-- | src/plugins/http/http_plugin.rst | 97 |
1 files changed, 96 insertions, 1 deletions
diff --git a/src/plugins/http/http_plugin.rst b/src/plugins/http/http_plugin.rst index c4c4d2c8234..2f7a58ef9bf 100644 --- a/src/plugins/http/http_plugin.rst +++ b/src/plugins/http/http_plugin.rst @@ -121,6 +121,7 @@ Following example shows how to parse headers: .. code-block:: C + #include <http/http_header_names.h> if (msg.data.headers_len) { u8 *headers = 0; @@ -134,7 +135,7 @@ Following example shows how to parse headers: /* your error handling */ } /* get Accept header */ - const char *accept_value = http_get_header (ht, HTTP_HEADER_ACCEPT); + const char *accept_value = http_get_header (ht, http_header_name_str (HTTP_HEADER_ACCEPT)); if (accept_value) { /* do something interesting */ @@ -154,3 +155,97 @@ Finally application reads body: rv = svm_fifo_peek (ts->rx_fifo, msg.data.body_offset, msg.data.body_len, body); ASSERT (rv == msg.data.body_len); } + +Sending data +"""""""""""""" + +When server application sends response back to HTTP layer it starts with message metadata, followed by optional serialized headers and finally body (if any). + +Application should set following items: + +* Status code +* target form +* 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. + +.. note:: + Following headers are added at protocol layer and **MUST NOT** be set by application: Date, Server, Content-Length + +Following example shows how to create headers section: + +.. code-block:: C + + #include <http/http.h> + #include <http/http_header_names.h> + #include <http/http_content_types.h> + http_header_t *resp_headers = 0; + u8 *headers_buf = 0; + http_add_header (resp_headers, + http_header_name_token (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_token_lit ("max-age=600")); + http_add_header (&hs->resp_headers, + http_header_name_token (HTTP_HEADER_LOCATION), + (const char *) redirect, vec_len (redirect)); + headers_buf = http_serialize_headers (hs->resp_headers); + +The example below show how to create and send response HTTP message metadata: + +.. code-block:: C + + http_msg_t msg; + 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.type = HTTP_MSG_DATA_INLINE; + msg.data.body_len = vec_len (tx_buf); + msg.data.body_offset = msg.data.headers_len; + msg.data.len = msg.data.body_len + msg.data.headers_len; + ts = session_get (hs->vpp_session_index, hs->thread_index); + rv = svm_fifo_enqueue (ts->tx_fifo, sizeof (msg), (u8 *) &msg); + ASSERT (rv == sizeof (msg)); + +Next you will send your serialized headers: + +.. code-block:: C + + rv = svm_fifo_enqueue (ts->tx_fifo, vec_len (headers_buf), headers_buf); + ASSERT (rv == msg.data.headers_len); + vec_free (headers_buf); + +Finally application sends response body: + +.. code-block:: C + + rv = svm_fifo_enqueue (ts->tx_fifo, vec_len (tx_buf), tx_buf); + if (rv != vec_len (hs->tx_buf)) + { + hs->tx_offset = rv; + svm_fifo_add_want_deq_ntf (ts->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF); + } + else + { + vec_free (tx_buf); + } + if (svm_fifo_set_event (ts->tx_fifo)) + session_send_io_evt_to_thread (ts->tx_fifo, SESSION_IO_EVT_TX); + +Example above shows how to send body data by copy, alternatively you could pass it as pointer: + +.. code-block:: C + + msg.data.type = HTTP_MSG_DATA_PTR; + /* code omitted for brevity */ + uword data = pointer_to_uword (tx_buf); + rv = svm_fifo_enqueue (ts->tx_fifo, sizeof (data), (u8 *) &data); + ASSERT (rv == sizeof (data)); + +In this case you need to free data when you receive next request or when session is closed. |