libebb

libebb is a lightweight HTTP server library for C. It lays the foundation for writing a web server by providing the socket juggling and request parsing. By implementing the HTTP/1.1 grammar provided in RFC2612, libebb understands most most valid HTTP/1.1 connections (persistent, pipelined, and chunked requests included) and rejects invalid or malicious requests. libebb supports SSL over HTTP.

The library embraces a minimalistic single-threaded evented design. No control is removed from the user. For example, all allocations are done through callbacks so that the user might implement in optimal ways for their specific application. By design libebb is not thread-safe and all provided callbacks must not block. libebb uses the high-performance libev event loop, but does not control it. The user of the library may start and stop the loop at will, they may attach thier own watchers.

libebb depends on POSIX sockets, libev, and optionally GnuTLS.

libebb is in the early stages of development and probably contains many bugs. The API is subject to radical changes. If you're interested checkout the source code and join the mailing list. A release will be made when it proves stable.

libebb is released under the X11 license.

Usage

libebb is a simple API, mostly it is providing callbacks. There are two types of callbacks that one will work with:

In libebb there are three important classes: ebb_server, ebb_connection, and ebb_request. Each server has many peer connections. Each peer connection may have many requests. There are two additional classes ebb_buf and ebb_request_parser which may or may not be useful.

ebb_server

ebb_server represents a single web server listening on a single port. The user must allocate the structure themselves, then call ebb_server_init() and provide a libev event loop. ebb_server_set_secure() will make the server understand HTTPS connections.

After initialized the ebb_server_listen_on_port() can be called to open the server up to new connections. libebb does not control the event loop, it is the user's responsibility to start the event loop (using ev_loop()) after ebb_server_listen_on_port() is called.

To accept connections you must provide the new server with a callback called new_connection. This callback must return an allocated and initialized ebb_connection structure. To set this callback do

my_server->new_connection = my_new_connection_callback;

Additional documentation can be found in ebb.h

ebb_connection

This structure contains information and callbacks for a single client connection. It is allocated and initialized through the new_connection callback in ebb_server. To initialize a newly allocated ebb_connection use ebb_connection_init().

After ebb_connection_init() is called a number of callbacks can be set: new_request, new_buf, on_timeout, and on_close.

When an ebb_connection is returned to an ebb_server, data is immediately data is read from the socket. This data must be stored somewhere. Because libebb is agnostic about allocation decisions, it passes this off to the user in the form of a callback: connection->new_buf. This callback returns a newly allocated and initialized ebb_buf structure. How much libebb attempts to read from the socket is determined by how large the returned ebb_buf structure is. Using new_buf is optional. By default libebb reads data into a static buffer (allocated at compile time), writing over it on each read. In many web server using the static buffer will be sufficent because callbacks made during the parsing will buffer the data elsewhere. Providing a new_buf callback is necessary only if you want to save the raw data coming from the socket.

The new_request callback is called at the beginning of a request. It must return a newly allocated and initialized ebb_request structure. Because HTTP/1.1 supports peristant connections, there may be many requests per connection.

You may access the file descriptor for the client socket inside the ebb_connection structure. Writing the response, in valid HTTP, is the user's responsibility. Remember, requests must be returned to client in the same order that they were received.

A convience function, ebb_connection_write, is provided which will write a single string to the peer. You may use this function or you may write to the file descriptor directly.

To close a peer connection use ebb_connnection_schedule_close(). Because SSL may require some additional communication to close the connection properly, the file descriptor cannot be closed immediately. The on_close callback will be made when the peer socket is finally closed. Only once on_close is called may the user free the ebb_connection structure.

ebb_request

This structure provides information about a request. For example, request->method == EBB_POST would mean the method of the request is POST. There are also many callbacks which can be set to handle data from a request as it is parsed.

The on_uri callback and all other ebb_element_cb callbacks provide pointers to request data. The annoying thing is they do not necessarily provide a complete string. This is because the reads from the socket may not contain an entire request and for efficency libebb does not attempt to buffer the data. Theoretically, one might receive an on_uri callback 10 times, each providing just a single character of the request's URI. See ebb_request_parser.h for a full list of callbacks that you may provide. (If you don't set them, they are ignored.)

The on_complete callback is called at the end of each request. Only once on_complete is called may the user free the ebb_request structure.

Example

A simple example is provided in examples/hello_world.c.