HTTPSERVER(3) Library Functions Manual HTTPSERVER(3)

HttpServerExtremely simple HTTP server.

#include <HttpServer.h>

HttpServer *
HttpServerCreate(unsigned short, unsigned int, unsigned int, HttpHandler *, void *);

HttpServerFree(HttpServer *);

HttpServerStart(HttpServer *);

HttpServerJoin(HttpServer *);

HttpServerStop(HttpServer *);

HashMap *
HttpRequestHeaders(HttpServerContext *);

HttpRequestMethodGet(HttpServerContext *);

char *
HttpRequestPath(HttpServerContext *);

HashMap *
HttpRequestParams(HttpServerContext *);

char *
HttpResponseHeader(HttpServerContext *, char *, char *);

HttpResponseStatus(HttpServerContext *, HttpStatus");

HttpStream(HttpServerContext *);

HttpSendHeaders(HttpServerContext *);

HttpServer builds on the Http(3) API, and provides a very simple, yet very functional API for creating an HTTP server. It aims at being easy to use and minimal, yet also efficient. It uses non-blocking I/O, is fully multi-threaded, very configurable, yet also able to be set up in just two function calls.

This API should be familiar to those that have dealt with the HTTP server libraries of other programming languages, particularly Java. In fact, much of the terminology used in this code came from Java, and you'll notice that the way responses are sent and received very closely resemble the way it's done in Java.

An HTTP server itself is created with (), which takes the port number to create the server on, the number of threads to use, the maximum number of connections, a request handler function, and the arguments to that function, in that order. The request handler function is of the following type:

typedef void (HttpHandler) (HttpServerContext *, void *)

Where the void pointer received is the same pointer that was passed into () as the last parameter.

The returned HttpServer pointer is then managed by (), HttpServerStop(), (), and HttpServerFree(). HttpServerStart() attempts to start the HTTP server, and returns immediately with the status. This API is fully threaded and asyncronous, so the caller can continue working while the HTTP server is running in a separate thread, and managing a pool of threads to handle responses. Typically at some point after calling HttpServerStart(), the program will have no more work to do, and so it will want to wait for the HTTP server to finish. This is accomplished with HttpServerJoin(), which joins the HTTP worker thread to the calling thread, making the calling thread wait until the HTTP server has stopped.

The only condition that will cause the HTTP server to stop is when () is invoked. This will typically happen in a signal handler that catches signals instructing the program to shut down. Only after the server has been stopped can it be freed with (). Note that calling HttpServerFree() while the server is running results in undefined behavior.

The remainder of the functions in this API are used inside of the HTTP handler function passed by the caller of (). They allow the handler to figure out the context of an HTTP request, which includes the path that was requested, any parameters, and the headers used to make the request. They also allow the handler to respond with a status code, headers, and a body.

(), (), (), and () get the information about the request. They should all be passed the server context pointer that was passed into the handler function. The data returned by these functions should be treated as read-only, and should not be freed; their memory is handled outside of the HTTP server handler function.

() and () are used to set response headers, and the response status of the request, respectively.

() returns a stream that is both readable and writable. Reading from the stream reads the request body that the client sent, if there is one. Note that the request headers have already been read, so the stream is correctly positioned at the beginning of the body of the request. () must be called before the stream is written to, otherwise a malformed HTTP response will be sent. An HTTP handler should properly set all the headers it intends to send, send those headers, and then write the response body to the stream. Finally, note that the stream does not need to be closed by the HTTP handler; in fact, doing so results in undefined behavior. The stream is managed by the server itself.

HttpRequestHeaders() and HttpRequestParams() return a hash map that can be used to access the request headers and parameters, if necessary. Note that the request parameters would be GET parameters, attached to the path that was requested. To get POST parameters, read the stream returned by HttpStream() and pass the contents into HttpParamDecode() to get a hash map.

HttpRequestPath() returns a string that represents the path that the client requested. Note that it is not normalized; it is exactly what the client sent, so it should be checked for path traversal attacks and other malformed paths that the client may sent.

HttpResponseHeader() returns the previous value of the given header, or NULL if there was no previous value.

HttpStream() returns a FILE pointer that can be read and written using the C standard I/O functions.


December 13, 2022 Telodendria Project