GNU libmicrohttpd

About

GNU libmicrohttpd is a small C library that is supposed to make it easy to run an HTTP server as part of another application. GNU libmicrohttpd is free software and part of the GNU project. Key features that distinguish libmicrohttpd from other projects are:

libmicrohttpd was started because the author needed an easy way to add a concurrent HTTP server to other projects. Existing alternatives were either non-free, not reentrant, standalone, of terrible code quality or a combination thereof. Do not use libmicrohttpd if you are looking for a standalone http server, there are many other projects out there that provide that kind of functionality already. However, if you want to be able to serve simple WWW pages from within your C or C++ application, check it out.

libmicrohttpd is licensed under the GNU LGPL.

Download

You can find the current release here. Binaries for Windows are available here. The latest version of the source code can be browsed from here or obtained using

$ svn checkout https://gnunet.org/svn/libmicrohttpd/

libmicrohttpd can be used without any dependencies; however, for SSL/TLS support, we currently require libgcrypt. Furthermore, the testcases use libcurl. Some extended testcases also use zzuf and socat (to simulate clients that violate the HTTP protocols). You can compile and use libmicrohttpd without installing libgcrypt, libcurl, zzuf or socat.

If you want to be notified about updates, subscribe to libmicrohttpd on freshmeat A public mailinglist for libmicrohttpd is hosted at http://crisp.cs.du.edu/cgi-bin/mailman/listinfo/libmicrohttpd/.

Using libmicrohttpd

In addition to the brief documentation on this webpage, we have various other forms of documentation available:

microhttpd.h
This include file documents most of the API in detail.
Doxygen
Here can find detailed documentation generated from the source code using doxygen.
Manual
The libmicrohttpd manual is available as one document in pdf and html formats, and as multiple pages in html format.
Tutorial
The libmicrohttpd tutorial is available as one document in pdf and html formats, and as multiple pages in html format.
Coverage reports
This link refers to code coverage reports for our testsuite.

The rest of this section gives a general overview.

Before including the microhttpd.h header you must include the headers in your operating system that define the size_t, fd_set, socklen_t and struct sockaddr data types.

Here is a minimal example for GNU/Linux (included in the distribution):

#include <sys/types.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <microhttpd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define PAGE "<html><head><title>libmicrohttpd demo</title>"\
             "</head><body>libmicrohttpd demo</body></html>"

static int ahc_echo(void * cls,
		    struct MHD_Connection * connection,
		    const char * url,
		    const char * method,
                    const char * version,
		    const char * upload_data,
		    unsigned int * upload_data_size,
                    void ** ptr) {
  static int dummy;
  const char * page = cls;
  struct MHD_Response * response;
  int ret;

  if (0 != strcmp(method, "GET"))
    return MHD_NO; /* unexpected method */
  if (&dummy != *ptr) 
    {
      /* The first time only the headers are valid,
         do not respond in the first round... */
      *ptr = &dummy;
      return MHD_YES;
    }
  *ptr = NULL; /* clear context pointer */
  response = MHD_create_response_from_data(strlen(page),
					   (void*) page,
					   MHD_NO,
					   MHD_NO);
  ret = MHD_queue_response(connection,
			   MHD_HTTP_OK,
			   response);
  MHD_destroy_response(response);
  return ret;
}

int main(int argc,
	 char ** argv) {
  struct MHD_Daemon * d;
  if (argc != 3) {
    printf("%s PORT SECONDS-TO-RUN\n",
	   argv[0]);
    return 1;
  }
  d = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION,
		       atoi(argv[1]),
		       NULL,
		       NULL,
		       &ahc_echo,
		       PAGE,
		       MHD_OPTION_END);
  if (d == NULL)
    return 1;
  sleep(atoi(argv[2]));
  MHD_stop_daemon(d);
  return 0;
}

Threading models

The example above uses the simplest threading model, MHD_USE_THREAD_PER_CONNECTION. In this model, MHD starts one thread to listen on the port for new connections and then spawns a new thread to handle each connection. This model is great if the HTTP server has hardly any state that is shared between connections (no synchronization issues!) and may need to perform blocking operations (such as extensive IO or running of code) to handle an individual connection.

The second threading model, MHD_USE_SELECT_INTERNALLY, uses only a single thread to handle listening on the port and processing of requests. This model is preferable if spawning a thread for each connection would be costly. If the HTTP server is able to quickly produce responses without much computational overhead for each connection, this model can be a great choice. Note that MHD will still start a single thread -- the main program can continue with its operations. Naturally, if the HTTP server needs to interact with shared state in the main application, synchronization will be required. If such synchronization in code providing a response results in blocking, all HTTP server operations on all connections will stall. This mode is a bad choice if response data (for responses generated using the MHD_create_response_from_callback function) cannot always be provided instantly. The reason is that the code generating responses should not block (since that would block all other connections) and on the other hand, if response data is not available immediately, MHD will start to busy wait on it. Use the first model if you want to block on providing response data in the callback, or the last model if you want to use a more event-driven model with one big select loop.

