1.. _http_server_interface:
2
3HTTP Server
4###########
5
6.. contents::
7    :local:
8    :depth: 2
9
10Overview
11********
12
13Zephyr provides an HTTP server library, which allows to register HTTP services
14and HTTP resources associated with those services. The server creates a listening
15socket for every registered service, and handles incoming client connections.
16It's possible to communicate over a plain TCP socket (HTTP) or a TLS socket (HTTPS).
17Both, HTTP/1.1 (RFC 2616) and HTTP/2 (RFC 9113) protocol versions are supported.
18
19The server operation is generally transparent for the application, running in a
20background thread. The application can control the server activity with
21respective API functions.
22
23Certain resource types (for example dynamic resource) provide resource-specific
24application callbacks, allowing the server to interact with the application (for
25instance provide resource content, or process request payload).
26
27Currently, the following resource types are supported:
28
29* Static resources - content defined compile-time, cannot be modified at runtime
30  (:c:enumerator:`HTTP_RESOURCE_TYPE_STATIC`).
31
32* Dynamic resources - content provided at runtime by respective application
33  callback (:c:enumerator:`HTTP_RESOURCE_TYPE_DYNAMIC`).
34
35* Websocket resources - allowing to establish Websocket connections with the
36  server (:c:enumerator:`HTTP_RESOURCE_TYPE_WEBSOCKET`).
37
38Zephyr provides a sample demonstrating HTTP(s) server operation and various
39resource types usage. See :zephyr:code-sample:`sockets-http-server` for more
40information.
41
42Server Setup
43************
44
45A few prerequisites are needed in order to enable HTTP server functionality in
46the application.
47
48First of all, the HTTP server has to be enabled in applications configuration file
49with :kconfig:option:`CONFIG_HTTP_SERVER` Kconfig option:
50
51.. code-block:: cfg
52    :caption: ``prj.conf``
53
54    CONFIG_HTTP_SERVER=y
55
56All HTTP services and HTTP resources are placed in a dedicated linker section.
57The linker section for services is predefined locally, however the application
58is responsible for defining linker sections for resources associated with
59respective services. Linker section names for resources should be prefixed with
60``http_resource_desc_``, appended with the service name.
61
62Linker sections for resources should be defined in a linker file. For example,
63for a service named ``my_service``, the linker section shall be defined as follows:
64
65.. code-block:: c
66    :caption: ``sections-rom.ld``
67
68    #include <zephyr/linker/iterable_sections.h>
69
70    ITERABLE_SECTION_ROM(http_resource_desc_my_service, Z_LINK_ITERABLE_SUBALIGN)
71
72Finally, the linker file and linker section have to be added to your application
73using CMake:
74
75.. code-block:: cmake
76    :caption: ``CMakeLists.txt``
77
78    zephyr_linker_sources(SECTIONS sections-rom.ld)
79    zephyr_linker_section(NAME http_resource_desc_my_service
80                          KVMA RAM_REGION GROUP RODATA_REGION
81                          SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN})
82
83.. note::
84
85    You need to define a separate linker section for each HTTP service
86    registered in the system.
87
88Sample Usage
89************
90
91Services
92========
93
94The application needs to define an HTTP service (or multiple services), with
95the same name as used for the linker section with :c:macro:`HTTP_SERVICE_DEFINE`
96macro:
97
98.. code-block:: c
99
100    #include <zephyr/net/http/service.h>
101
102    static uint16_t http_service_port = 80;
103
104    HTTP_SERVICE_DEFINE(my_service, "0.0.0.0", &http_service_port, 1, 10, NULL);
105
106Alternatively, an HTTPS service can be defined with
107:c:macro:`HTTPS_SERVICE_DEFINE`:
108
109.. code-block:: c
110
111    #include <zephyr/net/http/service.h>
112    #include <zephyr/net/tls_credentials.h>
113
114    #define HTTP_SERVER_CERTIFICATE_TAG 1
115
116    static uint16_t https_service_port = 443;
117    static const sec_tag_t sec_tag_list[] = {
118        HTTP_SERVER_CERTIFICATE_TAG,
119    };
120
121    HTTPS_SERVICE_DEFINE(my_service, "0.0.0.0", &https_service_port, 1, 10,
122                         NULL, sec_tag_list, sizeof(sec_tag_list));
123
124.. note::
125
126    HTTPS services rely on TLS credentials being registered in the system.
127    See :ref:`sockets_tls_credentials_subsys` for information on how to
128    configure TLS credentials in the system.
129
130Once HTTP(s) service is defined, resources can be registered for it with
131:c:macro:`HTTP_RESOURCE_DEFINE` macro.
132
133Application can enable resource wildcard support by enabling
134:kconfig:option:`CONFIG_HTTP_SERVER_RESOURCE_WILDCARD` option. When this
135option is set, then it is possible to match several incoming HTTP requests
136with just one resource handler. The `fnmatch()
137<https://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html>`__
138POSIX API function is used to match the pattern in the URL paths.
139
140Example:
141
142.. code-block:: c
143
144    HTTP_RESOURCE_DEFINE(my_resource, my_service, "/foo*", &resource_detail);
145
146This would match all URLs that start with a string ``foo``. See
147`POSIX.2 chapter 2.13
148<https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13>`__
149for pattern matching syntax description.
150
151Static resources
152================
153
154Static resource content is defined build-time and is immutable. The following
155example shows how gzip compressed webpage can be defined as a static resource
156in the application:
157
158.. code-block:: c
159
160    static const uint8_t index_html_gz[] = {
161        #include "index.html.gz.inc"
162    };
163
164    struct http_resource_detail_static index_html_gz_resource_detail = {
165        .common = {
166            .type = HTTP_RESOURCE_TYPE_STATIC,
167            .bitmask_of_supported_http_methods = BIT(HTTP_GET),
168            .content_encoding = "gzip",
169        },
170        .static_data = index_html_gz,
171        .static_data_len = sizeof(index_html_gz),
172    };
173
174    HTTP_RESOURCE_DEFINE(index_html_gz_resource, my_service, "/",
175                         &index_html_gz_resource_detail);
176
177The resource content and content encoding is application specific. For the above
178example, a gzip compressed webpage can be generated during build, by adding the
179following code to the application's ``CMakeLists.txt`` file:
180
181.. code-block:: cmake
182    :caption: ``CMakeLists.txt``
183
184    set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/)
185    set(source_file_index src/index.html)
186    generate_inc_file_for_target(app ${source_file_index} ${gen_dir}/index.html.gz.inc --gzip)
187
188where ``src/index.html`` is the location of the webpage to be compressed.
189
190Static filesystem resources
191===========================
192
193Static filesystem resource content is defined build-time and is immutable. The following
194example shows how the path can be defined as a static resource in the application:
195
196.. code-block:: c
197
198    struct http_resource_detail_static_fs static_fs_resource_detail = {
199        .common = {
200            .type                              = HTTP_RESOURCE_TYPE_STATIC_FS,
201            .bitmask_of_supported_http_methods = BIT(HTTP_GET),
202        },
203        .fs_path = "/lfs1/www",
204    };
205
206    HTTP_RESOURCE_DEFINE(static_fs_resource, my_service, "*", &static_fs_resource_detail);
207
208All files located in /lfs1/www are made available to the client. If a file is
209gzipped, .gz must be appended to the file name (e.g. index.html.gz), then the
210server delivers index.html.gz when the client requests index.html and adds gzip
211content-encoding to the HTTP header.
212
213The content type is evaluated based on the file extension. The server supports
214.html, .js, .css, .jpg, .png and .svg. More content types can be provided with the
215:c:macro:`HTTP_SERVER_CONTENT_TYPE` macro. All other files are provided with the
216content type text/html.
217
218.. code-block:: c
219
220    HTTP_SERVER_CONTENT_TYPE(json, "application/json")
221
222Dynamic resources
223=================
224
225For dynamic resource, a resource callback is registered to exchange data between
226the server and the application.
227
228The following example code shows how to register a dynamic resource with a simple
229resource handler, which echoes received data back to the client:
230
231.. code-block:: c
232
233    static int dyn_handler(struct http_client_ctx *client, enum http_data_status status,
234                           const struct http_request_ctx *request_ctx,
235                           struct http_response_ctx *response_ctx, void *user_data)
236    {
237    #define MAX_TEMP_PRINT_LEN 32
238        static char print_str[MAX_TEMP_PRINT_LEN];
239        enum http_method method = client->method;
240        static size_t processed;
241
242        __ASSERT_NO_MSG(buffer != NULL);
243
244        if (status == HTTP_SERVER_DATA_ABORTED) {
245            LOG_DBG("Transaction aborted after %zd bytes.", processed);
246            processed = 0;
247            return 0;
248        }
249
250        processed += request_ctx->data_len;
251
252        snprintf(print_str, sizeof(print_str), "%s received (%zd bytes)",
253                 http_method_str(method), request_ctx->data_len);
254        LOG_HEXDUMP_DBG(request_ctx->data, request_ctx->data_len, print_str);
255
256        if (status == HTTP_SERVER_DATA_FINAL) {
257            LOG_DBG("All data received (%zd bytes).", processed);
258            processed = 0;
259        }
260
261        /* Echo data back to client */
262        response_ctx->body = request_ctx->data;
263        response_ctx->body_len = request_ctx->data_len;
264        response_ctx->final_chunk = (status == HTTP_SERVER_DATA_FINAL);
265
266        return 0;
267    }
268
269    struct http_resource_detail_dynamic dyn_resource_detail = {
270        .common = {
271            .type = HTTP_RESOURCE_TYPE_DYNAMIC,
272            .bitmask_of_supported_http_methods =
273                BIT(HTTP_GET) | BIT(HTTP_POST),
274        },
275        .cb = dyn_handler,
276        .user_data = NULL,
277    };
278
279    HTTP_RESOURCE_DEFINE(dyn_resource, my_service, "/dynamic",
280                         &dyn_resource_detail);
281
282
283The resource callback may be called multiple times for a single request, hence
284the application should be able to keep track of the received data progress.
285
286The ``status`` field informs the application about the progress in passing
287request payload from the server to the application. As long as the status
288reports :c:enumerator:`HTTP_SERVER_DATA_MORE`, the application should expect
289more data to be provided in a consecutive callback calls.
290Once all request payload has been passed to the application, the server reports
291:c:enumerator:`HTTP_SERVER_DATA_FINAL` status. In case of communication errors
292during request processing (for example client closed the connection before
293complete payload has been received), the server reports
294:c:enumerator:`HTTP_SERVER_DATA_ABORTED`. Either of the two events indicate that
295the application shall reset any progress recorded for the resource, and await
296a new request to come. The server guarantees that the resource can only be
297accessed by single client at a time.
298
299The ``request_ctx`` parameter is used to pass request data to the application:
300
301* The ``data`` and ``data_len`` fields pass request data to the application.
302
303* The ``headers``, ``header_count`` and ``headers_status`` fields pass request
304  headers to the application, if
305  :kconfig:option:`CONFIG_HTTP_SERVER_CAPTURE_HEADERS` is enabled.
306
307The ``response_ctx`` field is used by the application to pass response data to
308the HTTP server:
309
310* The ``status`` field allows the application to send an HTTP response code. If
311  not populated, the response code will be 200 by default.
312
313* The ``headers`` and ``header_count`` fields can be used for the application to
314  send any arbitrary HTTP headers. If not populated, only Transfer-Encoding and
315  Content-Type are sent by default. The callback may override the Content-Type
316  if desired.
317
318* The ``body`` and ``body_len`` fields are used to send body data.
319
320* The ``final_chunk`` field is used to indicate that the application has no more
321  response data to send.
322
323Headers and/or response codes may only be sent in the first populated
324``response_ctx``, after which only further body data is allowed in subsequent
325callbacks.
326
327The server will call the resource callback until it provided all request data
328to the application, and the application reports there is no more data to include
329in the reply.
330
331Websocket resources
332===================
333
334Websocket resources register an application callback, which is called when a
335Websocket connection upgrade takes place. The callback is provided with a socket
336descriptor corresponding to the underlying TCP/TLS connection. Once called,
337the application takes full control over the socket, i. e. is responsible to
338release it when done.
339
340.. code-block:: c
341
342    static int ws_socket;
343    static uint8_t ws_recv_buffer[1024];
344
345    int ws_setup(int sock, void *user_data)
346    {
347        ws_socket = sock;
348        return 0;
349    }
350
351    struct http_resource_detail_websocket ws_resource_detail = {
352        .common = {
353            .type = HTTP_RESOURCE_TYPE_WEBSOCKET,
354            /* We need HTTP/1.1 Get method for upgrading */
355            .bitmask_of_supported_http_methods = BIT(HTTP_GET),
356        },
357        .cb = ws_setup,
358        .data_buffer = ws_recv_buffer,
359        .data_buffer_len = sizeof(ws_recv_buffer),
360        .user_data = NULL, /* Fill this for any user specific data */
361    };
362
363    HTTP_RESOURCE_DEFINE(ws_resource, my_service, "/", &ws_resource_detail);
364
365The above minimalistic example shows how to register a Websocket resource with
366a simple callback, used only to store the socket descriptor provided. Further
367processing of the Websocket connection is application-specific, hence outside
368of scope of this guide. See :zephyr:code-sample:`sockets-http-server` for an
369example Websocket-based echo service implementation.
370
371Accessing request headers
372=========================
373
374The application can register an interest in any specific HTTP request headers.
375These headers are then stored for each incoming request, and can be accessed
376from within a dynamic resource callback. Request headers are only included in
377the first callback for a given request, and are not passed to any subsequent
378callbacks.
379
380This feature must first be enabled with
381:kconfig:option:`CONFIG_HTTP_SERVER_CAPTURE_HEADERS` Kconfig option.
382
383Then the application can register headers to be captured, and read the values
384from within the dynamic resource callback:
385
386.. code-block:: c
387
388    HTTP_SERVER_REGISTER_HEADER_CAPTURE(capture_user_agent, "User-Agent");
389
390    static int dyn_handler(struct http_client_ctx *client, enum http_data_status status,
391                           uint8_t *buffer, size_t len, void *user_data)
392    {
393        size_t header_count = client->header_capture_ctx.count;
394        const struct http_header *headers = client->header_capture_ctx.headers;
395
396        LOG_INF("Captured %d headers with request", header_count);
397
398        for (uint32_t i = 0; i < header_count; i++) {
399            LOG_INF("Header: '%s: %s'", headers[i].name, headers[i].value);
400        }
401
402        return 0;
403    }
404
405API Reference
406*************
407
408.. doxygengroup:: http_service
409.. doxygengroup:: http_server
410