#pragma once /** ** \defgroup http HTTP Server ** This is a HTTP server. ** ** It can listen on multiple ports. It supports IPv4 ** and IPv6. It handles websocket connections. Requests can be handled ** immediately or at a later time. It is very bare bones, and that is a ** feature. ** @{ */ #include #include /** An HTTP connection. */ typedef struct _tf_http_connection_t tf_http_connection_t; /** An HTTP request. */ typedef struct _tf_http_request_t tf_http_request_t; /** An HTTP instance. */ typedef struct _tf_http_t tf_http_t; /** A TLS context. */ typedef struct _tf_tls_context_t tf_tls_context_t; /** A trace instance. */ typedef struct _tf_trace_t tf_trace_t; /** An event loop. */ typedef struct uv_loop_s uv_loop_t; /** ** A callback called when receiving a websocket message. ** @param request The HTTP request. ** @param op_code The type of websocket message. ** @param data The payload. ** @param size The size of the payload in bytes. */ typedef void(tf_http_message_callback)(tf_http_request_t* request, int op_code, const void* data, size_t size); /** ** A callback called when a request closes. ** @param request The HTTP request. */ typedef void(tf_http_close_callback)(tf_http_request_t* request); /** ** A callback called when an HTTP request is received. ** @param request The HTTP request. */ typedef void(tf_http_callback_t)(tf_http_request_t* request); /** ** A callback called when the HTTP instance is destroyed. ** @param user_data User data provided with the callback. */ typedef void(tf_http_cleanup_t)(void* user_data); /** ** An HTTP request. */ typedef struct _tf_http_request_t { /** The HTTP instance this request belongs to. */ tf_http_t* http; /** The HTTP connection associated with this request. */ tf_http_connection_t* connection; /** True if this is an HTTPS session. */ bool is_tls; /** The HTTP method of the request (GET/POST/...). */ const char* method; /** The HTTP request path. */ const char* path; /** The raw HTTP query string. */ const char* query; /** The HTTP request body. */ void* body; /** The length of the HTTP request body. */ size_t content_length; /** Header storage. Can also be accessed with tf_http_request_get_header(). */ struct phr_header* headers; /** The number of headers stored. */ int headers_count; /** A callback to be called when receiving a websocket message. */ tf_http_message_callback* on_message; /** A callback to be called when the connection is closed. */ tf_http_close_callback* on_close; /** Extra storage for user data. */ void* context; /** User data available to callbacks. */ void* user_data; /** The number of times tf_http_request_ref() has been called without tf_http_request_unref(). */ int ref_count; } tf_http_request_t; /** ** Create an HTTP server using the given libuv loop. ** @param loop A libuv loop to use. ** @return An HTTP server instance. */ tf_http_t* tf_http_create(uv_loop_t* loop); /** ** Register a trace instance with the HTTP instance to record the begin and end ** time of request handlers. ** @param http The HTTP instance to trace. ** @param trace The trace instance to use, or NULL to disable. */ void tf_http_set_trace(tf_http_t* http, tf_trace_t* trace); /** ** Begin listening for HTTP requests on a new port. May be called multiple ** times to listen on multiple ports. ** @param http The HTTP instance. ** @param port The port on which to listen, or 0 to assign a free port. ** @param tls An optional TLS context to use for HTTPS requests. ** @param cleanup A function called when the HTTP instance is being cleaned up. ** @param user_data User data passed to the cleanup callback. ** @return The port number on which the HTTP instance is now listening. */ int tf_http_listen(tf_http_t* http, int port, tf_tls_context_t* tls, tf_http_cleanup_t* cleanup, void* user_data); /** ** Add an HTTP request handler. ** @param http The HTTP instance. ** @param pattern The prefix that the path of incoming requests must match to use this handler. ** @param callback The function to be called to handle the request. ** @param cleanup A function to be called when the request is complete. ** @param user_data User data to pass to the callbacks. */ void tf_http_add_handler(tf_http_t* http, const char* pattern, tf_http_callback_t* callback, tf_http_cleanup_t* cleanup, void* user_data); /** ** Respond to an HTTP request. ** @param request The request. ** @param status The HTTP status with which to respond. ** @param headers Headers to include in the response. Content-Length will be added internally. ** @param headers_count The number of headers. The headers array must have ** twice as many entries as this value, since it is both keys and values. ** @param body The response body or NULL. ** @param content_length The length of the response body. */ void tf_http_respond(tf_http_request_t* request, int status, const char** headers, int headers_count, const void* body, size_t content_length); /** ** Get the request body content. ** @param request An incoming request. ** @param out_data The request body content. Valid until the request is completed. ** @return The size of the request body content. */ size_t tf_http_get_body(const tf_http_request_t* request, const void** out_data); /** ** Destroy an HTTP instance. ** @param http The HTTP instance. */ void tf_http_destroy(tf_http_t* http); /** ** Set instance-wide HTTP user data and a callback to clean it up. ** @param http The HTTP instance. ** @param user_data The user data. ** @param cleanup The cleanup callback. */ void tf_http_set_user_data(tf_http_t* http, void* user_data, tf_http_cleanup_t* cleanup); /** ** Get HTTP instance user data previous set with tf_http_set_user_data(). ** @param http The HTTP instance. ** @return The user data. */ void* tf_http_get_user_data(tf_http_t* http); /** ** Increment a requests refcount to keep it around after its callback. ** tf_http_respond() may be called at a later time, and tf_http_request_unref() ** must eventually be called in order to not leak the request. ** @param request The request to retain. */ void tf_http_request_ref(tf_http_request_t* request); /** ** Decrement a requests refcount. tf_http_request_ref() must have been previously called. ** @param request The request. */ void tf_http_request_unref(tf_http_request_t* request); /** ** Get the value of a header from an HTTP request. ** @param request The request. ** @param name The header key. Matched case insensitively. ** @return The value or NULL. */ const char* tf_http_request_get_header(tf_http_request_t* request, const char* name); /** ** Get a cookie value from request headers. ** @param cookie_header The value of the "Cookie" header of the form ** "name1=value1; name2=value2". ** @param name The cookie name. ** @return The cookie value, if found, or NULL. Must be freed with tf_free(). */ const char* tf_http_get_cookie(const char* cookie_header, const char* name); /** ** Send a websocket message. ** @param request The HTTP request which was previously updated to a websocket ** session with tf_http_request_websocket_upgrade(). ** @param data The message data. ** @param size The size of data. */ void tf_http_request_send(tf_http_request_t* request, const void* data, size_t size); /** ** Upgrade an HTTP request to a websocket session. ** @param request The HTTP request. */ void tf_http_request_websocket_upgrade(tf_http_request_t* request); /** ** Get standard HTTP status text for common HTTP statuses. 200 = "OK", 404 = ** "File not found", etc. ** @param status The HTTP status. ** @return The status text or NULL. */ const char* tf_http_status_text(int status); /** ** Match URL patterns. "*" matches anything, and "{word}" matches [a-zA-Z][a-zA-Z0-9]*". ** @param pattern The pattern to match. ** @param path The path to test. ** @return true if the path matches the pattern. */ bool tf_http_pattern_matches(const char* pattern, const char* path); /** @} */