blob: 6c5f2e1dbde5734098f0f25f393d4d1d28ade54c [file] [log] [blame] [raw]
/*
copyright: Boaz segev, 2016
license: MIT
Feel free to copy, use and enjoy according to the license provided.
*/
#ifndef HTTP_COLLECTED_H
#define HTTP_COLLECTED_H
/** \file http.h
This header file simply collects all the http libraries required to start an
HTTP server and defines simple marcros to start an HTTP server using lib-server.
The file also introduces the `start_http_server` macro.
*/
#include "lib-server.h"
#include "http-response.h"
#include "http-protocol.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#define HTTP_DEFAULT_TIMEOUT 5
/**
This macro allows an easy start for an HTTP server, using the lib-server library
and the HTTP library helpers.
The macro accepts variable arguments. The first two (required) arguments are the
on_request callback for the HTTP protocol and an optional (can be NULL) public
folder for serving static files. The rest of the optional (variable) arguments
are any valid `struct ServerSettings` fields.
i.e. use:
void on_request(struct HttpRequest request) {
; // ...
}
int main()
{
char * public_folder = NULL
start_http_server(on_request, public_folder, .threads = 16);
}
To get a more detailed startup and setup customization, add an initialization
callback. i.e.:
void on_request(struct HttpRequest request) {
; // ...
}
void on_startup(server_pt srv) {
struct HttpProtocol * http =
(struct HttpProtocol*)Server.settings(srv)->protocol;
http->maximum_body_size = 100; // 100 Mb POST data limit.
; // ...
}
int main()
{
char * public_folder = NULL
start_http_server(on_request,
public_folder,
.threads = 16,
.on_init = on_startup);
}
*/
#define start_http_server(on_request_callback, http_public_folder, ...) \
do { \
struct HttpProtocol* protocol = HttpProtocol.create(); \
if ((NULL != (void*)on_request_callback)) \
protocol->on_request = (on_request_callback); \
char real_public_path[PATH_MAX]; \
if ((http_public_folder) && ((char*)http_public_folder)[0] == '~' && \
getenv("HOME") && strlen((http_public_folder)) < PATH_MAX) { \
strcpy(real_public_path, getenv("HOME")); \
strcpy(real_public_path + strlen(real_public_path), \
((char*)http_public_folder) + 1); \
protocol->public_folder = real_public_path; \
} else if ((http_public_folder)) \
protocol->public_folder = \
realpath((http_public_folder), real_public_path); \
HttpResponse.init_pool(); \
Server.listen((struct ServerSettings){ \
.timeout = HTTP_DEFAULT_TIMEOUT, \
.busy_msg = "HTTP/1.1 503 Service Unavailable\r\n\r\nServer Busy.", \
__VA_ARGS__, \
.protocol = (struct Protocol*)(protocol)}); \
HttpResponse.destroy_pool(); \
HttpProtocol.destroy(protocol); \
} while (0);
#ifdef SSL_VERIFY_PEER
#define start_https_server(on_request_callback, http_public_folder, ...) \
do { \
struct HttpProtocol* protocol = HttpProtocol.create(); \
if ((NULL != (void*)on_request_callback)) \
protocol->on_request = (on_request_callback); \
char real_public_path[PATH_MAX]; \
if ((http_public_folder) && ((char*)http_public_folder)[0] == '~' && \
getenv("HOME") && strlen((http_public_folder)) < PATH_MAX) { \
strcpy(real_public_path, getenv("HOME")); \
strcpy(real_public_path + strlen(real_public_path), \
((char*)http_public_folder) + 1); \
protocol->public_folder = real_public_path; \
} else if ((http_public_folder)) \
protocol->public_folder = \
realpath((http_public_folder), real_public_path); \
HttpResponse.init_pool(); \
struct ServerSettings settings = { \
.timeout = HTTP_DEFAULT_TIMEOUT, \
.busy_msg = "HTTP/1.1 503 Service Unavailable\r\n\r\nServer Busy.", \
__VA_ARGS__, \
.protocol = (struct Protocol*)(protocol)}; \
}; \
TLSServer.update_settings(&settings); \
Server.listen(settings); \
HttpResponse.destroy_pool(); \
HttpProtocol.destroy(protocol); \
} \
while (0) \
;
#endif /* SSL_VERIFY_PEER */
#endif /* HTTP_COLLECTED_H */