Client#
The client runs one request at a time over a kept-alive connection. See the guide for the event model.
Types#
-
type lwhttp_client_t#
Opaque HTTP client.
A client runs one request at a time and keeps the connection open between requests when possible. Several clients can run concurrently. Create with
lwhttp_client_create(), free withlwhttp_client_destroy().
-
struct lwhttp_client_config_t#
Client configuration, copied by
lwhttp_client_create().Fill it with
lwhttp_client_config_default()first, then change what you need.-
uint32_t timeout_ms#
lwIP-CE socket inactivity timeout in milliseconds, covering connect, TLS handshake and transfer. It is extended by any traffic, so it bounds silence, not total request time. 0 disables it. Default 30000.
-
size_t header_size#
Size in bytes of the buffer that holds the response header section, the line being parsed and any trailers. Each stored field takes name + value + 2 bytes and must leave 128 bytes free for chunk-size and trailer lines; responses that do not fit fail with
LWHTTP_ERR_HEADERS_TOO_LARGE. Values below 256 are raised to 256. Default 4096.
-
uint8_t max_redirects#
Maximum number of redirects followed per request; 0 delivers 3xx responses unchanged. Default 5.
-
bool keep_alive#
Reuse connections between requests to the same scheme, host and port. When false the client sends
Connection: closeand opens a new connection for every request. Default true.
-
const char *user_agent#
User-Agentsent when the request has none, orNULLto send none. The pointer is stored, not copied, so the string must outlive the client. Default"LWHTTP/" LWHTTP_VERSION_STRING.
-
uint32_t timeout_ms#
-
struct lwhttp_request_t#
A request for
lwhttp_client_request().Zero-initialise it and set at least
lwhttp_request_t.url. The struct itself and the URL string are copied; every other pointer (method, target, headers and their strings, body, body_arg) is used untilon_completeand must stay valid until then.The client adds
Host,User-Agent(unless supplied here or disabled),Content-LengthorTransfer-Encoding: chunked,Accept-Encoding: identity(unless supplied here),Expect: 100-continueandConnection: closeas needed.Content-Length: 0is sent forPOST,PUTandPATCHwithout a body.-
const char *method#
Method token, case-sensitive;
NULLmeans"GET".
-
const char *url#
Absolute
http://orhttps://URL. Userinfo and fragment are ignored;localhost,127.x.x.xand::1use lwIP-CE’s loopback interface.
-
const char *target#
Request-target sent instead of the URL’s path and query (for example
"*"or an absolute URL for a proxy), orNULL. Must not contain spaces or control characters. Only the first request uses it; redirect hops send the path and query of the redirect URL. ForCONNECTwithout a target,host:portfrom the URL is sent.
-
const lwhttp_header_t *headers#
Extra header fields, sent after the client’s own. A
Host,User-AgentorAccept-Encodingfield here replaces the client’s. A suppliedHostis dropped, and the client’s own sent instead, once a redirect leaves the original scheme, host and port.Content-LengthandTransfer-Encodingare rejected withLWHTTP_ERR_ARG; the client sets them from the body fields. SupplyingAccept-Encodingdisables the content-coding check, so compressed bodies are delivered undecoded.
-
size_t header_count#
Number of entries in
lwhttp_request_t.headers.
-
const uint8_t *body#
In-memory body of
lwhttp_request_t.body_lengthbytes, orNULL. Ignored whenlwhttp_request_t.body_readeris set. Kept for redirects that preserve the body and for automatic retries.
-
uint32_t body_length#
Body length in bytes, sent as
Content-Length. Withlwhttp_request_t.body_reader,LWHTTP_LENGTH_UNKNOWNselects a chunked upload. Ignored when neitherbodynorbody_readeris set.
-
lwhttp_body_reader_t body_reader#
Streams the body instead of
lwhttp_request_t.body, orNULL. A streamed body cannot be replayed, so such requests are never retried, and a 307/308 redirect (or a 301/302 for a method other thanPOST) is delivered to the application instead of followed.
-
void *body_arg#
Passed to
lwhttp_request_t.body_reader.
-
bool expect_continue#
Send
Expect: 100-continueand hold the body until the server answers100 Continue. If the server stays silent the body is sent on the next lwIP-CE poll tick; if a final response arrives first the body is not sent and the connection is not reused. Ignored when the body is empty.
-
const char *method#
-
typedef unsigned long (*lwhttp_body_reader_t)(void *arg, uint8_t *buf, size_t size)#
Supplies streamed request body data.
Called from
lwhttp_client_request()or from socket event processing whenever the client can send more. The reader must produce data immediately; it cannot signal “not ready”.With a known
lwhttp_request_t.body_lengththe reader is asked for at most the bytes still owed and must return between 1 andsize; returning 0 early or more thansizeaborts the request withLWHTTP_ERR_ABORTED. WithLWHTTP_LENGTH_UNKNOWNeach return value becomes one chunk, and returning 0 ends the body.- Param arg:
- Param buf:
Where to write the data.
- Param size:
Maximum number of bytes to write (at most 512).
- Return:
Number of bytes written to
buf.
-
struct lwhttp_client_handlers_t#
Application callbacks for one request.
The table is used by pointer and must stay valid until
on_complete. Every member may beNULL, and the table pointer itself may beNULL. Callbacks run from insidelwhttp_service_events()(orlwhttp_client_cancel()), never concurrently. Inside any of them the application may calllwhttp_client_cancel()orlwhttp_client_destroy(); destruction is deferred until the callback returns and no further callbacks are made.-
bool (*on_response)(lwhttp_client_t *client, void *arg)#
Called once per request when the final response head has arrived: after redirects, not for interim 1xx responses (a 101 is final). Status, version and headers are available through the client accessors.
- Param client:
The client.
- Param arg:
The
arggiven tolwhttp_client_request().- Return:
true to continue, false to abort with
LWHTTP_ERR_ABORTED.
-
bool (*on_body)(lwhttp_client_t *client, const uint8_t *data, size_t len, void *arg)#
Called with response body data as it arrives, after
on_response. Bodies of followed redirects are discarded and not reported.- Param client:
The client.
- Param data:
Body bytes; valid only during the call.
- Param len:
Number of bytes in
data.- Param arg:
The
arggiven tolwhttp_client_request().- Return:
true to continue, false to abort with
LWHTTP_ERR_ABORTED.
-
void (*on_complete)(lwhttp_client_t *client, lwhttp_error_t result, void *arg)#
Called exactly once for every request that
lwhttp_client_request()accepted, unless the client is destroyed first. It may start a new request on the same client or destroy it.- Param client:
The client.
- Param result:
LWHTTP_OKwhen a complete response was received (any status code), or the error that ended the request.- Param arg:
The
arggiven tolwhttp_client_request().
-
bool (*on_response)(lwhttp_client_t *client, void *arg)#
-
struct lwhttp_header_t#
One request header field, used in
lwhttp_request_t.headers.-
const char *name#
Field name; must be a valid token (see
lwhttp_is_token()). Must not beNULL.
-
const char *value#
Field value; must not be
NULLand must not contain control characters other than horizontal tab (so no CR or LF). Bytes 0x80 and above are allowed.
-
const char *name#
-
struct lwhttp_client_stats_t#
Counters kept by a client, read with
lwhttp_client_stats().All counters accumulate over the client’s lifetime except
lwhttp_client_stats_t.unsentandlwhttp_client_stats_t.final_state, which describe the most recently finished request.-
uint16_t connections#
Connections opened (TCP or TLS), including those for redirect hops and retries.
-
uint16_t reused#
Requests, including redirect hops, started on an already open kept-alive connection.
-
uint16_t retries#
Automatic retries. A request is retried once on a new connection when a reused connection fails before any response byte arrives, if its method is idempotent (
GET,HEAD,PUT,DELETE,OPTIONS,TRACE) and it has no body reader.
-
uint16_t redirects#
Redirects followed.
-
uint16_t write_stalls#
Times lwIP-CE refused even a small write for lack of memory; sending resumes on the next event.
-
uint32_t bytes_sent#
Bytes handed to lwIP-CE (request heads and bodies, before TLS).
-
uint32_t bytes_received#
Bytes read from lwIP-CE (response heads and bodies, after TLS).
-
uint32_t unsent#
Nonzero when the last request finished before its whole request was written: request-head and body bytes not yet sent, plus 1 if a chunked upload had not sent its last chunk.
-
uint8_t final_state#
Client state when the last request finished: 1 while connecting, 2 while exchanging data (0 if no request has finished yet).
-
uint16_t connections#
-
LWHTTP_LENGTH_UNKNOWN#
Body length meaning “not known in advance”.
Set
lwhttp_request_t.body_lengthto this value together withlwhttp_request_t.body_readerto upload the body withTransfer-Encoding: chunked. The parser likewise rejects a responseContent-Lengthof exactly 4294967295 withLWHTTP_ERR_TOO_LARGE.
Lifetime#
-
void lwhttp_client_config_default(lwhttp_client_config_t *config)#
Fill a configuration with the defaults: 30000 ms timeout, 4096-byte header buffer, 5 redirects, keep-alive on,
User-Agent: LWHTTP/<version>.- Parameters:
config – Configuration to fill.
-
lwhttp_client_t *lwhttp_client_create(const lwhttp_client_config_t *config)#
Create a client.
Allocates one block from the lwIP-CE heap of about
header_size+ 1 KB + the client struct. Each request also makes small allocations (URL copy, host name, request head) while it runs. No connection is opened until the first request.- Parameters:
config – Configuration to copy, or
NULLfor the defaults.
- Returns:
The new client, or
NULLif memory is exhausted.
-
void lwhttp_client_destroy(lwhttp_client_t *client)#
Destroy a client, closing its connection.
Safe to call at any time. A request in progress is dropped without calling
on_complete. Called from inside one of the client’s callbacks, the destruction is deferred until the callback returns and no further callbacks are made. The socket itself is freed by a laterlwhttp_service_events().- Parameters:
client – The client, or
NULL(no effect).
Requests#
-
lwhttp_error_t lwhttp_client_request(lwhttp_client_t *client, const lwhttp_request_t *request, const lwhttp_client_handlers_t *handlers, void *arg)#
Start a request. Returns immediately; the request progresses inside
lwhttp_service_events().Requests that cannot start fail synchronously and never call
on_complete. An accepted request callson_completeexactly once (unless the client is destroyed first). The client reuses its kept-alive connection when the scheme, host and port match, otherwise it connects;httpsuses lwIP-CE TLS 1.3 with SNI and certificate verification against lwIP-CE’s trust store.Redirects 301, 302, 303, 307 and 308 with a
Locationare followed up tolwhttp_client_config_t.max_redirects. 303 becomesGET(unless the method isHEAD), as do 301 and 302 forPOST; the others keep the method and body.Authorization,Proxy-Authorization,Cookieand a suppliedHostare no longer sent once a redirect leaves the original scheme, host and port.Responses with a body that uses a non-identity
Content-Encoding(unless the request suppliedAccept-Encoding) or a transfer coding other thanchunkedfail withLWHTTP_ERR_UNSUPPORTEDbeforeon_response. A101response or a 2xx answer toCONNECTcompletes the request successfully and keeps the socket forlwhttp_client_detach().- Parameters:
client – The client; must not have a request in progress. May be called from
on_complete.request – The request; copied, but see
lwhttp_request_tfor what must stay valid.handlers – Callbacks, or
NULL; must stay valid untilon_complete.arg – Passed to every handler.
- Returns:
LWHTTP_OKif the request was accepted. Otherwise, without callingon_complete:LWHTTP_ERR_ARG(NULLclient, request or URL; invalid method, target, header orUser-Agent; userContent-Length/Transfer-Encoding),LWHTTP_ERR_STATE(a request is in progress or the client is being destroyed),LWHTTP_ERR_URL(unparsable URL, or no scheme or host),LWHTTP_ERR_UNSUPPORTED(scheme nothttp/https),LWHTTP_ERR_MEM, orLWHTTP_ERR_CONNECT(lwIP-CE refused to start connecting). Failures detected after the URL was copied (URL, scheme, header and connection errors) also mark the client done with that result forlwhttp_client_result().
-
lwhttp_error_t lwhttp_client_wait(lwhttp_client_t *client)#
Block until the current request finishes, calling
lwhttp_service_events()in a loop. Handlers still run as usual. Must not be called from a client callback.- Parameters:
client – The client.
- Returns:
The request’s result (see
lwhttp_client_result()); immediately the last result if no request is in progress;LWHTTP_ERR_ARGifclientisNULL.
-
lwhttp_error_t lwhttp_client_request_sync(lwhttp_client_t *client, const lwhttp_request_t *request, const lwhttp_client_handlers_t *handlers, void *arg)#
Start a request and wait for it:
lwhttp_client_request()followed bylwhttp_client_wait(). Must not be called from a client callback.- Parameters:
client – The client.
request – The request.
handlers – Callbacks, or
NULLwhen the status and headers are enough.arg – Passed to every handler.
- Returns:
The synchronous error from
lwhttp_client_request(), or the request’s final result.
-
void lwhttp_client_cancel(lwhttp_client_t *client)#
Abort the request in progress and close its connection.
on_completeis called withLWHTTP_ERR_ABORTEDbefore this function returns. Safe to call from callbacks. No effect if no request is in progress.- Parameters:
client – The client, or
NULL.
-
void lwhttp_client_close(lwhttp_client_t *client)#
Close the idle kept-alive connection (or an upgraded connection that was not detached).
No effect while a request is in progress. The next request opens a new connection.
- Parameters:
client – The client, or
NULL.
Results#
-
bool lwhttp_client_is_done(const lwhttp_client_t *client)#
Check whether the most recent request has finished, successfully or not.
- Parameters:
client – The client.
- Returns:
true once a request has finished and until the next one starts; false before the first request, while one is in progress, or for
NULL.
-
lwhttp_error_t lwhttp_client_result(const lwhttp_client_t *client)#
Result of the most recent request.
- Parameters:
client – The client.
- Returns:
The value passed to
on_complete(or the synchronous failure after the URL was accepted);LWHTTP_OKbefore the first request or while one is in progress;LWHTTP_ERR_ARGforNULL.
-
uint16_t lwhttp_client_status(const lwhttp_client_t *client)#
Status code of the current or most recent response (the final one after redirects).
- Parameters:
client – The client.
- Returns:
Status code, or 0 if no status line has been received for this request or
clientisNULL.
-
uint8_t lwhttp_client_version(const lwhttp_client_t *client)#
Minor HTTP version of the current or most recent response.
- Parameters:
client – The client.
- Returns:
1 for HTTP/1.1, 0 for HTTP/1.0 or if no response was received or
clientisNULL.
-
const char *lwhttp_client_header(const lwhttp_client_t *client, const char *name)#
Look up a response header, ignoring case.
The store holds the fields of the final response and, after a chunked body, its trailers. Values remain valid until the next request starts or the client is destroyed.
- Parameters:
client – The client, may be
NULL.name – Field name.
- Returns:
Value of the first matching field, or
NULL.
-
const lwhttp_headers_t *lwhttp_client_headers(const lwhttp_client_t *client)#
Access the response header store, for example to iterate with
lwhttp_headers_at().Same contents and lifetime as for
lwhttp_client_header(). Do not modify it.- Parameters:
client – The client.
- Returns:
The store, or
NULLifclientisNULL.
-
const char *lwhttp_client_url(const lwhttp_client_t *client)#
URL of the current or most recent request; after redirects, the final URL.
- Parameters:
client – The client.
- Returns:
Client-owned copy, valid until the next request or redirect;
NULLbefore the first request or forNULL.
-
const lwhttp_client_stats_t *lwhttp_client_stats(const lwhttp_client_t *client)#
Access the client’s counters.
- Parameters:
client – The client.
- Returns:
Pointer into the client, updated live;
NULLforNULL.
Upgrades#
-
struct lwip_socket *lwhttp_client_detach(lwhttp_client_t *client, const uint8_t **pending, size_t *pending_len)#
Take over the socket of an upgraded connection (
101or a 2xx answer toCONNECT).Call after the request completed with
LWHTTP_OK, for example fromon_complete. The client unregisters its event handler and forgets the socket; the caller owns it from then on and must register its own handler and eventuallylwip_socket_close()andlwip_socket_destroy()it.- Parameters:
client – The client.
pending – Receives a pointer to bytes the client already read past the response head (the start of the new protocol), or
NULLif not wanted. The data lives in the client and is valid until its next request or destruction.pending_len – Receives the number of pending bytes (at most 512), or
NULLif not wanted.
- Returns:
The socket, or
NULLif the last request did not upgrade, the socket was already detached or closed, orclientisNULL.