HTTP API¶
This is the yimmo HTTP public API reference.
Info
To get a general sense for how the module is used, see The HTTP Protocol.
Contents
HTTP Headers¶
Note
Re: Set-Cookie:
All HTTP response headers have to conform to the rules
outlined in RFC 7230 (section 3.2.2 — Field Order)
with the exception of the Set-Cookie
header which has its own
grammar (outlined in RFC 6265, section 4.1.1 — Set-Cookie Syntax).
At this time, the library uses a crude trick to accommodate this: it
checks to see if the header being set is Set-Cookie
and, if so, it
adds another node to the header table, rather than concatenating the
values.
This works out okay for setting cookies, but it also means that once a cookie has been inserted into a header table as part of a single exchange, it cannot be unset using either insert or add operations.
This doesn’t mean you can’t unset cookies at all — it is possible to unset a cookie by merely not setting it again on subsequent requests. You just can’t set a cookie inside a request handler and then unset it in the same response.
TL;DR: The Set-Cookie
header is essentially append-only.
Warning
Re: storage:
Generally, yimmo does not copy header field names or data (the only
exception is concatenation — see ymo_http_hdr_table_add()
for
more info). The pointers you pass in are the locations in memory the
header table will actually read from (but not write to — it does not
modify any data passed in).
This means that you are responsible for ensuring that the data referenced by the header name/value parameters exists at least as long as the yimmo response object.
Don’t worry!: there are facilities in the ymo_http_request
type to facilitate exactly this kind of memory pattern (i.e. allocation
arenas associated with a particular HTTP exchange) via the ws
(workspace) field.
For more info, see:
-
type ymo_http_hdr_table_t¶
HTTP header table type.
typedef struct ymo_http_hdr_table ymo_http_hdr_table_t;
-
type ymo_http_hdr_table_node_t¶
HTTP header table node type.
typedef struct ymo_http_hdr_table_node ymo_http_hdr_table_node_t;
-
type ymo_http_hdr_table_pool_t¶
HTTP header table node pool type (when enabled).
typedef struct ymo_http_hdr_table_pool ymo_http_hdr_table_pool_t;
-
type ymo_http_hdr_ptr_t¶
HTTP header table node pointer — used by
ymo_http_hdr_table_next()
as a cursor for iterating over tables.typedef ymo_http_hdr_table_node_t* ymo_http_hdr_ptr_t;
-
ymo_http_hdr_table_t *ymo_http_hdr_table_create(void)¶
Create a new HTTP header table.
-
ymo_http_hdr_id_t ymo_http_hdr_table_insert(ymo_http_hdr_table_t *table, const char *hdr, const char *value)¶
Insert a new value,
value
at keyhdr
.Warning
If the header name given by
hdr
is already present in the header table, it will be replaced.- Parameters
table – a pointer to the header table to modify.
hdr – the header field name.
value – the header field value.
- Returns
the computed integer ID for the inserted header.
-
ymo_http_hdr_id_t ymo_http_hdr_table_add(ymo_http_hdr_table_t *table, const char *hdr, const char *value)¶
Add the value,
value
at keyhdr
.Note
If the header name given by
hdr
is not present, it is created. If it’s already present, the header values are joined using','
and combined into a single header table entry.- Parameters
table – a pointer to the header table to modify.
hdr – the header field name.
value – the header field value.
- Returns
the computed integer ID for the added header.
-
const char *ymo_http_hdr_table_get(const ymo_http_hdr_table_t *table, const char *hdr)¶
Get the value of a header field by name.
- Parameters
table – a pointer to the header table to query
hdr – the name of the header field whose value we’re fetching
- Returns
a pointer to the internal header field value on success;
NULL
on failure.
-
ymo_http_hdr_ptr_t ymo_http_hdr_table_next(ymo_http_hdr_table_t *table, ymo_http_hdr_ptr_t cur, const char **hdr, size_t *hdr_len, const char **value)¶
Iterate over all of the headers in a header table.
- Parameters
table – a pointer to the header table to query
cur – a cursor used to traverse the header table. (This is set to
NULL
on the first invocation).hdr – the header field name is stored here
hdr_len – the length of the header field name is stored here
value – the header field value is stored here
- Returns
the next cursor or
NULL
once the end of the table is reached.
// These will be populated during iteration: const char* hdr_name; const char* hdr_value; size_t name_len; // On the first invocation, we just // pass NULL for the cursor: ymo_http_hdr_ptr_t iter = ymo_http_hdr_table_next( table, NULL, &hdr_name, &name_len, &hdr_value); // As long as the returned cursor is not // NULL, we've got data: while( iter ) { printf("%.*s=%s\n", (int)name_len, hdr_name, hdr_value); // Get the next entry in the table: iter = ymo_http_hdr_table_next( table, iter, &hdr_name, &name_len, &hdr_value); }
-
void ymo_http_hdr_table_clear(ymo_http_hdr_table_t *table)¶
Remove all the entries from the hash table.
-
void ymo_http_hdr_table_free(ymo_http_hdr_table_t *table)¶
Free the given hash table.
Exchanges¶
Type Definitions¶
-
type ymo_http_request_t¶
Opaque struct used to represent HTTP requests.
typedef struct ymo_http_request ymo_http_request_t;
-
type ymo_http_response_t¶
Opaque struct used to represent HTTP responses.
typedef struct ymo_http_response ymo_http_response_t;
-
type ymo_http_exchange_t¶
Opaque struct used to represent HTTP requests-response pairs.
typedef struct ymo_http_exchange ymo_http_exchange_t;
-
type ymo_http_session_t¶
Opaque struct used to represent HTTP sessions.
typedef struct ymo_http_session ymo_http_session_t;
-
type ymo_http_method¶
Enum type used to indicate parsed HTTP method.
YMO_ENUM8_TYPEDEF(ymo_http_method) { YMO_HTTP_METH_OPTIONS, YMO_HTTP_METH_GET, YMO_HTTP_METH_HEAD, YMO_HTTP_METH_POST, YMO_HTTP_METH_PUT, YMO_HTTP_METH_DELETE, YMO_HTTP_METH_TRACE, YMO_HTTP_METH_CONNECT, YMO_HTTP_METH_OTHER, } YMO_ENUM8_AS(ymo_http_method_t);
-
type ymo_http_status_t¶
Convenience enums for HTTP status codes.
typedef uint16_t ymo_http_status_t;
Requests¶
-
struct ymo_http_request¶
HTTP request callback structure.
Note
Re: request “Workspaces”
Yimmo provides a Varnish-style, per-request, block-memory, workspace which can be used to acquire memory on demand which is automatically freed after the request has completed (or otherwise been disposed of), e.g.:
// Contrived example: set the HTTP header // "hex-counter" to the value of some global // counter, incremented with each request: typedef ymo_status_t my_http_callback( ymo_http_session_t* session, ymo_http_request_t* request, ymo_http_response_t* response, void* user_data) { // Allocate space enough for "0x" + 4 hex digits + '\0' terminal: char* value = ymo_blalloc(request->ws, alignof(char), 7); snprintf(value, "0x%x", ++my_global_counter, 7); ymo_http_hdr_table_insert(&request->headers, "hex-counter", value); // ... do other request handling stuff ... ymo_http_response_finish(response); return YMO_OKAY; }
The workspace object,
ws
is allocated and deallocated by yimmo automatically — i.e.ws
is already usable at the time that any of the HTTP callbacks are invoked. Noymo_blalloc_create()
orymo_blalloc_free()
invocations are required!struct ymo_http_request { const char* method; /* GET, POST, etc */ const char* uri; /* Full URI, *as received* */ const char* version; /* Protocol version *string* */ const char* query; /* Query string, *as received* */ const char* fragment; /* URI fragment, *as received* */ ymo_http_hdr_table_t headers; /* Request headers */ ymo_blalloc_t* ws; /* Request workspace */ char* body; /* Optionally buffered body data */ size_t body_received; /* Body data received */ size_t content_length; /* Content-length, per client */ ymo_http_flags_t flags; /* Request flags */ void* user; /* Arbitrary, per-request, user-data */ };
Responses¶
-
ymo_http_hdr_table_t *ymo_http_response_get_headers(ymo_http_response_t *response)¶
Get the header table for a response object.
-
const char *ymo_http_response_get_header(const ymo_http_response_t *response, const char *hdr_name)¶
Get the value of the header given by
hdr_name
.- Parameters
response – the HTTP response object to modify
header – the HTTP header to get
-
ymo_status_t ymo_http_response_add_header(ymo_http_response_t *response, const char *header, const char *value)¶
Used to set HTTP header values for responses
- Parameters
response – the HTTP response object to modify
header – the HTTP header to set
value – the value for the header
- Returns
YMO_OKAY on success; appropriate errno on failure
-
ymo_status_t ymo_http_response_insert_header(ymo_http_response_t *response, const char *header, const char *value)¶
Used to set HTTP header values for responses
- Parameters
response – the HTTP response object to modify
header – the HTTP header to set
value – the value for the header
- Returns
YMO_OKAY on success; appropriate errno on failure
-
void ymo_http_response_body_append(ymo_http_response_t *response, ymo_bucket_t *body_data)¶
Add HTTP body data
- Parameters
response – the HTTP response object to which we append body data
body_data – the body payload as a
ymo_bucket_t
(see Buckets for more info)
-
void ymo_http_response_set_status(ymo_http_response_t *response, ymo_http_status_t status)¶
Set the HTTP status code — the reason will be filled in from a table or else “NULL”.
- Parameters
response – the HTTP response object to modify
status – the integer HTTP status code
-
int ymo_http_response_set_status_str(ymo_http_response_t *response, const char *status_str)¶
Set the HTTP status code and reason as a string.
- Parameters
response – the HTTP response object to modify
status – the integer HTTP status code
-
void ymo_http_response_ready(ymo_http_response_t *response)¶
Mark the http response as ready for transmission.
-
int ymo_http_response_is_ready(const ymo_http_response_t *response)¶
- Returns
true if this response has data ready to send; false otherwise.
-
void ymo_http_response_finish(ymo_http_response_t *response)¶
Mark the response data as complete (i.e. fully ready to transmit)
-
int ymo_http_response_finished(const ymo_http_response_t *response)¶
- Returns
true if this response is finished; false otherwise.
Sessions¶
-
void ymo_http_session_set_userdata(ymo_http_session_t *session, void *data)¶
Set session-level user data.
-
void *ymo_http_session_get_userdata(const ymo_http_session_t *session)¶
Get session-level user data.
Callbacks¶
Note
See Callbacks for more info.
-
type ymo_http_session_init_cb_t¶
Session initialization callback.
typedef ymo_status_t (*ymo_http_session_init_cb_t)( void* server_data, ymo_http_session_t* session);
-
type ymo_http_session_cleanup_cb_t¶
Session cleanupialization callback.
typedef void (*ymo_http_session_cleanup_cb_t)( void* server_data, ymo_http_session_t* session, void* user_data);
-
type ymo_http_cb_t¶
HTTP exchange callback.
- Param session
The client HTTP session
- Param exchange
The originating exchange object
- Param response
A blank response object
- Param user_data
user data if set; else
NULL
- Returns
YMO_OKAY on success; errno.h value on failure.
typedef ymo_status_t (*ymo_http_cb_t)( ymo_http_session_t* session, ymo_http_request_t* request, ymo_http_response_t* response, void* user_data);
-
type ymo_http_header_cb_t¶
HTTP exchange callback.
- Param session
The client HTTP session
- Param exchange
The originating exchange object
- Param response
A blank response object
- Param user
user data if set; else
NULL
- Returns
YMO_OKAY on success; errno.h value on failure.
typedef ymo_http_cb_t ymo_http_header_cb_t;
-
type ymo_http_body_cb_t¶
HTTP exchange callback.
- Param session
the client HTTP session
- Param exchange
the originating exchange object
- Param data
exchange body data
- Param len
size of body data in bytes
- Param user_data
user data if set; else
NULL
typedef ymo_status_t (*ymo_http_body_cb_t)( ymo_http_session_t* session, ymo_http_request_t* request, ymo_http_response_t* response, const char* data, size_t len, void* user_data);
Protocol Management¶
-
type ymo_http_upgrade_status¶
YMO_ENUM8_TYPEDEF(ymo_http_upgrade_status) { YMO_HTTP_UPGRADE_HANDLED, YMO_HTTP_UPGRADE_IGNORE, YMO_HTTP_UPGRADE_ERROR, YMO_HTTP_UPGRADE_NOPROTO, } YMO_ENUM8_AS(ymo_http_upgrade_status_t);
-
type ymo_http_upgrade_cb_t¶
HTTP upgrade handler callback.
- Param hdr_upgrade
the value of the HTTP “Upgrade:” header
- Param exchange
the originating http exchange object
- Param response
a blank response object
- Returns
ymo_http_status_t indicator + set errno on failure
typedef ymo_http_upgrade_status_t (*ymo_http_upgrade_cb_t)( const char* hdr_upgrade, ymo_http_request_t* request, ymo_http_response_t* response);
-
type ymo_http_upgrade_handler_t¶
Struct that encapsulates functions and data required to validate and perform and HTTP Upgrade exchange protocol switch.
typedef struct ymo_http_upgrade_handler { ymo_http_upgrade_cb_t cb; ymo_proto_t* proto_new; } ymo_http_upgrade_handler_t;
-
ymo_http_upgrade_handler_t *ymo_http2_no_upgrade_handler(void)¶
Yimmo has no HTTP/2 support, at the moment. This callback can be used to reject an upgrade exchange for h2c over HTTP/1.0 or HTTP/1.1.
-
ymo_proto_t *ymo_proto_http_create(ymo_http_session_init_cb_t session_init, ymo_http_cb_t http_callback, ymo_http_header_cb_t header_callback, ymo_http_body_cb_t body_cb, ymo_http_session_cleanup_cb_t session_cleanup, void *data)¶
Used to create a new HTTP protocol endpoint.
-
ymo_status_t ymo_http_add_upgrade_handler(ymo_proto_t *proto, ymo_http_upgrade_handler_t *upgrade_handler)¶
Used to add an upgrade handler to the internal upgrade handler chain.
Quickstart¶
-
ymo_server_t *ymo_http_simple_init(struct ev_loop *loop, in_port_t port, ymo_http_cb_t http_callback, ymo_http_upgrade_handler_t **upgrade_handlers, void *data)¶
Create a server by
- invoking
ymo_proto_http_create()
to create a new, buffered, HTTP protocol object with the given port and handler callback.
- invoking
- passing that proto object to
ymo_server_create()
, along with the default
ymo_serfer_config_t
.
- passing that proto object to
- Parameters
loop – pointer to a libev loop object, or NULL for default
port – port number to bind to
http_callback – buffered HTTP callback handler
upgrade_handlers – an array of
ymo_http_upgrade_handler_t
pointers for HTTP upgrade requests.data – arbitrary pointer to associate with this server (available in callbacks as
data
).
- Returns
a
ymo_server_t
pointer on success;NULL
witherrno
set on failure.
Misc¶
-
YMO_HTTP_CONTINUE¶
HTTP Status 100 (Continue)
#define YMO_HTTP_CONTINUE 100
-
YMO_HTTP_SWITCHING_PROTOCOLS¶
HTTP Status 101 (Switching protocols)
#define YMO_HTTP_SWITCHING_PROTOCOLS 101
-
YMO_HTTP_OK¶
HTTP Status 200 (Ok)
#define YMO_HTTP_OK 200
-
YMO_HTTP_CREATED¶
HTTP Status 201 (Created)
#define YMO_HTTP_CREATED 201
-
YMO_HTTP_ACCEPTED¶
HTTP Status 202 (Accepted)
#define YMO_HTTP_ACCEPTED 202
-
YMO_HTTP_NON_AUTHORITATIVE_INFORMATION¶
HTTP Status 203 (Non authoritative information)
#define YMO_HTTP_NON_AUTHORITATIVE_INFORMATION 203
-
YMO_HTTP_NO_CONTENT¶
HTTP Status 204 (No content)
#define YMO_HTTP_NO_CONTENT 204
-
YMO_HTTP_RESET_CONTENT¶
HTTP Status 205 (Reset content)
#define YMO_HTTP_RESET_CONTENT 205
-
YMO_HTTP_PARTIAL_CONTENT¶
HTTP Status 206 (Partial content)
#define YMO_HTTP_PARTIAL_CONTENT 206
-
YMO_HTTP_MULTIPLE_CHOICES¶
HTTP Status 300 (Multiple choices)
#define YMO_HTTP_MULTIPLE_CHOICES 300
-
YMO_HTTP_MOVED_PERMANENTLY¶
HTTP Status 301 (Moved permanently)
#define YMO_HTTP_MOVED_PERMANENTLY 301
-
YMO_HTTP_FOUND¶
HTTP Status 302 (Found)
#define YMO_HTTP_FOUND 302
-
YMO_HTTP_SEE_OTHER¶
HTTP Status 303 (See other)
#define YMO_HTTP_SEE_OTHER 303
-
YMO_HTTP_NOT_MODIFIED¶
HTTP Status 304 (Not modified)
#define YMO_HTTP_NOT_MODIFIED 304
-
YMO_HTTP_USE_PROXY¶
HTTP Status 305 (Use proxy)
#define YMO_HTTP_USE_PROXY 305
-
YMO_HTTP_TEMPORARY_REDIRECT¶
HTTP Status 307 (Temporary redirect)
#define YMO_HTTP_TEMPORARY_REDIRECT 307
-
YMO_HTTP_BAD_REQUEST¶
HTTP Status 400 (Bad request)
#define YMO_HTTP_BAD_REQUEST 400
-
YMO_HTTP_UNAUTHORIZED¶
HTTP Status 401 (Unauthorized)
#define YMO_HTTP_UNAUTHORIZED 401
-
YMO_HTTP_PAYMENT_REQUIRED¶
HTTP Status 402 (Payment required)
#define YMO_HTTP_PAYMENT_REQUIRED 402
-
YMO_HTTP_FORBIDDEN¶
HTTP Status 403 (Forbidden)
#define YMO_HTTP_FORBIDDEN 403
-
YMO_HTTP_NOT_FOUND¶
HTTP Status 404 (Not found)
#define YMO_HTTP_NOT_FOUND 404
-
YMO_HTTP_METHOD_NOT_ALLOWED¶
HTTP Status 405 (Method not allowed)
#define YMO_HTTP_METHOD_NOT_ALLOWED 405
-
YMO_HTTP_NOT_ACCEPTABLE¶
HTTP Status 406 (Not acceptable)
#define YMO_HTTP_NOT_ACCEPTABLE 406
-
YMO_HTTP_PROXY_AUTHENTICATION_REQUIRED¶
HTTP Status 407 (Proxy authentication required)
#define YMO_HTTP_PROXY_AUTHENTICATION_REQUIRED 407
-
YMO_HTTP_REQUEST_TIMEOUT¶
HTTP Status 408 (Request timeout)
#define YMO_HTTP_REQUEST_TIMEOUT 408
-
YMO_HTTP_CONFLICT¶
HTTP Status 409 (Conflict)
#define YMO_HTTP_CONFLICT 409
-
YMO_HTTP_GONE¶
HTTP Status 410 (Gone)
#define YMO_HTTP_GONE 410
-
YMO_HTTP_LENGTH_REQUIRED¶
HTTP Status 411 (Length required)
#define YMO_HTTP_LENGTH_REQUIRED 411
-
YMO_HTTP_PRECONDITION_FAILED¶
HTTP Status 412 (Precondition failed)
#define YMO_HTTP_PRECONDITION_FAILED 412
-
YMO_HTTP_REQUEST_ENTITY_TOO_LARGE¶
HTTP Status 413 (Request entity too large)
#define YMO_HTTP_REQUEST_ENTITY_TOO_LARGE 413
-
YMO_HTTP_REQUEST_URI_TOO_LONG¶
HTTP Status 414 (Request uri too long)
#define YMO_HTTP_REQUEST_URI_TOO_LONG 414
-
YMO_HTTP_UNSUPPORTED_MEDIA_TYPE¶
HTTP Status 415 (Unsupported media type)
#define YMO_HTTP_UNSUPPORTED_MEDIA_TYPE 415
-
YMO_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE¶
HTTP Status 416 (Requested range not satisfiable)
#define YMO_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE 416
-
YMO_HTTP_EXPECTATION_FAILED¶
HTTP Status 417 (Expectation failed)
#define YMO_HTTP_EXPECTATION_FAILED 417
-
YMO_HTTP_UPGRADE_REQUIRED¶
HTTP Status 426 (Upgrade required)
#define YMO_HTTP_UPGRADE_REQUIRED 426
-
YMO_HTTP_PRECONDITION_REQUIRED¶
HTTP Status 428 (Precondition required)
#define YMO_HTTP_PRECONDITION_REQUIRED 428
-
YMO_HTTP_TOO_MANY_REQUESTES¶
HTTP Status 429 (Too many requestes)
#define YMO_HTTP_TOO_MANY_REQUESTES 429
-
YMO_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE¶
HTTP Status 431 (Request header fields too large)
#define YMO_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE 431
-
YMO_HTTP_INTERNAL_SERVER_ERROR¶
HTTP Status 500 (Internal server error)
#define YMO_HTTP_INTERNAL_SERVER_ERROR 500
-
YMO_HTTP_NOT_IMPLEMENTED¶
HTTP Status 501 (Not implemented)
#define YMO_HTTP_NOT_IMPLEMENTED 501
-
YMO_HTTP_BAD_GATEWAY¶
HTTP Status 502 (Bad gateway)
#define YMO_HTTP_BAD_GATEWAY 502
-
YMO_HTTP_SERVICE_UNAVAILABLE¶
HTTP Status 503 (Service unavailable)
#define YMO_HTTP_SERVICE_UNAVAILABLE 503
-
YMO_HTTP_GATEWAY_TIMEOUT¶
HTTP Status 504 (Gateway timeout)
#define YMO_HTTP_GATEWAY_TIMEOUT 504
-
YMO_HTTP_HTTP_VERSION_NOT_SUPPORTED¶
HTTP Status 505 (Http version not supported)
#define YMO_HTTP_HTTP_VERSION_NOT_SUPPORTED 505
-
YMO_HTTP_STATUS_CHR3_TO_INT¶
Given an array of three or more
char
from a trusted source, convert the character string to an integer.Warning
There is no:
bounds checking
range checking
validation
#define YMO_HTTP_STATUS_CHR3_TO_INT(s) \ ( \ ((s[0] & 0xf) * 100) + \ ((s[1] & 0xf) * 10) + \ (s[2] & 0xf) \ )