HTTP API ========== This is the yimmo HTTP public API reference. .. admonition:: Info To get a general sense for how the module is used, see :ref:`HTTP Overview`. .. contents:: Contents :local: .. toctree:: :maxdepth: 2 :hidden: --------------------------------------------------------------- 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 :c:func:`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 :c:struct:`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: - :c:struct:`ymo_http_request` - :c:macro:`YMO_BLALLOC`, :c:func:`ymo_blalloc` and :c:func:`ymo_blalloc_strdup` .. c:type:: ymo_http_hdr_table_t HTTP header table type. .. code-block:: c :caption: Definition typedef struct ymo_http_hdr_table ymo_http_hdr_table_t; .. c:type:: ymo_http_hdr_table_node_t HTTP header table node type. .. code-block:: c :caption: Definition typedef struct ymo_http_hdr_table_node ymo_http_hdr_table_node_t; .. c:type:: ymo_http_hdr_table_pool_t HTTP header table node pool type (when enabled). .. code-block:: c :caption: Definition typedef struct ymo_http_hdr_table_pool ymo_http_hdr_table_pool_t; .. c:type:: ymo_http_hdr_ptr_t HTTP header table node pointer — used by :c:func:`ymo_http_hdr_table_next` as a cursor for iterating over tables. .. code-block:: c :caption: Definition typedef ymo_http_hdr_table_node_t* ymo_http_hdr_ptr_t; .. c:function:: ymo_http_hdr_table_t* ymo_http_hdr_table_create(void) Create a new HTTP header table. .. c:function:: 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 key ``hdr``. .. warning:: If the header name given by ``hdr`` is already present in the header table, it will be *replaced*. :param table: a pointer to the header table to modify. :param hdr: the header field name. :param value: the header field value. :returns: the computed integer ID for the inserted header. .. c:function:: 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 key ``hdr``. .. 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. :param table: a pointer to the header table to modify. :param hdr: the header field name. :param value: the header field value. :returns: the computed integer ID for the added header. .. c:function:: 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. :param table: a pointer to the header table to query :param 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. .. c:function:: 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. :param table: a pointer to the header table to query :param cur: a cursor used to traverse the header table. (This is set to ``NULL`` on the first invocation). :param hdr: the header field *name* is stored here :param hdr_len: the length of the header field *name* is stored here :param value: the header field *value* is stored here :returns: the next cursor or ``NULL`` once the end of the table is reached. .. code-block:: c :caption: Example: Print all of the entries in a header table // 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); } .. c:function:: void ymo_http_hdr_table_clear(ymo_http_hdr_table_t* table) Remove all the entries from the hash table. .. c:function:: void ymo_http_hdr_table_free(ymo_http_hdr_table_t* table) Free the given hash table. --------------------------------------------------------------- Exchanges --------------------------------------------------------------- Type Definitions .................. .. c:type:: ymo_http_request_t Opaque struct used to represent HTTP requests. .. code-block:: c :caption: Definition typedef struct ymo_http_request ymo_http_request_t; .. c:type:: ymo_http_response_t Opaque struct used to represent HTTP responses. .. code-block:: c :caption: Definition typedef struct ymo_http_response ymo_http_response_t; .. c:type:: ymo_http_exchange_t Opaque struct used to represent HTTP requests-response pairs. .. code-block:: c :caption: Definition typedef struct ymo_http_exchange ymo_http_exchange_t; .. c:type:: ymo_http_session_t Opaque struct used to represent HTTP sessions. .. code-block:: c :caption: Definition typedef struct ymo_http_session ymo_http_session_t; .. c:type:: ymo_http_method Enum type used to indicate parsed HTTP method. .. code-block:: c :caption: Definition 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); .. c:type:: ymo_http_status_t Convenience enums for HTTP status codes. .. code-block:: c :caption: Definition typedef uint16_t ymo_http_status_t; Requests .......... .. c: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.: .. code-block:: c // 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. No :c:func:`ymo_blalloc_create` or :c:func:`ymo_blalloc_free` invocations are required! .. code-block:: c :caption: Definition 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 ........... .. c:function:: ymo_http_hdr_table_t* ymo_http_response_get_headers( ymo_http_response_t* response) Get the header table for a response object. .. c:function:: 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``. :param response: the HTTP response object to modify :param header: the HTTP header to get .. c:function:: 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 :param response: the HTTP response object to modify :param header: the HTTP header to set :param value: the value for the header :returns: YMO_OKAY on success; appropriate errno on failure .. c:function:: 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 :param response: the HTTP response object to modify :param header: the HTTP header to set :param value: the value for the header :returns: YMO_OKAY on success; appropriate errno on failure .. c:function:: void ymo_http_response_body_append( ymo_http_response_t* response, ymo_bucket_t* body_data) Add HTTP body data :param response: the HTTP response object to which we append body data :param body_data: the body payload as a :c:type:`ymo_bucket_t` (see :ref:`Yimmo Buckets` for more info) .. c:function:: 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". :param response: the HTTP response object to modify :param status: the integer HTTP status code .. c:function:: 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. :param response: the HTTP response object to modify :param status: the integer HTTP status code .. c:function:: void ymo_http_response_ready(ymo_http_response_t* response) Mark the http response as ready for transmission. .. c:function:: int ymo_http_response_is_ready(const ymo_http_response_t* response) :returns: true if this response has data ready to send; false otherwise. .. c:function:: void ymo_http_response_finish(ymo_http_response_t* response) Mark the response data as complete (i.e. fully ready to transmit) .. c:function:: int ymo_http_response_finished(const ymo_http_response_t* response) :returns: true if this response is finished; false otherwise. --------------------------------------------------------------- Sessions --------------------------------------------------------------- .. c:function:: void ymo_http_session_set_userdata(ymo_http_session_t* session, void* data) Set session-level user data. .. c:function:: void* ymo_http_session_get_userdata(const ymo_http_session_t* session) Get session-level user data. --------------------------------------------------------------- Callbacks --------------------------------------------------------------- .. note:: See :ref:`HTTP Callbacks` for more info. .. c:type:: ymo_http_session_init_cb_t Session initialization callback. .. code-block:: c :caption: Definition typedef ymo_status_t (*ymo_http_session_init_cb_t)( void* server_data, ymo_http_session_t* session); .. c:type:: ymo_http_session_cleanup_cb_t Session cleanupialization callback. .. code-block:: c :caption: Definition typedef void (*ymo_http_session_cleanup_cb_t)( void* server_data, ymo_http_session_t* session, void* user_data); .. c: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. .. code-block:: c :caption: Definition 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); .. c: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. .. code-block:: c :caption: Definition typedef ymo_http_cb_t ymo_http_header_cb_t; .. c: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`` .. code-block:: c :caption: Definition 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 --------------------------------------------------------------- .. c:type:: ymo_http_upgrade_status .. code-block:: c :caption: Definition 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); .. c: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 .. code-block:: c :caption: Definition 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); .. c:type:: ymo_http_upgrade_handler_t Struct that encapsulates functions and data required to validate and perform and HTTP Upgrade exchange protocol switch. .. code-block:: c :caption: Definition typedef struct ymo_http_upgrade_handler { ymo_http_upgrade_cb_t cb; ymo_proto_t* proto_new; } ymo_http_upgrade_handler_t; .. c:function:: 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. .. c:function:: 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. .. c:function:: 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 --------------------------------------------------------------- .. c:function:: 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 :c:func:`ymo_proto_http_create` to create a new, buffered, HTTP protocol object with the given port and handler callback. - passing that proto object to :c:func:`ymo_server_create`, along with the default :c:type:`ymo_serfer_config_t`. :param loop: pointer to a libev loop object, or NULL for default :param port: port number to bind to :param http_callback: buffered HTTP callback handler :param upgrade_handlers: an array of :c:type:`ymo_http_upgrade_handler_t` pointers for HTTP upgrade requests. :param data: arbitrary pointer to associate with this server (available in callbacks as ``data``). :returns: a :c:type:`ymo_server_t` pointer on success; ``NULL`` with ``errno`` set on failure. --------------------------------------------------------------- Misc --------------------------------------------------------------- .. c:macro:: YMO_HTTP_CONTINUE HTTP Status 100 (Continue) .. code-block:: c :caption: Definition #define YMO_HTTP_CONTINUE 100 .. c:macro:: YMO_HTTP_SWITCHING_PROTOCOLS HTTP Status 101 (Switching protocols) .. code-block:: c :caption: Definition #define YMO_HTTP_SWITCHING_PROTOCOLS 101 .. c:macro:: YMO_HTTP_OK HTTP Status 200 (Ok) .. code-block:: c :caption: Definition #define YMO_HTTP_OK 200 .. c:macro:: YMO_HTTP_CREATED HTTP Status 201 (Created) .. code-block:: c :caption: Definition #define YMO_HTTP_CREATED 201 .. c:macro:: YMO_HTTP_ACCEPTED HTTP Status 202 (Accepted) .. code-block:: c :caption: Definition #define YMO_HTTP_ACCEPTED 202 .. c:macro:: YMO_HTTP_NON_AUTHORITATIVE_INFORMATION HTTP Status 203 (Non authoritative information) .. code-block:: c :caption: Definition #define YMO_HTTP_NON_AUTHORITATIVE_INFORMATION 203 .. c:macro:: YMO_HTTP_NO_CONTENT HTTP Status 204 (No content) .. code-block:: c :caption: Definition #define YMO_HTTP_NO_CONTENT 204 .. c:macro:: YMO_HTTP_RESET_CONTENT HTTP Status 205 (Reset content) .. code-block:: c :caption: Definition #define YMO_HTTP_RESET_CONTENT 205 .. c:macro:: YMO_HTTP_PARTIAL_CONTENT HTTP Status 206 (Partial content) .. code-block:: c :caption: Definition #define YMO_HTTP_PARTIAL_CONTENT 206 .. c:macro:: YMO_HTTP_MULTIPLE_CHOICES HTTP Status 300 (Multiple choices) .. code-block:: c :caption: Definition #define YMO_HTTP_MULTIPLE_CHOICES 300 .. c:macro:: YMO_HTTP_MOVED_PERMANENTLY HTTP Status 301 (Moved permanently) .. code-block:: c :caption: Definition #define YMO_HTTP_MOVED_PERMANENTLY 301 .. c:macro:: YMO_HTTP_FOUND HTTP Status 302 (Found) .. code-block:: c :caption: Definition #define YMO_HTTP_FOUND 302 .. c:macro:: YMO_HTTP_SEE_OTHER HTTP Status 303 (See other) .. code-block:: c :caption: Definition #define YMO_HTTP_SEE_OTHER 303 .. c:macro:: YMO_HTTP_NOT_MODIFIED HTTP Status 304 (Not modified) .. code-block:: c :caption: Definition #define YMO_HTTP_NOT_MODIFIED 304 .. c:macro:: YMO_HTTP_USE_PROXY HTTP Status 305 (Use proxy) .. code-block:: c :caption: Definition #define YMO_HTTP_USE_PROXY 305 .. c:macro:: YMO_HTTP_TEMPORARY_REDIRECT HTTP Status 307 (Temporary redirect) .. code-block:: c :caption: Definition #define YMO_HTTP_TEMPORARY_REDIRECT 307 .. c:macro:: YMO_HTTP_BAD_REQUEST HTTP Status 400 (Bad request) .. code-block:: c :caption: Definition #define YMO_HTTP_BAD_REQUEST 400 .. c:macro:: YMO_HTTP_UNAUTHORIZED HTTP Status 401 (Unauthorized) .. code-block:: c :caption: Definition #define YMO_HTTP_UNAUTHORIZED 401 .. c:macro:: YMO_HTTP_PAYMENT_REQUIRED HTTP Status 402 (Payment required) .. code-block:: c :caption: Definition #define YMO_HTTP_PAYMENT_REQUIRED 402 .. c:macro:: YMO_HTTP_FORBIDDEN HTTP Status 403 (Forbidden) .. code-block:: c :caption: Definition #define YMO_HTTP_FORBIDDEN 403 .. c:macro:: YMO_HTTP_NOT_FOUND HTTP Status 404 (Not found) .. code-block:: c :caption: Definition #define YMO_HTTP_NOT_FOUND 404 .. c:macro:: YMO_HTTP_METHOD_NOT_ALLOWED HTTP Status 405 (Method not allowed) .. code-block:: c :caption: Definition #define YMO_HTTP_METHOD_NOT_ALLOWED 405 .. c:macro:: YMO_HTTP_NOT_ACCEPTABLE HTTP Status 406 (Not acceptable) .. code-block:: c :caption: Definition #define YMO_HTTP_NOT_ACCEPTABLE 406 .. c:macro:: YMO_HTTP_PROXY_AUTHENTICATION_REQUIRED HTTP Status 407 (Proxy authentication required) .. code-block:: c :caption: Definition #define YMO_HTTP_PROXY_AUTHENTICATION_REQUIRED 407 .. c:macro:: YMO_HTTP_REQUEST_TIMEOUT HTTP Status 408 (Request timeout) .. code-block:: c :caption: Definition #define YMO_HTTP_REQUEST_TIMEOUT 408 .. c:macro:: YMO_HTTP_CONFLICT HTTP Status 409 (Conflict) .. code-block:: c :caption: Definition #define YMO_HTTP_CONFLICT 409 .. c:macro:: YMO_HTTP_GONE HTTP Status 410 (Gone) .. code-block:: c :caption: Definition #define YMO_HTTP_GONE 410 .. c:macro:: YMO_HTTP_LENGTH_REQUIRED HTTP Status 411 (Length required) .. code-block:: c :caption: Definition #define YMO_HTTP_LENGTH_REQUIRED 411 .. c:macro:: YMO_HTTP_PRECONDITION_FAILED HTTP Status 412 (Precondition failed) .. code-block:: c :caption: Definition #define YMO_HTTP_PRECONDITION_FAILED 412 .. c:macro:: YMO_HTTP_REQUEST_ENTITY_TOO_LARGE HTTP Status 413 (Request entity too large) .. code-block:: c :caption: Definition #define YMO_HTTP_REQUEST_ENTITY_TOO_LARGE 413 .. c:macro:: YMO_HTTP_REQUEST_URI_TOO_LONG HTTP Status 414 (Request uri too long) .. code-block:: c :caption: Definition #define YMO_HTTP_REQUEST_URI_TOO_LONG 414 .. c:macro:: YMO_HTTP_UNSUPPORTED_MEDIA_TYPE HTTP Status 415 (Unsupported media type) .. code-block:: c :caption: Definition #define YMO_HTTP_UNSUPPORTED_MEDIA_TYPE 415 .. c:macro:: YMO_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE HTTP Status 416 (Requested range not satisfiable) .. code-block:: c :caption: Definition #define YMO_HTTP_REQUESTED_RANGE_NOT_SATISFIABLE 416 .. c:macro:: YMO_HTTP_EXPECTATION_FAILED HTTP Status 417 (Expectation failed) .. code-block:: c :caption: Definition #define YMO_HTTP_EXPECTATION_FAILED 417 .. c:macro:: YMO_HTTP_UPGRADE_REQUIRED HTTP Status 426 (Upgrade required) .. code-block:: c :caption: Definition #define YMO_HTTP_UPGRADE_REQUIRED 426 .. c:macro:: YMO_HTTP_PRECONDITION_REQUIRED HTTP Status 428 (Precondition required) .. code-block:: c :caption: Definition #define YMO_HTTP_PRECONDITION_REQUIRED 428 .. c:macro:: YMO_HTTP_TOO_MANY_REQUESTES HTTP Status 429 (Too many requestes) .. code-block:: c :caption: Definition #define YMO_HTTP_TOO_MANY_REQUESTES 429 .. c:macro:: YMO_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE HTTP Status 431 (Request header fields too large) .. code-block:: c :caption: Definition #define YMO_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE 431 .. c:macro:: YMO_HTTP_INTERNAL_SERVER_ERROR HTTP Status 500 (Internal server error) .. code-block:: c :caption: Definition #define YMO_HTTP_INTERNAL_SERVER_ERROR 500 .. c:macro:: YMO_HTTP_NOT_IMPLEMENTED HTTP Status 501 (Not implemented) .. code-block:: c :caption: Definition #define YMO_HTTP_NOT_IMPLEMENTED 501 .. c:macro:: YMO_HTTP_BAD_GATEWAY HTTP Status 502 (Bad gateway) .. code-block:: c :caption: Definition #define YMO_HTTP_BAD_GATEWAY 502 .. c:macro:: YMO_HTTP_SERVICE_UNAVAILABLE HTTP Status 503 (Service unavailable) .. code-block:: c :caption: Definition #define YMO_HTTP_SERVICE_UNAVAILABLE 503 .. c:macro:: YMO_HTTP_GATEWAY_TIMEOUT HTTP Status 504 (Gateway timeout) .. code-block:: c :caption: Definition #define YMO_HTTP_GATEWAY_TIMEOUT 504 .. c:macro:: YMO_HTTP_HTTP_VERSION_NOT_SUPPORTED HTTP Status 505 (Http version not supported) .. code-block:: c :caption: Definition #define YMO_HTTP_HTTP_VERSION_NOT_SUPPORTED 505 .. c:macro:: 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 .. code-block:: c :caption: Definition #define YMO_HTTP_STATUS_CHR3_TO_INT(s) \ ( \ ((s[0] & 0xf) * 100) + \ ((s[1] & 0xf) * 10) + \ (s[2] & 0xf) \ )