picow-http 0.12.1-4-g9d4fd13
HTTP server for the Raspberry Pi PicoW
Requests

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 reqhttp_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...
 

Detailed Description

Read properties of the current HTTP request.

Macro Definition Documentation

◆ HTTP_METHODS_GET_HEAD

#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.

See also
enum http_method_t, register_hndlr_methods()

◆ http_req_cookie_ltrl

#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:

err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
const unsigned char *val;
size_t val_len;
// ...
val = http_req_cookie_ltrl(req, "foo", &val_len);
if (val == NULL)
HTTP_LOG_INFO("Cookie foo not found");
else if (val_len > 0)
HTTP_LOG_INFO("Cookie foo: %.*s", val_len, val);
else
HTTP_LOG_INFO("Cookie foo found, but empty");
// ...
}
#define HTTP_LOG_INFO(...)
Log an informational message.
Definition: log.h:285
static struct req * http_req(struct http *http)
Get the current request object.
Definition: http.h:1330
#define http_req_cookie_ltrl(req, name, val_len)
Return the value of a cookie whose name is a string literal.
Definition: http.h:2012
Current HTTP connection, request and response.
HTTP request.
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[in]namecookie name
MUST be a string literal
[out]val_lenlength of the returned value, if any
Returns
value of the cookie name, if found
NULL if name was not found, or if there is no Cookie header
NULL if val_len is NULL
"" (the static constant empty string) if name is in the Cookie header, but its value is empty
See also
http_req_cookie(), http_req_cookie_str(), http_req_cookie_iter()

◆ http_req_hdr_contains_ltrl

#define http_req_hdr_contains_ltrl (   req,
  name,
  substring 
)
Value:
http_req_hdr_contains((req), (name), STRLEN_LTRL(name), (substring), \
STRLEN_LTRL(substring))
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.
#define STRLEN_LTRL(s)
Length of a literal string.
Definition: http.h:662

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:

err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
// ...
if (http_req_hdr_contains_ltrl(req, "Content-Language", "en")) {
HTTP_LOG_INFO("Language is English");
// ...
}
}
#define http_req_hdr_contains_ltrl(req, name, substring)
Return true if a request header contains a literal string.
Definition: http.h:1729
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[in]namerequest header name, matched case insensitively
MUST be a literal string
[in]substringsubstring to search for in header values
MUST be a literal string
Returns
true or false under the same conditions as http_req_hdr_contains()
See also
http_req_hdr_contains()

◆ http_req_hdr_eq_ltrl

