![]() |
picow-http 0.12.1-4-g9d4fd13
HTTP server for the Raspberry Pi PicoW
|
Data Structures | |
| struct | resp |
| HTTP response. More... | |
Macros | |
| #define | RESP_HDR_SMALL_BUF_SZ (512) |
| Size of "small" buffers for response headers. More... | |
| #define | RESP_HDR_LARGE_BUF_SZ (TCP_MSS) |
| Size of "large" buffers for response headers. More... | |
| #define | RESP_HDR_SMALL_POOL_SZ (MAX_CONCURRENT_CX_HINT) |
| Number of buffers in the "small" memory pool for response headers. More... | |
| #define | RESP_HDR_LARGE_POOL_SZ (RESP_HDR_SMALL_POOL_SZ / 2) |
| Number of buffers in the "large" memory pool for response headers. More... | |
| #define | http_resp_set_hdr_ltrl(resp, name, val) |
| Set a response header to a literal string. More... | |
| #define | http_resp_set_type_ltrl(resp, type) http_resp_set_type((resp), (type), STRLEN_LTRL(type)) |
| Set the Content-Type response header to a literal string. More... | |
Typedefs | |
| typedef err_t(* | hndlr_f) (struct http *http, void *priv) |
| Function type for custom response handlers. More... | |
Functions | |
| static struct resp * | http_resp (struct http *http) |
| Get the current response object. More... | |
| static err_t | http_resp_set_status (struct resp *resp, uint16_t status) |
| Set the response status code. More... | |
| static uint16_t | http_resp_status (struct resp *resp) |
| Get the response status code. More... | |
| err_t | http_resp_set_hdr (struct resp *resp, const char *name, size_t name_len, const char *val, size_t val_len) |
| Set a response header. More... | |
| static err_t | http_resp_set_hdr_str (struct resp *resp, const char *name, const char *val) |
| Set a response header to a nul-terminated string. More... | |
| static err_t | http_resp_set_type (struct resp *resp, const char *type, size_t type_len) |
| Set the Content-Type response header. More... | |
| static err_t | http_resp_set_type_str (struct resp *resp, const char *type) |
| Set the Content-Type response header to a nul-terminated string. More... | |
| err_t | http_resp_set_len (struct resp *resp, size_t len) |
| Set the Content-Length response header. More... | |
| static err_t | http_resp_set_xfer_chunked (struct resp *resp) |
| Set the Transfer-Encdoing response header to "chunked". More... | |
| err_t | http_resp_send_hdr (struct http *http) |
| Send the response header. More... | |
| err_t | http_resp_send_buf (struct http *http, const uint8_t *buf, size_t len, bool durable) |
| Send the contents of a buffer as the response body. More... | |
| err_t | http_resp_send_chunk (struct http *http, const uint8_t *buf, size_t len, bool durable) |
| Send a chunk in a chunked-encoded response body. More... | |
| static err_t | http_resp_err (struct http *http, uint16_t status) |
| Send an error response. More... | |
| err_t | register_hndlr_methods (struct server_cfg *cfg, const char *path, hndlr_f hndlr, uint8_t methods, void *priv) |
| Register a response handler for request methods and a path. More... | |
| static err_t | register_hndlr (struct server_cfg *cfg, const char *path, hndlr_f hndlr, enum http_method_t method, void *priv) |
| Register a response handler for a request method and path. More... | |
| err_t | register_default_hndlr (struct server_cfg *cfg, hndlr_f hndlr, void *priv, priv_fini_f fini) |
| Register a default response handler. More... | |
| err_t | register_error_hndlr (struct server_cfg *cfg, hndlr_f hndlr, void *priv, priv_fini_f fini) |
| Register a custom error response handler. More... | |
Set HTTP response headers and body, and send responses to the client
The API includes two functions for sending response bodies:
Content-Length response header.Transfer-Encoding: chunked.Use only one or the other of these two mechanisms to send a response body. Exactly one of Content-Length or Transfer-Encoding: chunked must be included in the response header.
Both of these functions have a boolean parameter durable to indicate whether the response contents can be queued for send without copying the buffer.
Packets containing the response contents are sent asynchronously, and are retained by the TCP stack (potentially for re-send if not acknowledged by the network peer). This process may continue after the handler calling the send function has completed. Set durable to true if the buffer passed to the function is allocated for a lifetime that persists at least until the TCP send operation is fully complete – in this case the buffer will not be copied. Set durable to false otherwise, so that the buffer is copied for the TCP stack.
For example, if the pointer to response contents points to static storage, or has been returned from malloc(), then durable may be set to true. If it points to memory on the stack, such as an array declared as a local variable within a handler, then durable MUST be false, since the TCP stack must retain a copy that persists after completion of the handler invocation.
Zero-copy send is more efficient, in terms of both RAM usage and processing time. If your application allows it, prefer sending response bodies with the durable parameter set to true.
http_resp_err() is an alternative to http_resp_send_buf() and http_resp_send_chunk() that may be used when the response status is >= 400. By default, it sends a simple, standard error response body built in to the library. Optionally, register_error_hndlr() may be used to register a custom error handler for response codes specified in the build configuration.
The response header may be sent separately from the body with http_resp_send_hdr(). If the response status has not been set (with http_resp_set_status()) before sending the header, it set to 200.
Functions that send the response body also send the header, if it has not already been sent. http_resp_send_chunk() sends the header, if needed, before sending the first chunk. Calling http_resp_send_hdr() before sending the body is not necessary (but harmless).
To use the API properly, be aware of the kinds of responses that, according to HTTP standards, may only contain a header, but no body. These are:
HEAD method.In these cases, just http_resp_send_hdr() is sufficient. If either of http_resp_send_buf() or http_resp_send_chunk() are called for such a response, a debug level message is printed to the log, the body contents are ignored, but the functions return ERR_OK. Only using a function that sends a body is a convenient way for a handler to respond to both GET and HEAD requests – the function does the right thing for HEAD requests transparently.
picow-http uses lwIP's memory pools to allocate space for response headers; no dynamic allocation for response headers takes place at runtime. This is done transparently by the library, with no requirements for the application developer. But you can configure the pools and buffer sizes, for example to lower the memory footprint, or if the application requires large headers.
Two pools are used, for "small" and "large" response headers. The assumption is that most response headers will require no more than the small size, and the large size will only be used in rare exceptions. A buffer from the small pool is always used initially; a buffer from the large pool is used if the header exceeds the small buffer size. No response header may exceed the large size. Buffers are returned to their pools after a response has been sent.
http_resp_set_hdr() and its variants fail with the ERR_MEM error code if it needs a buffer from a memory pool that is exhausted, of if the header's size exceeds the large buffer size.
The memory pools are configured by these macros, whose default values can be overridden with compile-time definitions:
| #define http_resp_set_hdr_ltrl | ( | resp, | |
| name, | |||
| val | |||
| ) |
Add a response header field named name with the value val. name and val MUST be literal strings (compile-time constant strings).
Example:
| [in] | resp | resp object for the current response MUST be a valid resp pointer obtained from http_resp() |
| [in] | name | response header name MUST be a literal string |
| [in] | val | header value MUST be a literal string |
ERR_OK on successERR_MEM if there is insufficient memory for the header | #define http_resp_set_type_ltrl | ( | resp, | |
| type | |||
| ) | http_resp_set_type((resp), (type), STRLEN_LTRL(type)) |
Add the Content-Type response header with the value type. type MUST be a literal string (compile-time constant string).
Example:
| [in] | resp | resp object for the current response MUST be a valid resp pointer obtained from http_resp() |
| [in] | type | value to set for the Content-Type header MUST be a literal string |
ERR_OK on successERR_MEM if there is insufficient memory for the header | #define RESP_HDR_LARGE_BUF_SZ (TCP_MSS) |
The maximum size in bytes for a response header. Buffers of this size are obtained from a memory pool if the header exceeds the "small" size (RESP_HDR_SMALL_BUF_SZ). By default, there are fewer buffers in the "large" pool, on the assumption that they will only rarely be necessary.
The default is the TCP maximum segment size (MSS) configured for lwIP, which in most cases is 1460 bytes. The default value can be overridden by #define-ing RESP_HDR_LARGE_BUF_SZ prior to including picow_http/http.h, or by passing in a definition as a compile option.
| #define RESP_HDR_LARGE_POOL_SZ (RESP_HDR_SMALL_POOL_SZ / 2) |
The number of buffers of size RESP_HDR_LARGE_BUF_SZ that are allocated in the "large" memory pool for response headers. The default value is half the size of the "small" pool for response headers.
The default value can be overridden by #define-ing RESP_HDR_LARGE_POOL_SZ prior to including picow_http/http.h, or by passing in a definition as a compile option.
| #define RESP_HDR_SMALL_BUF_SZ (512) |
The size in bytes of memory pool buffers that are initally used for response headers. To save memory footprint, this value is set to a small size that is sufficient for most or all response headers.
The default value can be overridden by #define-ing RESP_HDR_SMALL_BUF_SZ prior to including picow_http/http.h, or by passing in a definition as a compile option.
| #define RESP_HDR_SMALL_POOL_SZ (MAX_CONCURRENT_CX_HINT) |
The number of buffers of size RESP_HDR_SMALL_BUF_SZ that are allocated in the "small" memory pool for response headers.
The default value is set to accomodate the maximum number of concurrent connections for all of the servers (listeners) configured for the application. If the macro MAX_CONCURRENT_CX_HINT has been defined (for "max concurrent connection hint", see the documentation for the sample lwipopts.h), then the value is MAX_CONCURRENT_CX_HINT times the number of listeners. Otherwise, the likely maximum for concurrent connections is inferred from lwIP settings.
The default value can be overridden by #define-ing RESP_HDR_SMALL_POOL_SZ prior to including picow_http/http.h, or by passing in a definition as a compile option.
Function typedef for custom response handlers. Custom handlers implement a function with this signature, which is responsible for generating HTTP responses to requests received at the endpoint for which it is registered.
| [in] | http | HTTP object for the current connection. Objects representing the current request and response are accessed via http_req() and http_resp(). |
| [in] | priv | Optional pointer passed to the register functionNULL if no such object was configured |
ERR_OK on success, or an error status on failure | enum http_status_t |
Enum representing HTTP response status codes
Get the object representing the current response on an HTTP connection.
Example:
| [in] | http | MUST be a valid HTTP object passed into a handler function |
|
inlinestatic |
Initiate sending a standard error response with response code status. By default, the server sends a simple and small (but not very aesthetic) built-in response. If a custom error handler has been regsitered that is configured for status, the custom handler is called.
The header includes the field "Connection: close", and the connection to the client is closed after the response is sent.
Example:
| [in] | http | MUST be a valid HTTP object passed into a handler function |
| [in] | status | response status code MUST be >= 400 |
ERR_OK on success| err_t http_resp_send_buf | ( | struct http * | http, |
| const uint8_t * | buf, | ||
| size_t | len, | ||
| bool | durable | ||
| ) |
Initiate sending len bytes in the fixed-length buffer buf as the response body to the client. If the response header has not already been sent, it is sent as well. The contents of the response (header and) body are queued by the TCP stack, which then begins the process of sending packets over the network.
The response header Content-Length should have been set to the value of len; http_resp_set_len() does this as a convenience. The header must not include the field Transfer-Encoding: chunked.
buf may not be NULL. Set durable to true if the contents of buf can be queued for send without copying, as described above.
If the response status has not already been set, it is set to 200. After calling this function, it is no longer possible to modify any part of the response header or body.
If the properties of the response are such that it is header-only, a debug level message is issued to the log, the body is not sent, and the function returns ERR_OK.
Example:
| [in] | http | MUST be a valid HTTP object passed into a handler function |
| [in] | buf | pointer to the buffer containing the response body |
| [in] | len | number of bytes in buf to send |
| [in] | durable | set to true iff buf points to durable storage, as described above |
ERR_OK on success (the response header and/or body is queued for send)ERR_VAL if buf is NULLERR_ALREADY if sending the body has already begun| err_t http_resp_send_chunk | ( | struct http * | http, |
| const uint8_t * | buf, | ||
| size_t | len, | ||
| bool | durable | ||
| ) |
Add len bytes at buf as a chunk in a response body sent with chunked transfer encoding. Each chunk is queued for immediate send by the TCP stack. Call with len == 0 to finalize sending the response.
buf may not be NULL unless len is 0. Set durable to true if the contents of buf can be queued for send without copying, as described above.
If the response header has not already been sent, it is sent before the first chunk. If the response status has not already been set, it is set to 200. The header cannot be modified after the first chunk is sent.
Arbitrarily many chunks with len > 0 may be sent, but after an invocation with len = 0, it is no longer possible to modify the response body.
It is the programmer's responsibility to use this function in such a way that the response is successfully transmitted. Make sure that these requirements are met:
Transfer-Encoding: chunked. http_resp_set_xfer_chunked() does this as a convenience.Content-Length header must not be set.len = 0 (and no further chunks may follow).If the properties of the response are such that it is header-only, a debug level message is issued to the log, the chunk is ignored, and the function returns ERR_OK.
Example:
| [in] | http | MUST be a valid HTTP object passed into a handler function |
| [in] | buf | pointer to the buffer containing the chunk contents |
| [in] | len | number of bytes in buf to send, or 0 to finalize the response |
| [in] | durable | set to true iff buf points to durable storage, as described above |
ERR_OK on success (the chunk and if necessary the response header are queued for send)ERR_VAL if buf is NULL but len > 0| err_t http_resp_send_hdr | ( | struct http * | http | ) |
Initiate sending the response header to the client. The contents of the header are queued by the TCP stack, which then begins the process of sending packets over the network. If the response status has not already been set, it is set to 200. After calling this function, it is no longer possible to change the status or add a response header.
See Sending response headers above for notes about the use of this function.
Example:
| [in] | http | MUST be a valid HTTP object passed into a handler function |
ERR_OK on successERR_ALREADY if the header has already been sentERR_VAL if the response status is out of range (< 100 or >= 1000)ERR_MEM if there is insufficient memory to send the header | err_t http_resp_set_hdr | ( | struct resp * | resp, |
| const char * | name, | ||
| size_t | name_len, | ||
| const char * | val, | ||
| size_t | val_len | ||
| ) |
Add a response header field named name with the value val. name and val do not necessarily have to be nul-terminated.
Example:
| [in] | resp | resp object for the current response MUST be a valid resp pointer obtained from the handler |
| [in] | name | response header name |
| [in] | name_len | length of name |
| [in] | val | header value |
| [in] | val_len | length of val |
ERR_OK on successERR_VAL if either of name or val is NULLERR_MEM if there is insufficient memory for the header
|
inlinestatic |
Add a response header field named name with the value val. name and val MUST be nul-terminated.
Example:
| [in] | resp | resp object for the current response MUST be a valid resp pointer obtained from http_resp() |
| [in] | name | response header name MAY NOT be NULL, and MUST be nul-terminated |
| [in] | val | header value MAY NOT be NULL, and MUST be nul-terminated |
ERR_OK on successERR_MEM if there is insufficient memory for the header | err_t http_resp_set_len | ( | struct resp * | resp, |
| size_t | len | ||
| ) |
Add the Content-Length response header with the value len.
Example:
| [in] | resp | resp object for the current response MUST be a valid resp pointer obtained from http_resp() |
| [in] | len | value to set for the Content-Length header may not be greater than INT32_MAX |
ERR_OK on successERR_VAL if len is out of range (> INT32_MAX)ERR_MEM if there is insufficient memory for the header
|
inlinestatic |
Set the response status code. If the status is not set by the time the response header is sent , the status is set to 200 ("OK").
Example:
| [in] | resp | resp object for the current response MUST be a valid resp pointer obtained from http_resp() |
| [in] | status | response status |
status is out of range (< 100 or >= 1000)
|
inlinestatic |
Add the Content-Type response header with the value type. type does not necessarily have to be nul-terminated.
Example:
| [in] | resp | resp object for the current response MUST be a valid resp pointer obtained from http_resp() |
| [in] | type | value to set for the Content-Type header |
| [in] | type_len | length of type |
ERR_OK on successERR_VAL if type is NULLERR_MEM if there is insufficient memory for the header
|
inlinestatic |
Add the Content-Type response header with the value type. type MUST be nul-terminated.
Example:
| [in] | resp | resp object for the current response MUST be a valid resp pointer obtained from http_resp() |
| [in] | type | value to set for the Content-Type header MAY NOT be NULL, and MUST be nul-terminated |
ERR_OK on successERR_MEM if there is insufficient memory for the header
|
inlinestatic |
Add the Transfer-Encoding response header with the value "chunked". This is required for chunked transfer encoding.
Example:
| [in] | resp | resp object for the current response MUST be a valid resp pointer obtained from http_resp() |
ERR_OK on successERR_MEM if there is insufficient memory for the header
|
inlinestatic |
Get the response status code currently set for resp. This may be a status previously set with http_resp_set_status(), or the default 200 ("OK").
Example:
| [in] | resp | resp object for the current response MUST be a valid resp pointer obtained from http_resp() |
| err_t register_default_hndlr | ( | struct server_cfg * | cfg, |
| hndlr_f | hndlr, | ||
| void * | priv, | ||
| priv_fini_f | fini | ||
| ) |
Register hndlr as the default response handler for the server configured by cfg. If a default handler has been registered, it is invoked for any request whose path does not match any path specified in the static or custom elements of the build configuration. hndlr MUST have the function signature defined for hndlr_f.
A default response handler is optional. If no default handler is registered, the server returns an error response with status 404 ("Not found") for requests whose path does not match the build configuration. If a default handler is registered, it may choose to generate responses for any other path and method, and takes on the role of returning 404 responses when appropriate.
priv is an optional pointer to private data for the default handler that is passed in the priv parameter of hndlr. fini is an optional finalizer for priv. Set one or both or priv and fini to NULL if not needed; see Application private data.
Example:
| [in] | cfg | server configuration MUST be a valid configuration returned from http_cfg() or http_default_cfg() |
| [in] | hndlr | default handler function to be registered MUST satisfy typedef hndlr_f |
| [in] | priv | pointer to private data passed into the handler set to NULL if private data is not needed for the default handler |
| [in] | fini | pointer to a finalizer function for privset to NULL if not needed |
ERR_OK on successERR_VAL if either of cfg or hndlr is NULL | err_t register_error_hndlr | ( | struct server_cfg * | cfg, |
| hndlr_f | hndlr, | ||
| void * | priv, | ||
| priv_fini_f | fini | ||
| ) |
Register hndlr as the custom error response handler for the server configured by cfg, to generate responses with status codes in the 400 and 500 range. A custom error handler can only be registered if response codes were defined for it in the optional custom_error section of the build configuration (www.yaml).
The custom_error configuration specifies selected error response status codes in the range 400 to 599. If an error handler is registered, it is invoked for responses with those status codes that are to be generated by the server under various conditions, including:
custom_error, the error responses for requests whose path and method do not match any combination configured for static or custom in the build configuration (unless a default handler is registered)Accept-Encoding header does not match any encoding configured for the resourcecustom, but no handler has been registered for itA custom error handler is optional. If for any such cases the response code was not configured for a custom error handler, or if no error handler has been registered, the server generates a built-in (small but plain) error response.
Before the error handler is called, the response header Connection is added with the value close. Accordingly, the connection with the client is closed after the response is sent. The handler code does not need to add the Connection header.
priv is an optional pointer to private data for the error handler that is passed in the priv parameter of hndlr. fini is an optional finalizer for priv. Set one or both or priv and fini to NULL if not needed; see Application private data.
Example:
| [in] | cfg | server configuration MUST be a valid configuration returned from http_cfg() or http_default_cfg() |
| [in] | hndlr | error handler function to be registered MUST satisfy typedef hndlr_f |
| [in] | priv | pointer to private data passed into the handler set to NULL if private data is not needed for the error handler |
| [in] | fini | pointer to a finalizer function for privset to NULL if not needed |
ERR_OK on successERR_VAL if either of cfg or hndlr is NULLERR_ARG if custom_error did not appear in the build configuration
|
inlinestatic |
Register hndlr as the response handler for requests with method and path, for the server configued by cfg. A custom handler MUST have been configured for method and path in the build configuration. hndlr MUST have the function signature defined for hndlr_f.
A query string is not considered part of the path. So requests for method and path with any query string (or none) are directed to the handler.
register_hndlr() may be called prior to server start, so that the custom handler is immediately active for requests for which it is configured. If the server is started and requests are received for which register_hndlr() has not yet been invoked, the server sends an error response with status 501 ("Not Implemented").
priv is an optional pointer that is passed in the priv parameter of the handler, so that application code can access handler-specific data. If a priv pointer is used, ensure that it points to storage that is allocated for the lifetime of the server. See the discussion in Application private data.
Unlike other API functions that provide for private data, register_hndlr() and register_hndlr_methods() do not have a parameter for a finalizer function. If you need to de-allocate resources associated with priv, do so after calling http_srv_fini(). See the discussion in Application private data.
If the same handler should be invoked for more than one method for the same path, for example to use the same handler for GET and HEAD requests, use register_hndlr_methods(), or call register_hndlr() with each method for that path.
Example:
| [in] | cfg | server configuration MUST be a valid configuration returned from http_cfg() or http_default_cfg() |
| [in] | path | URL path for which the handler is registered query strings do not form a part of the path |
| [in] | hndlr | handler function to be registered MUST satisfy the typedef for hndlr_f |
| [in] | method | enum value representing the request method for which the handler is registered |
| [in] | priv | pointer to private data passed into the handler set to NULL if handler-specific private data is not needed |
ERR_OK on successERR_VAL if either of path or hndlr is NULL, or if method is invalid (not a valid value of enum http_method_t)ERR_ARG if no custom handler was configured for method and path at build time | err_t register_hndlr_methods | ( | struct server_cfg * | cfg, |
| const char * | path, | ||
| hndlr_f | hndlr, | ||
| uint8_t | methods, | ||
| void * | priv | ||
| ) |
Register hndlr as the response handler for requests with the methods designated in methods and the URL path, for the server configured by cfg. A custom handler MUST have been configured for path and each of the methods in the build configuration.
methods is a bit map, where the bit positions are values of enum http_method_t. For example, set bit (1U << HTTP_METHOD_GET) in methods to register hndlr for the GET method.
Otherwise, the same conditions apply as for register_hndlr().
Example:
| [in] | cfg | server configuration MUST be a valid configuration returned from http_cfg() or http_default_cfg() |
| [in] | path | URL path for which the handler is registered query strings do not form a part of the path |
| [in] | hndlr | handler function to be registered MUST satisfy the typedef for hndlr_f |
| [in] | methods | bitmap representing the request methods for which the handler is registered the bit positions are values of enum http_method_t |
| [in] | priv | pointer to private data passed into the handler set to NULL if handler-specific private data is not needed |
ERR_OK on successERR_VAL if either of path or hndlr is NULLERR_ARG if no custom handler was configured for method and path at build time