The third threading model (used when no specific flag is given), uses no threads. Instead, the main application must (periodically) request file descriptor sets from MHD, perform a select call and then call MHD_run. MHD_run will then process HTTP requests as usual and return. MHD_run is guaranteed to not block; however, access handlers and response processing callbacks that it invokes may block. This mode is useful if a single-threaded implementation is desired and in particular if the main application already uses a select loop for its processing. If the application is not ready to provide a response, it can just return zero for the number of bytes read and use its file descriptors in the external select loop to wake up and continue once the data is ready -- MHD will unlist the socket from the write set if the application failed to provide response data (this only happens in this mode).

The testcases provided include examples for using each of the three threading modes.

Responses

MHD provides various functions to create struct MHD_Response objects. A response consists of a set of HTTP headers and a (possibly empty) body. The two main ways to create a response are either by specifying a given (fixed-size) body (MHD_create_response_from_data) or by providing a function of type MHD_ContentReaderCallback which provides portions of the response as needed. The first response construction is great for small and in particular static webpages that fit into memory. The second response type should be used for response objects where the size is initially not known or where the response maybe too large to fit into memory.

A response is used by calling MHD_queue_response which sends the response back to the client on the specified connection. Once created, a response object can be used any number of times. Internally, each response uses a reference counter. The response is freed once the reference counter reaches zero. The HTTP server should call MHD_destroy_response when a response object is no longer needed, that is, the server will not call MHD_queue_response again using this response object. Note that this does not mean that the response will be immediately destroyed -- destruction maybe delayed until sending of the response is complete on all connections that have the response in the queue.

Clients should never queue a "100 CONTINUE" response. MHD handles "100 CONTINUE" internally and only allows clients to queue a single response per connection. Furthermore, clients must not queue a response before the request has been fully received. If a client attempts to queue multiple responses or attempts to queue a response early, MHD_queue_response will fail (and return MHD_NO).

Queueing responses

The callback function for the respective URL will be called at least twice. The first call happens after the server has received the headers. The client should use the last void** argument to store internal context for the session. The first call to the callback function is mostly for this type of initialization and for internal access checks. At least, the callback function should "remember" that the first call with just the headers has happened. Queueing a response during the first call (for a given connection) should only be used for errors -- if the client queues a response during this first call, a 100 CONTINUE response will be suppressed, the request body will not be read and the connection will be closed after sending the response. After the first call, the callback function will be called with upload data. Until *upload_data_size is zero, the callback may not queue a response, any such attempt will fail. The callback function should update *upload_data_size to indicate how many bytes were processed. Depending on available buffer space, incremental processing of the upload maybe required. Once all of the upload data has been processed, MHD will call the callback a second time with *upload_data_size being zero. At this point, the callback should queue a "normal" response. If queueing a response is not possible, the callback may either block or simply not queue a response depending on the threading model that is used. If the callback does not queue a response at this point, MHD will either (eventually) timeout the connection or keep calling it.

Parsing of POST requests

MHD includes a set of three functions for parsing and processing data received in POST requests. The functions allow incremental parsing and processing of POST data. Only a tiny fraction of the overall POST data needs to fit into memory. As a result, applications using MHD can support POST requests of arbitrary size. POST data is processed by providing MHD with a callback function that is called on portions of the received values. The POST parser itself is invoked repeatedly whenever more input bytes become available. MHD supports both uri- and multipart/form-encoded POST data.

Memory Management

The application can determine the size of buffers that MHD should use for handling of HTTP requests and parsing of POST data. This way, MHD users can trade-off processing time and memory utilization. Applications can limit the overall number of connections MHD will accept, as well as the total amount of memory used per connection. MHD will gracefully handle all out-of-memory situations (by closing the connection and cleaning up any remaining state).

Bugtrack

libmicrohttpd uses Mantis for bugtracking. Visit https://gnunet.org/mantis/ to report bugs. You need to sign up for a reporter account. Please make sure you report bugs under libmicrohttpd and not under any of the other projects.

If you dislike Mantis and need to report a bug contact christian@grothoff.org via e-mail.

Applications using libmicrohttpd

If you write an application that uses libmicrohttpd, please let us know so that we can add you to the list!

Alternatives


Christian Grothoff
Copyright (C) 2007, 2008 Christian Grothoff.
Verbatim copying and distribution of this entire article
is permitted in any medium, provided this notice is preserved.