#define http_req_hdr_eq_ltrl (   req,
  name,
  val 
)
Value:
http_req_hdr_eq((req), (name), STRLEN_LTRL(name), (val), \
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.

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:

err_t
my_handler(struct http *http, void *priv)
{
if (http_req_hdr_eq_ltrl(http, "Baz", "quux")) {
HTTP_LOG_INFO("Baz is quux");
// ...
}
}
#define http_req_hdr_eq_ltrl(req, name, val)
Return true if a request header value is equal to a literal string.
Definition: http.h:1688
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[in]namerequest header name, matched case insensitively
MUST be a literal string
[in]valvalue to match, matched exactly
MUST be a literal string
Returns
true or false under the same conditions as http_req_hdr_eq()

◆ http_req_hdr_ltrl

#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:

err_t
my_handler(struct http *http, void *p)
{
const char *host;
size_t host_len;
struct req *req = http_req(http);
host = http_req_hdr_ltrl(req, "Host", &host_len);
if (host != NULL) {
HTTP_LOG_INFO("Host is %.*s", host_len, host);
// ...
}
else {
HTTP_LOG_INFO("No Host request header");
}
}
#define http_req_hdr_ltrl(req, name, val_len)
Return the value of a request header with a literal name.
Definition: http.h:1480
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[in]namerequest header name
MUST be a literal string
[out]val_lenon successful return, *val_len is the length of the header value
0 if the header is not found
Returns
pointer to the header value, or NULL if there is no such header
NULL if val_len is NULL

◆ HTTP_REQ_MAX_HDRS

#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 Documentation

◆ name_val_iter_f

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:

// A function that satisfies the typedef
err_t
my_name_val_cb(const char *name, size_t name_len, const char *val,
size_t val_len, void *priv)
{
HTTP_LOG_INFO("%.*s: %.*s", name_len, name, val_len, val);
// ...
return ERR_OK;
}
Parameters
[in]namename (such as a request header name)
[in]name_lenlength of name
[in]valvalue assigned to name
[in]val_lenlength of val
may be 0
[in]privpointer to any object, or NULL
passed in as the priv argument to the iterator
Returns
ERR_OK on success, any other error value on failure
See also
http_req_hdr_iter(), http_req_query_iter(), lwIP err_t

Enumeration Type Documentation

◆ http_method_t

Enum representing HTTP request methods.

See also
http_req_method()
Enumerator
HTTP_METHOD_GET 

Method GET

HTTP_METHOD_HEAD 

Method HEAD

HTTP_METHOD_POST 

Method POST

HTTP_METHOD_PUT 

Method PUT

HTTP_METHOD_DELETE 

Method DELETE

HTTP_METHOD_CONNECT 

Method CONNECT

HTTP_METHOD_OPTIONS 

Method OPTIONS

HTTP_METHOD_TRACE 

Method TRACE

__HTTP_METHOD_MAX 

Symbol for the numer of methods

Function Documentation

◆ http_req()

static struct req * http_req ( struct http http)
inlinestatic

Get the object representing the current request on an HTTP connection.

Example:

err_t
my_handler(struct http *http, void *priv)
{
struct req *req;
// ...
}
Parameters
[in]httpMUST be a valid HTTP object passed into a handler function
Returns
pointer to the current request object

◆ http_req_body()

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.

Attention
http_req_body() may copy fewer bytes than requested. Check the value of *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:

#include <stdlib.h>
#include <stdint.h>
// This handler uses malloc() to allocate a buffer for the whole body.
err_t
a_handler(struct http *http, void *p)
{
uint8_t *buf;
size_t body_len, l, total;
err_t err;
struct req *req = http_req(http);
body_len = http_req_body_len(req);
l = body_len;
buf = malloc(body_len);
if (buf == NULL) {
// Error handling ...
}
err = http_req_body(http, buf, &l, 0);
if (err != ERR_OK) {
// Error handling ...
}
// If the copy was incomplete, continue copying.
total = l;
while (total < body_len) {
l = body_len - total;
err = http_req_body(http, buf + total, &l, total);
if (err != ERR_OK) {
// Error handling ...
}
total += l;
}
// The body has now been fully read and can be processed ...
}
// This handler reads the body incrementally into a limited buffer.
err_t
another_handler(struct http *http, void *p)
{
uint8_t buf[MAX_BUF];
size_t body_len, l;
err_t err;
struct req *req = http_req(http);
body_len = http_req_body_len(req);
for (size_t total = 0; total < body_len; total += l) {
l = MAX_BUF;
if ((err = http_req_body(http, buf, &l, 0)) != ERR_OK) {
// Error handling ...
}
// Process the body partially copied into buf ...
}
}
err_t http_req_body(struct http *http, uint8_t buf[], size_t *len, size_t off)
Copy the request body to a buffer.
static size_t http_req_body_len(struct req *req)
Return the length of the request body.
Definition: http.h:2407
Parameters
[in]httpMUST be a valid HTTP object passed into a handler function
[in]bufbuffer into which the request body is copied
[in,out]lenbefore 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]offoffset in bytes from which to copy the request body
Returns
ERR_OK on success
ERR_ARG if either of buf or len is NULL
ERR_VAL if off is greater than the size of the request body
ERR_BUF if the copy fails
ERR_INPROGRESS if the portion of the request body to be copied has not yet been fully received; in this case, http_req_body() may be retried, since the TCP stack is still receiving the request
See also
http_req_body_len(), http_req_body_ptr(), lwIP err_t

◆ http_req_body_len()

static size_t http_req_body_len ( struct req req)
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:

err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
size_t body_len;
// ...
body_len = http_req_body_len(req);
if (body_len != 0) {
// Read the request body ...
}
// ...
}
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
Returns
length of the request body as set in the Content-Length header, or 0 if there was no such header
See also
http_req_body(), http_req_body_ptr()

◆ http_req_body_ptr()

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:

