#pragma once /** ** \defgroup httpd_js HTTPD Interface ** Exposes the \ref http server to script and registers a number of built-in ** endpoints. ** ** core/core.js is gradually being moved from JS to C here, at which point this will ** no longer be a bridge between the two and instead primarily expose the web API. ** ** @{ */ #include #include #include #include "quickjs.h" static const int64_t k_httpd_auth_refresh_interval = 1ULL * 7 * 24 * 60 * 60 * 1000; /** A JS context. */ typedef struct JSContext JSContext; /** ** An HTTP server instance. */ typedef struct _tf_http_t tf_http_t; /** ** An HTTP request. */ typedef struct _tf_http_request_t tf_http_request_t; /** ** An SSB instance. */ typedef struct _tf_ssb_t tf_ssb_t; /** ** A user and app name. */ typedef struct _tf_httpd_user_app_t { /** The username. */ const char* user; /** The app name. */ const char* app; } tf_httpd_user_app_t; /** ** Register the HTTP script interface. Also registers a number of built-in ** request handlers. An ongoing project is to move the JS request handlers ** into C, after which point this will only do the latter. ** @param context The JS context. */ void tf_httpd_register(JSContext* context); /** ** Create the HTTP server instance. ** @param context The JS context. */ tf_http_t* tf_httpd_create(JSContext* context); /** ** Destroy the HTTP server instance. ** @param http The HTTP server instance. */ void tf_httpd_destroy(tf_http_t* http); /** ** Determine a content-type from a file extension. ** @param ext The file extension. ** @param use_fallback If not found, fallback to application/binary. ** @return A MIME type or NULL. */ const char* tf_httpd_ext_to_content_type(const char* ext, bool use_fallback); /** ** Determine a content type from magic bytes. ** @param bytes The first bytes of a file. ** @param size The length of the bytes. ** @return A MIME type or NULL. */ const char* tf_httpd_magic_bytes_to_content_type(const uint8_t* bytes, size_t size); /** ** Respond with a redirect. ** @param request The HTTP request. ** @return true if redirected. */ bool tf_httpd_redirect(tf_http_request_t* request); /** ** Parse a username and app from a path like /~user/app/. ** @param path The path. ** @param expected_suffix A suffix that is required to be on the path, and removed. ** @return The user and app. Free with tf_free(). */ tf_httpd_user_app_t* tf_httpd_parse_user_app_from_path(const char* path, const char* expected_suffix); /** ** Decode form data into key value pairs. ** @param data The form data string. ** @param length The length of the form data string. ** @return Key values pairs terminated by NULL. */ const char** tf_httpd_form_data_decode(const char* data, int length); /** ** Get a form data value from an array of key value pairs produced by tf_httpd_form_data_decode(). ** @param form_data The form data. ** @param key The key for which to fetch the value. ** @return the value for the case-insensitive key or NULL. */ const char* tf_httpd_form_data_get(const char** form_data, const char* key); /** ** Validate a JWT. ** @param ssb The SSB instance. ** @param context A JS context. ** @param jwt The JWT. ** @return The JWT contents if valid. */ JSValue tf_httpd_authenticate_jwt(tf_ssb_t* ssb, JSContext* context, const char* jwt); ; /** ** Make a JS response object for a request. ** @param context The JS context. ** @param request The HTTP request. ** @return The respone object. */ JSValue tf_httpd_make_response_object(JSContext* context, tf_http_request_t* request); /** ** Check if a name meets requirements. ** @param name The name. ** @return true if the name is valid. */ bool tf_httpd_is_name_valid(const char* name); /** ** Make a header for the session cookie. ** @param request The HTTP request. ** @param session_cookie The session cookie. ** @return The header. */ const char* tf_httpd_make_set_session_cookie_header(tf_http_request_t* request, const char* session_cookie); /** ** Make a JWT for the session. ** @param context A JS context. ** @param ssb The SSB instance. ** @param name The username. ** @return The JWT. */ const char* tf_httpd_make_session_jwt(JSContext* context, tf_ssb_t* ssb, const char* name); /** ** Serve a static file. ** @param request The HTTP request. */ void tf_httpd_endpoint_static(tf_http_request_t* request); /** ** View a blob. ** @param request The HTTP request. */ void tf_httpd_endpoint_view(tf_http_request_t* request); /** ** Save a blob or app. ** @param request The HTTP request. */ void tf_httpd_endpoint_save(tf_http_request_t* request); /** ** Delete a blob or app. ** @param request The HTTP request. */ void tf_httpd_endpoint_delete(tf_http_request_t* request); /** ** App endpoint. ** @param request The HTTP request. */ void tf_httpd_endpoint_app(tf_http_request_t* request); /** ** App index endpoint. ** @param request The HTTP request. */ void tf_httpd_endpoint_app_index(tf_http_request_t* request); /** ** Login endpoint. ** @param request The HTTP request. */ void tf_httpd_endpoint_login(tf_http_request_t* request); /** ** Auto-login endpoint. ** @param request The HTTP request. */ void tf_httpd_endpoint_login_auto(tf_http_request_t* request); /** ** Logout endpoint. ** @param request The HTTP request. */ void tf_httpd_endpoint_logout(tf_http_request_t* request); /** @} */