| /* |
| copyright: Boaz segev, 2016-2017 |
| license: MIT |
| |
| Feel free to copy, use and enjoy according to the license provided. |
| */ |
| #ifndef HTTP_H |
| #define HTTP_H |
| #define LIB_FACIL_HTTP_VERSION_MAJOR 0 |
| #define LIB_FACIL_HTTP_VERSION_MINOR 4 |
| #define LIB_FACIL_HTTP_VERSION_PATCH 0 |
| #include "facil.h" |
| |
| /** an HTTP/1.1 vs. HTTP/2 identifier. */ |
| enum HTTP_VERSION { HTTP_V1 = 0, HTTP_V2 = 1 }; |
| |
| /** HTTP header information */ |
| typedef struct { |
| const char *name; |
| union { |
| const char *data; |
| const char *value; |
| }; |
| uint32_t name_len; |
| union { |
| uint32_t data_len; |
| uint32_t value_len; |
| }; |
| } http_header_s; |
| |
| /** Settings typedef */ |
| typedef struct http_settings_s http_settings_s; |
| |
| /* ***************************************************************************** |
| Core include files |
| */ |
| // clang-format off |
| #include <time.h> |
| #include "http_request.h" |
| #include "http_response.h" |
| // clang-format on |
| /* ***************************************************************************** |
| Hard Coded Settings |
| */ |
| |
| /** When a new connection is accepted, it will be immediately declined with a |
| * 503 service unavailable (server busy) response unless the following number of |
| * file descriptors is available.*/ |
| #ifndef HTTP_BUSY_UNLESS_HAS_FDS |
| #define HTTP_BUSY_UNLESS_HAS_FDS 64 |
| #endif |
| |
| #ifndef HTTP_DEFAULT_BODY_LIMIT |
| #define HTTP_DEFAULT_BODY_LIMIT (1024 * 1024 * 50) |
| #endif |
| |
| /* ***************************************************************************** |
| HTTP Core API & data structure |
| */ |
| |
| /** Manages protocol settings for the HTTP protocol */ |
| struct http_settings_s { |
| /** |
| The maximum size of an HTTP request's body (when posting data). |
| |
| Defaults to ~ 50Mb. |
| */ |
| size_t max_body_size; |
| /** REQUIRED: the callback to be performed when requests come in. */ |
| void (*on_request)(http_request_s *request); |
| /** |
| A public folder for file transfers - allows to circumvent any application |
| layer server and simply serve files. |
| */ |
| const char *public_folder; |
| /** |
| The length of the public_folder string. |
| */ |
| size_t public_folder_length; |
| /** Opaque user data. */ |
| void *udata; |
| /** Opaque user data for the optional `set_rw_hooks`. */ |
| void *rw_udata; |
| /** (optional) the callback to be performed when the HTTP service closes. */ |
| void (*on_finish)(intptr_t uuid, void *udata); |
| /** |
| * Allows a an implementation for the transport layer (i.e. TLS) without |
| * effecting the HTTP protocol. |
| */ |
| sock_rw_hook_s *(*set_rw_hooks)(intptr_t fduuid, void *rw_udata); |
| /** |
| * A cleanup callback for the `rw_udata`. |
| */ |
| void (*on_finish_rw)(intptr_t uuid, void *rw_udata); |
| /** |
| Logging flag - set to TRUE to log static file requests. |
| |
| Dynamic request logging is always the dynamic application's responsibility. |
| */ |
| uint8_t log_static; |
| /** An HTTP/1.x connection timeout. Defaults to ~5 seconds.*/ |
| uint8_t timeout; |
| /** |
| The default HTTP version which a new connection will use. At the moment, only |
| version HTTP/1.1 is supported. |
| */ |
| enum HTTP_VERSION version; |
| /** |
| internal flag for library use. |
| */ |
| uint8_t private_metaflags; |
| }; |
| |
| typedef protocol_s *(*http_on_open_func)(intptr_t, void *); |
| typedef void (*http_on_finish_func)(void *); |
| /** |
| Return the callback used for creating the HTTP protocol in the `settings`. |
| */ |
| http_on_open_func http_get_on_open_func(http_settings_s *settings); |
| /** |
| Return the callback used for freeing the HTTP protocol in the `settings`. |
| */ |
| http_on_finish_func http_get_on_finish_func(http_settings_s *settings); |
| |
| /** |
| Listens for incoming HTTP connections on the specified posrt and address, |
| implementing the requested settings. |
| |
| Since facil.io doesn't support native TLS/SLL |
| */ |
| int http_listen(const char *port, const char *address, |
| http_settings_s settings); |
| |
| #define http_listen(port, address, ...) \ |
| http_listen((port), (address), (http_settings_s){__VA_ARGS__}) |
| |
| /* ***************************************************************************** |
| HTTP Helper functions that might be used globally |
| */ |
| |
| /** |
| A faster (yet less localized) alternative to `gmtime_r`. |
| |
| See the libc `gmtime_r` documentation for details. |
| |
| Falls back to `gmtime_r` for dates before epoch. |
| */ |
| struct tm *http_gmtime(const time_t *timer, struct tm *tmbuf); |
| |
| /** |
| Writes an HTTP date string to the `target` buffer. |
| |
| This requires _____ bytes of space to be available at the target buffer. |
| |
| Returns the number of bytes actually written. |
| */ |
| size_t http_date2str(char *target, struct tm *tmbuf); |
| |
| /** |
| A fast, inline alternative to `sprintf(dest, "%lu", num)`. |
| |
| Writes an **unsigned** number to a buffer, as a string. This is an unsafe |
| functions that assumes the buffer will have at least 21 bytes and isn't NULL. |
| |
| A NULL terminating byte is written. |
| |
| Returns the number of bytes actually written (excluding the NULL byte). |
| */ |
| static inline size_t http_ul2a(char *dest, size_t num) { |
| uint8_t digits = 1; |
| size_t tmp = num; |
| while ((tmp /= 10)) |
| ++digits; |
| |
| dest += digits; |
| *(dest--) = 0; |
| for (size_t i = 0; i < digits; i++) { |
| num = num - (10 * (tmp = (num / 10))); |
| *(dest--) = '0' + num; |
| num = tmp; |
| } |
| return digits; |
| } |
| |
| /** Decodes a URL encoded string, no buffer overflow protection. */ |
| ssize_t http_decode_url_unsafe(char *dest, const char *url_data); |
| |
| /** Decodes a URL encoded string (i.e., the "query" part of a request). */ |
| ssize_t http_decode_url(char *dest, const char *url_data, size_t length); |
| |
| /** Decodes the "path" part of a request, no buffer overflow protection. */ |
| ssize_t http_decode_path_unsafe(char *dest, const char *url_data); |
| |
| /** Decodes the "path" part of an HTTP request, no buffer overflow protection. |
| */ |
| ssize_t http_decode_path(char *dest, const char *url_data, size_t length); |
| |
| #endif |