// A custom response handler that processes the request body with
// zero copy.
err_t
no_copy_hndlr(struct http *http, void *priv)
{
struct req *req = http_req(http);
size_t req_len, off;
// Get the length of the request body.
// If http_req_body_len() returns 0, this request was sent
// without a Content-Length header (or content length 0).
// In that case, the loop below is not executed.
req_len = http_req_body_len(req);
// Process body contents in a loop.
off = 0;
while (req_len > 0) {
const uint8_t *buf;
size_t len;
err_t err;
err = http_req_body_ptr(http, &buf, &len, off);
if (err != ERR_OK) {
// Error handling ...
}
// If the call returned ERR_OK, buf is now a pointer
// to a region of length len in the request body.
// Process the buffer ...
// Count down from the total request length to determine
// when the whole body has been read. Set the offset for
// the next iteration to the previously unread portion
// of the request body.
req_len -= len;
off += len;
}
// Send a response ...
}
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.
Parameters
[in]httpMUST be a valid HTTP object passed into a handler function
[out]bufafter a successful call, buf points to a region of the request body
[out]lenafter 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]offoffset in bytes from the start of the request body to which a pointer is requested
Returns
ERR_OK on success
ERR_ARG if either of buf or len is NULL
ERR_VAL if off is greater than the size of the request body
ERR_INPROGRESS if the request body at the given offset has not yet been fully received; in this case, http_req_body_ptr() may be retried, since the TCP stack is still receiving the request
See also
http_req_body_len(), http_req_body(), lwIP err_t

◆ http_req_chunk()

err_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():

  • A conforming HTTP client only sends a request body with chunked encoding when the request header 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).
  • A conforming client will not send both 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").
  • Do not use both of http_req_chunk() and http_req_body() for the same request.

Example:

struct http *http;
// Process request body chunks in a loop.
for (;;) {
uint8_t buf[BUFLEN];
size_t len = BUFLEN;
err_t err;
// Before the call, len is the size of buf.
if ((err = http_req_chunk(http, buf, &len)) != ERR_OK) {
// Error handling ...
}
// len == 0 signals the end of the request body
if (len == 0)
break;
// If len != 0 after calling http_req_chunk(), its value is
// the length of the chunk copied into buf.
// Process the chunk ...
}
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.
Parameters
[in]httpMUST be a valid HTTP object passed into a handler function
[in]bufbuffer into which the chunk is to be copied
[in,out]lenbefore 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
Returns
ERR_OK on success
ERR_ARG if either of buf or len is NULL
ERR_VAL if the request body contents are invalid – the next bytes are not correctly formatted as a chunk
ERR_MEM if there is insufficient space for the next chunk (*len is too small)
ERR_BUF if the copy fails
ERR_INPROGRESS if the portion of the request body to be copied has not yet been fully received; in this case, http_req_chunk() may be retried, since the TCP stack is still receiving the request
See also
chunked transfer encoding, lwIP err_t

◆ http_req_cookie()

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:

  • return value is NULL
    • name is not in the Cookie header, or there is no Cookie header.
  • return value is non-NULL and *val_len > 0:
    • the return value points to the non-empty value of the cookie name.
  • return value is non-NULL and *val_len == 0:
    • name is in the Cookie header, but its value is empty.
Attention
The special case of the empty string, which starts with the nul character \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:

err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
const unsigned char *val;
size_t val_len;
// ...
val = http_req_cookie(req, "foo", 3, &val_len);
if (val == NULL)
HTTP_LOG_INFO("Cookie foo not found");
else if (val_len > 0)
HTTP_LOG_INFO("Cookie foo: %.*s", val_len, val);
else
HTTP_LOG_INFO("Cookie foo found, but empty");
// ...
}
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.
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[in]namecookie name
[in]name_lenlength of name
[out]val_lenlength of the returned value, if any
Returns
value of the cookie name, if found
NULL if name was not found, or if there is no Cookie header
NULL 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
See also
http_req_cookie_str(), http_req_cookie_ltrl(), http_req_cookie_iter()

◆ http_req_cookie_iter()

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:

