2023-12-13 18:59:11 -05:00
|
|
|
#pragma once
|
|
|
|
|
2024-02-20 21:41:37 -05:00
|
|
|
/**
|
|
|
|
** \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.
|
|
|
|
** @{
|
|
|
|
*/
|
|
|
|
|
2024-01-02 10:02:47 -05:00
|
|
|
#include <stdbool.h>
|
2023-12-17 12:44:54 -05:00
|
|
|
#include <stddef.h>
|
|
|
|
|
2024-03-03 12:35:10 -05:00
|
|
|
/** An HTTP connection. */
|
2023-12-13 18:59:11 -05:00
|
|
|
typedef struct _tf_http_connection_t tf_http_connection_t;
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/** An HTTP request. */
|
2023-12-25 18:39:16 -05:00
|
|
|
typedef struct _tf_http_request_t tf_http_request_t;
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/** An HTTP instance. */
|
2023-12-30 13:59:02 -05:00
|
|
|
typedef struct _tf_http_t tf_http_t;
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/** A TLS context. */
|
2023-12-30 13:59:02 -05:00
|
|
|
typedef struct _tf_tls_context_t tf_tls_context_t;
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/** A trace instance. */
|
2024-01-02 21:14:17 -05:00
|
|
|
typedef struct _tf_trace_t tf_trace_t;
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/** An event loop. */
|
2023-12-30 13:59:02 -05:00
|
|
|
typedef struct uv_loop_s uv_loop_t;
|
2023-12-13 18:59:11 -05:00
|
|
|
|
2024-03-03 12:35:10 -05:00
|
|
|
/**
|
|
|
|
** 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.
|
|
|
|
*/
|
2024-02-15 18:35:01 -05:00
|
|
|
typedef void(tf_http_message_callback)(tf_http_request_t* request, int op_code, const void* data, size_t size);
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
** A callback called when a request closes.
|
|
|
|
** @param request The HTTP request.
|
|
|
|
*/
|
2024-02-15 18:35:01 -05:00
|
|
|
typedef void(tf_http_close_callback)(tf_http_request_t* request);
|
2023-12-25 18:39:16 -05:00
|
|
|
|
2024-03-03 12:35:10 -05:00
|
|
|
/**
|
|
|
|
** 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.
|
|
|
|
*/
|
2023-12-13 18:59:11 -05:00
|
|
|
typedef struct _tf_http_request_t
|
|
|
|
{
|
2024-03-03 12:35:10 -05:00
|
|
|
/** The HTTP instance this request belongs to. */
|
2024-01-02 10:02:47 -05:00
|
|
|
tf_http_t* http;
|
2024-03-03 12:35:10 -05:00
|
|
|
/** The HTTP connection associated with this request. */
|
2023-12-13 18:59:11 -05:00
|
|
|
tf_http_connection_t* connection;
|
2024-03-03 12:35:10 -05:00
|
|
|
/** True if this is an HTTPS session. */
|
2024-01-02 10:02:47 -05:00
|
|
|
bool is_tls;
|
2024-03-03 12:35:10 -05:00
|
|
|
/** The HTTP method of the request (GET/POST/...). */
|
2023-12-13 18:59:11 -05:00
|
|
|
const char* method;
|
2024-03-03 12:35:10 -05:00
|
|
|
/** The HTTP request path. */
|
2023-12-13 18:59:11 -05:00
|
|
|
const char* path;
|
2024-03-03 12:35:10 -05:00
|
|
|
/** The raw HTTP query string. */
|
2023-12-23 14:52:59 -05:00
|
|
|
const char* query;
|
2024-03-03 12:35:10 -05:00
|
|
|
/** The HTTP request body. */
|
2023-12-23 14:52:59 -05:00
|
|
|
void* body;
|
2024-03-03 12:35:10 -05:00
|
|
|
/** The length of the HTTP request body. */
|
2023-12-23 14:52:59 -05:00
|
|
|
size_t content_length;
|
2024-03-03 12:35:10 -05:00
|
|
|
/** Header storage. Can also be accessed with tf_http_request_get_header(). */
|
2023-12-13 18:59:11 -05:00
|
|
|
struct phr_header* headers;
|
2024-03-03 12:35:10 -05:00
|
|
|
/** The number of headers stored. */
|
2023-12-13 18:59:11 -05:00
|
|
|
int headers_count;
|
2024-03-03 12:35:10 -05:00
|
|
|
/** A callback to be called when receiving a websocket message. */
|
2023-12-25 18:39:16 -05:00
|
|
|
tf_http_message_callback* on_message;
|
2024-03-03 12:35:10 -05:00
|
|
|
/** A callback to be called when the connection is closed. */
|
2024-01-26 21:36:08 -05:00
|
|
|
tf_http_close_callback* on_close;
|
2024-03-03 12:35:10 -05:00
|
|
|
/** Extra storage for user data. */
|
2023-12-25 18:39:16 -05:00
|
|
|
void* context;
|
2024-03-03 12:35:10 -05:00
|
|
|
/** User data available to callbacks. */
|
2023-12-13 18:59:11 -05:00
|
|
|
void* user_data;
|
2024-03-03 12:35:10 -05:00
|
|
|
/** The number of times tf_http_request_ref() has been called without tf_http_request_unref(). */
|
2023-12-21 12:45:06 -05:00
|
|
|
int ref_count;
|
2023-12-13 18:59:11 -05:00
|
|
|
} tf_http_request_t;
|
|
|
|
|
2024-02-20 21:41:37 -05:00
|
|
|
/**
|
|
|
|
** Create an HTTP server using the given libuv loop.
|
|
|
|
** @param loop A libuv loop to use.
|
|
|
|
** @return An HTTP server instance.
|
|
|
|
*/
|
2023-12-13 18:59:11 -05:00
|
|
|
tf_http_t* tf_http_create(uv_loop_t* loop);
|
2024-02-20 21:41:37 -05:00
|
|
|
|
2024-03-03 12:35:10 -05:00
|
|
|
/**
|
|
|
|
** 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.
|
|
|
|
*/
|
2024-01-02 21:14:17 -05:00
|
|
|
void tf_http_set_trace(tf_http_t* http, tf_trace_t* trace);
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
** 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.
|
|
|
|
*/
|
2024-01-27 12:27:56 -05:00
|
|
|
int tf_http_listen(tf_http_t* http, int port, tf_tls_context_t* tls, tf_http_cleanup_t* cleanup, void* user_data);
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
** 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.
|
|
|
|
*/
|
2024-01-27 12:11:24 -05:00
|
|
|
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);
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
** 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.
|
|
|
|
*/
|
2023-12-18 12:51:15 -05:00
|
|
|
void tf_http_respond(tf_http_request_t* request, int status, const char** headers, int headers_count, const void* body, size_t content_length);
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
** 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.
|
|
|
|
*/
|
2023-12-20 18:58:28 -05:00
|
|
|
size_t tf_http_get_body(const tf_http_request_t* request, const void** out_data);
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
** Destroy an HTTP instance.
|
|
|
|
** @param http The HTTP instance.
|
|
|
|
*/
|
2023-12-13 18:59:11 -05:00
|
|
|
void tf_http_destroy(tf_http_t* http);
|
2023-12-21 12:45:06 -05:00
|
|
|
|
2024-03-03 12:35:10 -05:00
|
|
|
/**
|
|
|
|
** 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.
|
|
|
|
*/
|
2024-01-02 10:02:47 -05:00
|
|
|
void tf_http_set_user_data(tf_http_t* http, void* user_data, tf_http_cleanup_t* cleanup);
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
** Get HTTP instance user data previous set with tf_http_set_user_data().
|
|
|
|
** @param http The HTTP instance.
|
|
|
|
** @return The user data.
|
|
|
|
*/
|
2024-01-02 10:02:47 -05:00
|
|
|
void* tf_http_get_user_data(tf_http_t* http);
|
|
|
|
|
2024-03-03 12:35:10 -05:00
|
|
|
/**
|
|
|
|
** 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.
|
|
|
|
*/
|
2023-12-21 12:45:06 -05:00
|
|
|
void tf_http_request_ref(tf_http_request_t* request);
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
** Decrement a requests refcount. tf_http_request_ref() must have been previously called.
|
|
|
|
** @param request The request.
|
|
|
|
*/
|
2024-01-27 10:45:51 -05:00
|
|
|
void tf_http_request_unref(tf_http_request_t* request);
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
** 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.
|
|
|
|
*/
|
2023-12-24 12:43:33 -05:00
|
|
|
const char* tf_http_request_get_header(tf_http_request_t* request, const char* name);
|
2024-03-03 12:35:10 -05:00
|
|
|
|
2024-03-31 16:15:50 -04:00
|
|
|
/**
|
|
|
|
** 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);
|
|
|
|
|
2024-03-03 12:35:10 -05:00
|
|
|
/**
|
|
|
|
** 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.
|
|
|
|
*/
|
2023-12-25 17:53:05 -05:00
|
|
|
void tf_http_request_send(tf_http_request_t* request, const void* data, size_t size);
|
2024-03-03 12:35:10 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
** Upgrade an HTTP request to a websocket session.
|
|
|
|
** @param request The HTTP request.
|
|
|
|
*/
|
2023-12-30 11:29:16 -05:00
|
|
|
void tf_http_request_websocket_upgrade(tf_http_request_t* request);
|
2024-02-08 20:21:57 -05:00
|
|
|
|
2024-03-03 12:35:10 -05:00
|
|
|
/**
|
|
|
|
** 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.
|
|
|
|
*/
|
2024-02-08 20:21:57 -05:00
|
|
|
const char* tf_http_status_text(int status);
|
2024-02-20 21:41:37 -05:00
|
|
|
|
|
|
|
/** @} */
|