picow-http 0.12.1-4-g9d4fd13
HTTP server for the Raspberry Pi PicoW
|
Data Structures | |
struct | req |
HTTP request. More... | |
Macros | |
#define | HTTP_REQ_MAX_HDRS (16) |
Maximum number of request headers. More... | |
#define | HTTP_METHODS_GET_HEAD ((1U << HTTP_METHOD_GET) | (1U << HTTP_METHOD_HEAD)) |
Bitmap for methods GET and HEAD. More... | |
#define | http_req_hdr_ltrl(req, name, val_len) http_req_hdr((req), (name), STRLEN_LTRL(name), (val_len)) |
Return the value of a request header with a literal name. More... | |
#define | http_req_hdr_eq_ltrl(req, name, val) |
Return true if a request header value is equal to a literal string. More... | |
#define | http_req_hdr_contains_ltrl(req, name, substring) |
Return true if a request header contains a literal string. More... | |
#define | http_req_cookie_ltrl(req, name, val_len) http_req_cookie((req), (name), STRLEN_LTRL(name), (val_len)) |
Return the value of a cookie whose name is a string literal. More... | |
Typedefs | |
typedef err_t(* | name_val_iter_f) (const char *name, size_t name_len, const char *val, size_t val_len, void *priv) |
Function type for name/value iterators. More... | |
Enumerations | |
enum | http_method_t { HTTP_METHOD_GET = 0 , HTTP_METHOD_HEAD , HTTP_METHOD_POST , HTTP_METHOD_PUT , HTTP_METHOD_DELETE , HTTP_METHOD_CONNECT , HTTP_METHOD_OPTIONS , HTTP_METHOD_TRACE , __HTTP_METHOD_MAX } |
Request method. More... | |
Functions | |
static struct req * | http_req (struct http *http) |
Get the current request object. More... | |
const char * | http_req_hdr (struct req *req, const char *name, size_t name_len, size_t *val_len) |
Return the value of a request header. More... | |
static const char * | http_req_hdr_str (struct req *req, const char *name, size_t *val_len) |
Return the value of a request header with a nul-terminated name. More... | |
bool | http_req_hdr_eq (struct req *req, const char *name, size_t name_len, const char *val, size_t val_len) |
Return true if a request header value is equal to a string. More... | |
bool | http_req_hdr_contains (struct req *req, const char *name, size_t name_len, const char *substring, size_t substring_len) |
Return true if a request header contains a string. More... | |
static bool | http_req_hdr_eq_str (struct req *req, const char *name, const char *val) |
Return true if a request header value is equal to a nul-terminated string. More... | |
static bool | http_req_hdr_contains_str (struct req *req, const char *name, const char *substring) |
Return true if a request header contains a nul-terminated string. More... | |
err_t | http_req_hdr_iter (struct req *req, name_val_iter_f iter_cb, void *priv) |
Iterate over request headers. More... | |
const uint8_t * | http_req_cookie (struct req *req, const char *name, size_t name_len, size_t *val_len) |
Return the value of a cookie. More... | |
static const uint8_t * | http_req_cookie_str (struct req *req, const char *name, size_t *val_len) |
Return the value of a cookie with a nul-terminated name. More... | |
err_t | http_req_cookie_iter (struct req *req, name_val_iter_f iter_cb, void *priv) |
Iterate over cooke name/value pairs. More... | |
static enum http_method_t | http_req_method (struct req *req) |
Return the request method. More... | |
static const uint8_t * | http_req_path (struct req *req, size_t *len) |
Return the path from the first request line. More... | |
static const uint8_t * | http_req_query (struct req *req, size_t *len) |
Return the request query string. More... | |
const uint8_t * | http_req_query_val (const uint8_t *query, size_t query_len, const uint8_t *name, size_t name_len, size_t *val_len) |
Return the value of a query parameter. More... | |
err_t | http_req_query_iter (const uint8_t *query, size_t len, name_val_iter_f iter_cb, void *priv) |
Iterate over query string parameter names and values. More... | |
static size_t | http_req_body_len (struct req *req) |
Return the length of the request body. More... | |
err_t | http_req_body (struct http *http, uint8_t buf[], size_t *len, size_t off) |
Copy the request body to a buffer. More... | |
err_t | http_req_body_ptr (struct http *http, const uint8_t **buf, size_t *len, size_t off) |
Get a pointer to request body contents with zero-copy. More... | |
err_t | http_req_chunk (struct http *http, uint8_t *buf, size_t *len) |
Copy the next chunk in a request body sent with chunked encdoding. More... | |
err_t | url_decode (char *const out, size_t *outlen, const char *const in, ssize_t inlen, bool plus) |
Decode a "percent-encoded" string. More... | |
Read properties of the current HTTP request.
#define HTTP_METHODS_GET_HEAD ((1U << HTTP_METHOD_GET) | (1U << HTTP_METHOD_HEAD)) |
Bitmap in which the bit positions at HTTP_METHOD_GET
and HTTP_METHOD_HEAD
are set. This is a convenience for use with register_hndlr_methods(), to register custom response handlers for the GET
and HEAD
methods and the same path.
#define http_req_cookie_ltrl | ( | req, | |
name, | |||
val_len | |||
) | http_req_cookie((req), (name), STRLEN_LTRL(name), (val_len)) |
Return the value of the cookie name
in the current request, if the Cookie
header is present and includes name
. Return NULL
if there is no Cookie
header, or if the Cookie
header does not contain name
.
name
MUST be a string literal (a compile-time constant string). Otherwise, the conditions are the same as for http_req_cookie().
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[in] | name | cookie name MUST be a string literal |
[out] | val_len | length of the returned value, if any |
name
, if foundNULL
if name
was not found, or if there is no Cookie
headerNULL
if val_len
is NULL
""
(the static constant empty string) if name
is in the Cookie
header, but its value is empty #define http_req_hdr_contains_ltrl | ( | req, | |
name, | |||
substring | |||
) |
Return true if the value of any request header identified by name
is equal to or contains substring
. name
and substring
MUST be literal strings (compile-time constant strings). Otherwise, the same conditions apply as for http_req_hdr_contains().
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[in] | name | request header name, matched case insensitively MUST be a literal string |
[in] | substring | substring to search for in header values MUST be a literal string |
#define http_req_hdr_eq_ltrl | ( | req, | |
name, | |||
val | |||
) |
Return true if the value of any request header field identified by name
is equal to val
. name
and val
MUST be literal strings (compile-time constant strings). Otherwise, the same conditions apply as for http_req_hdr_eq().
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[in] | name | request header name, matched case insensitively MUST be a literal string |
[in] | val | value to match, matched exactly MUST be a literal string |
#define http_req_hdr_ltrl | ( | req, | |
name, | |||
val_len | |||
) | http_req_hdr((req), (name), STRLEN_LTRL(name), (val_len)) |
Return a pointer to the value of the first request header field identified by name
, or NULL
if there is no such header. name
MUST be a literal string (a compile-time constant string). Otherwise identical to http_req_hdr().
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[in] | name | request header name MUST be a literal string |
[out] | val_len | on successful return, *val_len is the length of the header value0 if the header is not found |
NULL
if there is no such headerNULL
if val_len
is NULL
#define HTTP_REQ_MAX_HDRS (16) |
Maximum number of headers permitted in an HTTP request. If the server receives a request with more headers, it returns an error response with status 431 ("Request header fields too large").
The default (if HTTP_REQ_MAX_HDRS
is not previously defined) is 16. Note that most browsers usually send fewer than 10 headers.
To change the maximum, define HTTP_REQ_MAX_HDRS
, for example by #define
-ing it prior to including picow_http/http.h
, or by passing in a definition as a compile option.
typedef err_t(* name_val_iter_f) (const char *name, size_t name_len, const char *val, size_t val_len, void *priv) |
Function typedef for callbacks used in name/value iterators, such as:
The function is called for every name/value pair.
The callback must return ERR_OK
to indicate success, or any other value to indicate failure. The calling iterator returns ERR_OK
if ERR_OK
was returned for every name/value pair; on any other return value, the iterator stops and returns the value returned by the callback.
Example:
[in] | name | name (such as a request header name) |
[in] | name_len | length of name |
[in] | val | value assigned to name |
[in] | val_len | length of val may be 0 |
[in] | priv | pointer to any object, or NULL passed in as the priv argument to the iterator |
ERR_OK
on success, any other error value on failure enum http_method_t |
Enum representing HTTP request methods.
Get the object representing the current request on an HTTP connection.
Example:
[in] | http | MUST be a valid HTTP object passed into a handler function |
err_t http_req_body | ( | struct http * | http, |
uint8_t | buf[], | ||
size_t * | len, | ||
size_t | off | ||
) |
Copy the request body, if any, into buf
, wholly or partially. On invocation, set *len
to the maximum number of bytes to copy; after successful return, *len
is the number of bytes that were copied. If there is no request body, *len
is 0 after the call. The body is copied from the offset in off
; set off
to 0 to read the body from the beginning.
*len
after the call; if the request body has been partially read, http_req_body() may be called again with an appropriate value in off
to copy more bytes.http_req_body_len() may be used to determine the size of the request body. This makes it possible to dynamically allocate memory for the copied body, or to read it incrementally into small buffers, as illustrated in the example.
Example:
[in] | http | MUST be a valid HTTP object passed into a handler function |
[in] | buf | buffer into which the request body is copied |
[in,out] | len | before the call, set *len to the maximum number of bytes to copy to buf after the call, *len is the number of bytes copied, 0 if there was no request body |
[in] | off | offset in bytes from which to copy the request body |
buf
or len
is NULL
off
is greater than the size of the request body
|
inlinestatic |
Return the length of the request body as set in the Content-Length
request header, or 0 if there was no such header.
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
Content-Length
header, or 0 if there was no such header err_t http_req_body_ptr | ( | struct http * | http, |
const uint8_t ** | buf, | ||
size_t * | len, | ||
size_t | off | ||
) |
Set buf
to point to a read-only region of the request body starting at off
bytes from the beginning of the body. After the invocation, *len
is the length of the region. The resulting pointer directly addresses the message payload in the TCP stack, so that no copying is necessary.
Depending on its length, the request body may occupy more than one non-contiguous buffer in the TCP stack. In that case, *len
is set to the length of contiguous memory accessible from buf
, which may be less than the length of the body. Then additional invocations of http_req_body_ptr() are necessary to access the whole body, in which off
is set to the start of the previously unread region. http_req_body_len() can be used to get the total expected body length.
After calling http_req_body_ptr(), the contents of the buffer MAY NOT be modified.
http_req_body_ptr() only makes sense for requests sent with a Content-Length
header. If there is none, or if the length was set to 0, *len
is set to 0.
Example:
[in] | http | MUST be a valid HTTP object passed into a handler function |
[out] | buf | after a successful call, buf points to a region of the request body |
[out] | len | after a successful call, *len is the length of the region; 0 if there was no Content-Length header, or if it was set to 0 |
[in] | off | offset in bytes from the start of the request body to which a pointer is requested |
buf
or len
is NULL
off
is greater than the size of the request bodyerr_t http_req_chunk | ( | struct http * | http, |
uint8_t * | buf, | ||
size_t * | len | ||
) |
Copy the next chunk in a request body that was sent with chunked transfer encoding into buf
. On invocation, set *len
to the maximum number of bytes to copy; after successful return, *len
is the number of bytes that were copied – the length of the chunk. When there are no chunks left, *len
is 0 after the call.
Each sucessive invocation of http_req_chunk() copies the next chunk, until the zero-length chunk signals the end of the request body. After that, http_req_chunk() always sets *len
to 0.
Consider the following when using http_req_chunk():
Transfer-Encoding
is present and has the value chunked
. http_req_chunk() doesn't check for this, but will reject invalid body contents (with ERR_VAL
).Transfer-Encoding
and Content-Length
in the same request header. The HTTP standard gives the options to assume chunked encoding in such a case, or to reject the request (with status 400 "Bad Request").Example:
[in] | http | MUST be a valid HTTP object passed into a handler function |
[in] | buf | buffer into which the chunk is to be copied |
[in,out] | len | before the call, set *len to the maximum number of bytes to copy to buf after the call, *len is the number of bytes copied (the length of the chunk).0 when there are no more chunks |
buf
or len
is NULL
*len
is too small)const uint8_t * http_req_cookie | ( | struct req * | req, |
const char * | name, | ||
size_t | name_len, | ||
size_t * | val_len | ||
) |
Return the value of the cookie identified by name
in the current request header, if the Cookie
header is present and includes name
. name
does not necessarily have to be nul-terminated. Return NULL
if there is no Cookie
header, or if the Cookie
header does not contain name
.
On return, *val_len
is the length of the value. If the cookie value is double-quoted, the return value points to the double-quoted string (it is not "unquoted").
name
may be present in the Cookie
header without a value, such as the cookie foo
in foo=; bar=baz
. In that case, the return value is the static constant empty string ""
(hence the character pointed to by the return value is \0
), and *val_len
is 0. So the possibilities are:
NULL
name
is not in the Cookie
header, or there is no Cookie
header.NULL
and *val_len
> 0:name
.NULL
and *val_len
== 0:name
is in the Cookie
header, but its value is empty.\0
, for empty cookie values, is an exception. Otherwise, the returned string (when not NULL
) is not nul-terminated, and MAY NOT be modified.Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[in] | name | cookie name |
[in] | name_len | length of name |
[out] | val_len | length of the returned value, if any |
name
, if foundNULL
if name
was not found, or if there is no Cookie
headerNULL
if either of name
or val_len
is NULL
""
(the static constant empty string) if name
is in the Cookie
header, but its value is empty err_t http_req_cookie_iter | ( | struct req * | req, |
name_val_iter_f | iter_cb, | ||
void * | priv | ||
) |
Iterate over the cookies in the Cookie
request header, if any. The iter_cb
callback is invoked for each cookie name/value pair.
As with http_req_cookie()
: if there is a cookie with only a name and no value, the static empty constant string ""
is passed to the iterator in the value
parameter, and val_len
is 0. See http_req_cookie() for details.
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[in] | iter_cb | iterator callback function invoked for every request header name/value |
[in] | priv | pointer to any object, or NULL passed in as the priv argument to the callback |
ERR_OK
if each invocation of the callback returned ERR_OK
ERR_OK
value returned from the callback
|
inlinestatic |
Return the value of the cookie name
in the current request, if the Cookie
header is present and includes name
. Return NULL
if there is no Cookie
header, or if the Cookie
header does not contain name
.
name
MUST be nul-terminated. Otherwise, the conditions are the same as for http_req_cookie().
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[in] | name | cookie name MUST be nul-terminated |
[out] | val_len | length of the returned value, if any |
name
, if foundNULL
if name
was not found, or if there is no Cookie
headerNULL
if val_len
is NULL
""
(the static constant empty string) if name
is in the Cookie
header, but its value is empty const char * http_req_hdr | ( | struct req * | req, |
const char * | name, | ||
size_t | name_len, | ||
size_t * | val_len | ||
) |
Return a pointer to the value of the first request header field identified by name
, or NULL
if there is no such header. name
does not necessarily have to be nul-terminated. The header name match is case-insensitive.
After successful return, *val_len
is set to the length of the header value, or 0 if the header was not found.
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[in] | name | request header name |
[in] | name_len | length of name |
[out] | val_len | on successful return, *val_len is the length of the header value0 if the header is not found, or if name is NULL |
NULL
if there is no such headerNULL
if either of name
or val_len
is NULL
bool http_req_hdr_contains | ( | struct req * | req, |
const char * | name, | ||
size_t | name_len, | ||
const char * | substring, | ||
size_t | substring_len | ||
) |
Return true if the value of any request header identified by name
is equal to or contains substring
. name
and substring
do not necessarily have to be nul-terminated. Request header name matches are case insensitive, but the values must contain the exact substring.
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[in] | name | request header name, matched case insensitively |
[in] | name_len | length of name |
[in] | substring | substring to search for in header values |
[in] | substring_len | length of substring |
name
has a value that is identical to or contains substring
name
has a value that contains substring
, or no header matches name
, or if either of name
or substring
is NULL
|
inlinestatic |
Return true if the value of any request header identified by name
is equal to or contains substring
. name
and substring
MUST be nul-terminated. Otherwise, the same conditions apply as for http_req_hdr_contains().
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[in] | name | request header name, matched case insensitively MAY NOT be NULL , and MUST be nul-terminated |
[in] | substring | substring to search for in header values MAY NOT be NULL , and MUST be nul-terminated |
bool http_req_hdr_eq | ( | struct req * | req, |
const char * | name, | ||
size_t | name_len, | ||
const char * | val, | ||
size_t | val_len | ||
) |
Return true if the value of any request header field identified by name
is equal to val
. name
and val
do not necessarily have to be nul-terminated. Request header name matches are case insensitive. But header values are matched exactly (i.e. case sensitive).
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[in] | name | request header name, matched case insensitively |
[in] | name_len | length of name |
[in] | val | value to match, matched exactly |
[in] | val_len | length of val |
name
has a value identical to val
name
has a value equal to val
, or if there is no such header, or if either of name
or val
is NULL
|
inlinestatic |
Return true if the value of any request header field identified by name
is equal to val
. name
and val
MUST be nul-terminated. Otherwise, the same conditions apply as for http_req_hdr_eq().
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[in] | name | request header name, matched case insensitively MAY NOT be NULL , and MUST be nul-terminated |
[in] | val | value to match, matched exactly MAY NOT be NULL , and MUST be nul-terminated |
err_t http_req_hdr_iter | ( | struct req * | req, |
name_val_iter_f | iter_cb, | ||
void * | priv | ||
) |
Iterate over the headers in the current request. The iter_cb
callback is invoked for every request header name/value pair.
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[in] | iter_cb | iterator callback function invoked for every request header name/value |
[in] | priv | pointer to any object, or NULL passed in as the priv argument to the callback |
ERR_OK
if each invocation of the callback returned ERR_OK
ERR_OK
value returned from the callback
|
inlinestatic |
Return a pointer to the value of the first request header field identified by name
, or NULL
if there is no such header. name
MUST be nul-terminated. Otherwise identical to http_req_hdr().
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[in] | name | request header name MAY NOT be NULL , and MUST be nul-terminated |
[out] | val_len | on successful return, *val_len is the length of the header value0 if the header is not found |
NULL
if there is no such headerNULL
if val_len
is NULL
|
inlinestatic |
Return the request method.
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
|
inlinestatic |
Return the path sent in the first line of the request, not including any query string. For example, if the first line was GET /foo/bar?baz=quux HTTP/1.1
, this function returns a pointer to /foo/bar
. *len
is set to the length of the path.
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[out] | len | on return, *len is the length of the pathMAY NOT be NULL |
|
inlinestatic |
Return the query string sent in the request, or NULL
if none was sent. *len
is set to the length of the query string, or 0 if there was no query string.
Example:
[in] | req | req object for the current request MUST be a valid req pointer returned from http_req() |
[out] | len | on return, *len is the length of the query stringset to 0 if there was no query string MAY NOT be NULL |
NULL
if there was none err_t http_req_query_iter | ( | const uint8_t * | query, |
size_t | len, | ||
name_val_iter_f | iter_cb, | ||
void * | priv | ||
) |
Iterate over the parameter names and values in a query string, where names and values are separated by =
, and name-value pairs by &
. The query string may obtained from the URL as the string following the ?
character (see http_req_query()), or from the body of a POST request with content type application/x-www-form-urlencoded
. The iter_cb
callback is invoked for every name/value pair in the query string.
The value assigned to a query string parameter may be empty, for example the value of foo
in strings such as:
foo&bar=baz
foo=&bar=baz
If the value is empty, then the val_len
argument passed to the callback (for the length of the value) is 0. In that case, the val
argument should be ignored (it will not necessarily be NULL
).
Example:
[in] | query | query string may not be NULL |
[in] | len | length of query may not be 0 |
[in] | iter_cb | iterator callback function invoked for every query parameter name/value |
[in] | priv | pointer to any object, or NULL passed in as the priv argument to the callback |
ERR_OK
if each invocation of the callback returned ERR_OK
ERR_ARG
if query
is NULL
or len
is 0ERR_OK
value returned from the callback const uint8_t * http_req_query_val | ( | const uint8_t * | query, |
size_t | query_len, | ||
const uint8_t * | name, | ||
size_t | name_len, | ||
size_t * | val_len | ||
) |
Return the value of the first instance of parameter name
in the query string query
, or NULL
if name
is not in query
. For example, if query
contains foo=bar
, and name
is "foo"
, then http_req_query_val() returns "bar"
.
name
does not necessarily have to be nul-terminated. After successful return, *val_len
is set to the length of the value, or 0 if name
is not found.
query
may be any query string (names and values separated by =
, and name-value pairs separated by &
). It may be a query string from the request URL, as returned by http_req_query(), or the body of a POST request with content type application/x-www-form-urlencoded
.
Example:
[in] | query | query string in which to search for name |
[in] | query_len | length of query |
[in] | name | name of a parameter in query |
[in] | name_len | length of name |
[out] | val_len | on return, *val_len is the length of the returned value, or 0 if name is not found |
name
in query
NULL
if name
is not found, or if any of query
name
or val_len
is NULL
err_t url_decode | ( | char *const | out, |
size_t * | outlen, | ||
const char *const | in, | ||
ssize_t | inlen, | ||
bool | plus | ||
) |
Decode a string in the buffer in
that may be URL-encoded or "percent-encoded" (per RFC3986), saving the result in the buffer out
.
The decoding translates any sequence %XX, where XX
are two ASCII hexadecimal digits, into the byte value of XX
. If plus
is true, then it also changes any ASCII plus character +
into the ASCII space character ' ' (byte value 32). The percent character % must be encoded as %25 (its ASCII value in hex).
This makes it possible, for example, for the server to receive a query string with values coded for characters that are otherwise special in a query, such as &
and =
; or to encode non-ASCII characters in a request body.
The decoding stops at any nul byte (value 0) in the buffer. If inlen
>= 0, then at most inlen
bytes are decoded. If inlen
< 0, then the input buffer MUST contain a nul byte.
The buffers at in
and out
MAY NOT overlap (this is the condition imposed by restrict
).
Example:
[out] | out | buffer into which the decoded string is written |
[in,out] | outlen | before the call, *outlen is the size of out after successful return, *outlen is the length the decoded string in out |
[in] | in | the string to be decoded |
[in] | inlen | if >= 0, decode at most inlen bytes in in otherwise decode up to the first nul byte |
[in] | plus | if true, translate any ASCII + to ASCII ' ' (space) |
ERR_OK
on successERR_ARG
if any of in
or out
or outlen
is NULL
ERR_BUF
if out
is too small for the decoded stringERR_VAL
if the input string cannot be decoded