// A function that satisfies typedef name_val_iter_f
err_t
cookie_cb(const char *name, size_t name_len, const char *val,
size_t val_len, void *priv)
{
// ...
if (val_len != NULL)
HTTP_LOG_INFO("Cookie %.*s: %.*s", name_len, name,
val_len, val);
else
HTTP_LOG_INFO("Cookie %.*s found, but empty",
name_len, name);
// ...
return ERR_OK;
}
err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
// ...
if (http_req_cookie_iter(req, cookie_cb, NULL) != ERR_OK) {
// Error handling ...
}
// ...
}
err_t http_req_cookie_iter(struct req *req, name_val_iter_f iter_cb, void *priv)
Iterate over cooke name/value pairs.
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[in]iter_cbiterator callback function
invoked for every request header name/value
[in]privpointer to any object, or NULL
passed in as the priv argument to the callback
Returns
ERR_OK if each invocation of the callback returned ERR_OK
otherwise, the non-ERR_OK value returned from the callback
See also
name_val_iter_f, http_req_cookie(), http_req_cookie_str(), http_req_cookie_ltrl(), lwIP err_t

◆ http_req_cookie_str()

static const uint8_t * http_req_cookie_str ( struct req req,
const char *  name,
size_t *  val_len 
)
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:

err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
const char *name = "foo";
const unsigned char *val;
size_t val_len;
// ...
val = http_req_cookie_str(req, name, &val_len);
if (val == NULL)
HTTP_LOG_INFO("Cookie %s not found", name);
else if (val_len > 0)
HTTP_LOG_INFO("Cookie %s: %.*s", name, val_len, val);
else
HTTP_LOG_INFO("Cookie %s found, but empty", name);
// ...
}
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.
Definition: http.h:1957
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[in]namecookie name
MUST be nul-terminated
[out]val_lenlength of the returned value, if any
Returns
value of the cookie name, if found
NULL if name was not found, or if there is no Cookie header
NULL if val_len is NULL
"" (the static constant empty string) if name is in the Cookie header, but its value is empty
See also
http_req_cookie(), http_req_cookie_ltrl(), http_req_cookie_iter()

◆ http_req_hdr()

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.

Attention
The header value is not nul-terminated, and MAY NOT be modified.

Example:

err_t
my_handler(struct http *http, void *p)
{
const char *type;
size_t type_len;
struct req *req = http_req(http);
type = http_req_hdr(req, "Content-Type", 12, &type_len);
if (type != NULL) {
HTTP_LOG_INFO("Content-Type is %.*s", type_len, type);
// ...
}
else {
HTTP_LOG_INFO("No Content-Type request header");
}
}
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.
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[in]namerequest header name
[in]name_lenlength of name
[out]val_lenon successful return, *val_len is the length of the header value
0 if the header is not found, or if name is NULL
Returns
pointer to the header value, or NULL if there is no such header
NULL if either of name or val_len is NULL

◆ http_req_hdr_contains()

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:

err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
if (http_req_hdr_contains(req, "User-Agent", 10, "Mozilla", 7)) {
HTTP_LOG_INFO("User-Agent contains Mozilla");
// ...
}
}
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[in]namerequest header name, matched case insensitively
[in]name_lenlength of name
[in]substringsubstring to search for in header values
[in]substring_lenlength of substring
Returns
true if any request header matching name has a value that is identical to or contains substring
false if no header matching name has a value that contains substring, or no header matches name, or if either of name or substring is NULL

◆ http_req_hdr_contains_str()

static bool http_req_hdr_contains_str ( struct req req,
const char *  name,
const char *  substring 
)
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:

err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
const char *hdr = "Content-Language", *len = "en";
// ...
if (http_req_hdr_contains_str(req, hdr, len)) {
HTTP_LOG_INFO("Language is English");
// ...
}
}
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.
Definition: http.h:1647
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[in]namerequest header name, matched case insensitively
MAY NOT be NULL, and MUST be nul-terminated
[in]substringsubstring to search for in header values
MAY NOT be NULL, and MUST be nul-terminated
Returns
true or false under the same conditions as http_req_hdr_contains()
See also
http_req_hdr_contains()

◆ http_req_hdr_eq()

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:

err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
// Matches request header "Foo" or "foo", etc.
if (http_req_hdr_eq(req, "Foo", 3, "bar", 3)) {
HTTP_LOG_INFO("Foo is bar");
// ...
}
}
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[in]namerequest header name, matched case insensitively
[in]name_lenlength of name
[in]valvalue to match, matched exactly
[in]val_lenlength of val
Returns
true if any request header matching name has a value identical to val
false if no header matching name has a value equal to val, or if there is no such header, or if either of name or val is NULL

◆ http_req_hdr_eq_str()

static bool http_req_hdr_eq_str ( struct req req,
const char *  name,
const char *  val 
)
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:

err_t
my_handler(struct http *http, void *priv)
{
const char *hdr = "Baz", *val = "quux";
if (http_req_hdr_eq_str(http, hdr, val)) {
HTTP_LOG_INFO("Baz is quux");
// ...
}
}
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.
Definition: http.h:1603
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[in]namerequest header name, matched case insensitively
MAY NOT be NULL, and MUST be nul-terminated
[in]valvalue to match, matched exactly
MAY NOT be NULL, and MUST be nul-terminated
Returns
true or false under the same conditions as http_req_hdr_eq()

◆ http_req_hdr_iter()

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:

// A function that satisfies typedef name_val_iter_f
err_t
my_name_val_cb(const char *name, size_t name_len, const char *val,
size_t val_len, void *priv)
{
// ...
return ERR_OK;
}
err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
// ...
if (http_req_hdr_iter(req, my_name_val_cb, NULL) != ERR_OK) {
// Error handling ...
}
// ...
}
err_t http_req_hdr_iter(struct req *req, name_val_iter_f iter_cb, void *priv)
Iterate over request headers.
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[in]iter_cbiterator callback function
invoked for every request header name/value
[in]privpointer to any object, or NULL
passed in as the priv argument to the callback
Returns
ERR_OK if each invocation of the callback returned ERR_OK
otherwise, the non-ERR_OK value returned from the callback
See also
name_val_iter_f, lwIP err_t

◆ http_req_hdr_str()

static const char * http_req_hdr_str ( struct req req,
const char *  name,
size_t *  val_len 
)
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:

err_t
my_handler(struct http *http, void *p)
{
const char *ua_name = "User-Agent", const char *ua_val;
size_t ua_len;
struct req *req = http_req(http);
ua_val = http_req_hdr_str(req, "User-Agent", &ua_len);
if (ua_val != NULL) {
HTTP_LOG_INFO("User-Agent is %.*s", ua_len, ua_val);
// ...
}
else {
HTTP_LOG_INFO("No User-Agent request header");
}
}
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.
Definition: http.h:1432
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[in]namerequest header name
MAY NOT be NULL, and MUST be nul-terminated
[out]val_lenon successful return, *val_len is the length of the header value
0 if the header is not found
Returns
pointer to the header value, or NULL if there is no such header
NULL if val_len is NULL

◆ http_req_method()

static enum http_method_t http_req_method ( struct req req)
inlinestatic

Return the request method.

Example:

err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
enum http_method_t method;
// ...
method = http_req_method(req);
if (method == HTTP_METHOD_HEAD)) {
// Return the response header only ...
}
else {
// Return the response header and body ...
}
}
#define PICOW_HTTP_ASSERT(c)
Assert that a condition is true.
Definition: assertion.h:91
http_method_t
Request method.
Definition: http.h:379
static enum http_method_t http_req_method(struct req *req)
Return the request method.
Definition: http.h:2115
@ HTTP_METHOD_HEAD
Definition: http.h:381
@ HTTP_METHOD_GET
Definition: http.h:380
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
Returns
enum value representing the method
See also
http_method_t

◆ http_req_path()

static const uint8_t * http_req_path ( struct req req,
size_t *  len 
)
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.

Attention
The returned string is not nul-terminated.

Example:

#include <stdint.h>
err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
const uint8_t *path;
size_t path_len;
// ...
path = http_req_path(req, &path_len);
HTTP_LOG_INFO("Request path %.*s", path_len, path);
// ...
}
static const uint8_t * http_req_path(struct req *req, size_t *len)
Return the path from the first request line.
Definition: http.h:2163
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[out]lenon return, *len is the length of the path
MAY NOT be NULL
Returns
the request path, not including any query string
See also
http_req_query()

◆ http_req_query()

static const uint8_t * http_req_query ( struct req req,
size_t *  len 
)
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.

Attention
The returned string is not nul-terminated.

Example:

#include <stdint.h>
err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
const uint8_t *query;
size_t query_len;
// ...
query = http_req_query(req, &query_len);
if (query != NULL)
HTTP_LOG_INFO("Query string: %.*s", query_len, query);
else
HTTP_LOG_INFO("No query string");
// ...
}
static const uint8_t * http_req_query(struct req *req, size_t *len)
Return the request query string.
Definition: http.h:2216
Parameters
[in]reqreq object for the current request
MUST be a valid req pointer returned from http_req()
[out]lenon return, *len is the length of the query string
set to 0 if there was no query string
MAY NOT be NULL
Returns
the request query string, or NULL if there was none

◆ http_req_query_iter()

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:

err_t
query_iter_cb(const char *name, size_t name_len, const char *val,
size_t val_len, void *priv)
{
if (val_len == 0)
HTTP_LOG_INFO("query parameter %.*s with no value",
name_len, name);
else
HTTP_LOG_INFO("query parameter %.*s: %.*s",
name_len, name, val_len, val);
// ...
return ERR_OK;
}
err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
const uint8_t *query;
size_t qlen;
// ...
query = http_req_query(req, &qlen);
if (qlen != 0)
if (http_req_query_iter(query, qlen, query_iter_cb, NULL)
!= ERR_OK) {
// Error handling ...
}
// ...
}
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.
Parameters
[in]queryquery string
may not be NULL
[in]lenlength of query
may not be 0
[in]iter_cbiterator callback function
invoked for every query parameter name/value
[in]privpointer to any object, or NULL
passed in as the priv argument to the callback
Returns
ERR_OK if each invocation of the callback returned ERR_OK
ERR_ARG if query is NULL or len is 0
otherwise any non-ERR_OK value returned from the callback
See also
name_val_iter_f, http_req_query(), lwIP err_t

◆ http_req_query_val()

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.

Attention
The returned string is not nul-terminated.

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:

#include <stdint.h>
err_t
my_handler(struct http *http, void *p)
{
struct req *req = http_req(http);
const uint8_t *query, *val;
size_t query_len, val_len;
// ...
query = http_req_query(req, &query_len);
if (query != NULL) {
val = http_req_query_val(query, query_len, "foo", 3,
&val_len);
if (val != NULL)
HTTP_LOG_INFO("Value of 'foo': %.*s", val_len, val);
else
HTTP_LOG_INFO("'foo' not found in the query string");
// ...
}
// ...
}
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.
Parameters
[in]queryquery string in which to search for name
[in]query_lenlength of query
[in]namename of a parameter in query
[in]name_lenlength of name
[out]val_lenon return, *val_len is the length of the returned value, or 0 if name is not found
Returns
the value of name in query
NULL if name is not found, or if any of query name or val_len is NULL
See also
http_req_query()

◆ url_decode()

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).

Attention
The resulting string is not nul-terminated; but a terminating nul character may be added as shown in the example.

Example:

#define BUFSZ (64)
// This handler decodes the request query string, if present.
err_t
decode_handler(struct http *http, void *priv)
{
struct req *req = http_req(http);
uint8_t buf[BUFSZ];
const uint8_t *query;
size_t query_len, bufsz = BUFSZ;
// ...
//
query = http_req_query(req, &query_len);
if (query != NULL) {
// query_len is now the length of the query string.
// Set the plus parameter to true to convert '+' to ' '.
// Before the call, bufsz is the size of the output buffer.
err = url_decode(buf, &bufsz, query, query_len, true);
if (err != ERR_OK) {
// ... error handling ...
}
// If the call was successful, the decoded string is in
// the output buffer buf, and bufsz is the length of the
// decoded string.
// Append a terminating nul, if there is space for it after
//formatting.
if (bufsz < BUFSZ)
buf[bufsz] = '\0';
// ...
}
// ...
}
err_t url_decode(char *const out, size_t *outlen, const char *const in, ssize_t inlen, bool plus)
Decode a "percent-encoded" string.
Parameters
[out]outbuffer into which the decoded string is written
[in,out]outlenbefore the call, *outlen is the size of out
after successful return, *outlen is the length the decoded string in out
[in]inthe string to be decoded
[in]inlenif >= 0, decode at most inlen bytes in in
otherwise decode up to the first nul byte
[in]plusif true, translate any ASCII + to ASCII ' ' (space)
Returns
ERR_OK on success
ERR_ARG if any of in or out or outlen is NULL
ERR_BUF if out is too small for the decoded string
ERR_VAL if the input string cannot be decoded
See also
lwIP err_t