A minimalist HTTP server for Linux, written in x86_64 assembly。
asmhttpd - The tiniest webserver ever written.
HOW TO BUILD:
Just run "make". You will need NASM on your system.
HOW TO RUN:
./asmhttpd /path/to/your/webroot
sudo ./asmhttpd /path/to/your/webroot
If run as root, it will listen on port 80. Otherwise, it will use port 8080.
HOW TINY IS IT?
The entire text and data fit on a single 4K page:
{0}[calvin ~] cat /proc/$(pgrep -n asmhttpd)/maps
00401000-00402000 r-xp 00001000 00:16 2483272 asmhttpd
Each client allocates an additional 4K page and a thread while connected.
The code is written in a monolithic "branching tree" style with no functions,
and uses registers for all local variables. RAM is only used for buffering the
HTTP request, and for building structures necessary for system calls.
Because there is no stack, and the targets of all branch instructions are
constants, traditional buffer overflow exploits are impossible.from https://github.com/jcalvinowens/asmhttpd
-------
A web server written in bash。
bashttpd is a simple, configurable web server written in bash
bash, any recent version should worksocatornetcatto handle the underlying sockets.- A healthy dose of insanity
socat TCP4-LISTEN:8080 EXEC:/usr/local/bin/bashttpd
Or
netcat -lp 8080 -e ./bashttpd
Note that in the socat example above, the web
server will immediately exit once the first connection closes. If you
wish to serve to more than one client - like most servers do, then use
the variant:
socat TCP4-LISTEN:8080,fork EXEC:/usr/local/bin/bashttpd
This way, a new process is spawned for each incoming connection.
- Running bashttpd for the first time will generate a default configuration file, bashttpd.conf
- Review bashttpd.conf and configure it as you want.
- Run bashttpd using netcat or socat, as listed above.
- Serves text and HTML files
- Shows directory listings
- Allows for configuration based on the client-specified URI
- Does not support authentication
- Doesn't strictly adhere to the HTTP spec.
- Only rudimentary input handling. We would not running this on a public machine.
403: Returned when a directory is not listable, or a file is not readable
400: Returned when the first word of the first line is not GET
200: Returned with valid content
Content-type: Bashttpd uses /usr/bin/file to determine the MIME type to sent to the browser
1.0: The server doesn't support Host: headers or other HTTP/1.1 features - it barely supports HTTP/1.0!
As always, your patches/pull requests are welcome!
from https://github.com/tootallnate/bashttpd
-----
GNU Libmicrohttpd
GNU libmicrohttpd is a small C library that makes 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 GNU Libmicrohttpd from other projects are:
- C library: fast and small
- API is simple, expressive and fully reentrant
- Implementation is HTTP 1.1 compliant
- HTTP server can listen on multiple ports
- Various threading modes: run in application thread, internal thread, thread pool, and thread-per-connection
- Three different sockets polling modes: select(), poll(), and epoll
- Minimised number of sys-calls to avoid extra user/kernel mode switches
- Supported platforms include GNU/Linux, FreeBSD, OpenBSD, NetBSD, Android, Darwin (macOS), W32, OpenIndiana/Solaris, and z/OS
- Support for IPv6
- Support for SHOUTcast
- Support for incremental processing of POST data (optional)
- Support for basic and digest authentication (optional)
- Support for TLS (requires libgnutls, optional)
- Binary is only about 32k (without TLS support and other optional features)
GNU 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 GNU 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 WWW pages from within your C or C++ application, check it out.
GNU libmicrohttpd is maintained by Evgeny Grin (Karlson2k) and another co-maintainer.
Downloading libmicrohttpd
There are currently two main versions of the library available. GNU libmicrohttpd 1.x is the stable version, and GNU libmicrohttpd 2.x is experimental and remains under heavy development. GNU libmicrohttpd 2.x can currently only be obtained by cloning our Git repository at git://git.gnunet.org/libmicrohttpd2.git.- Source Code
- Libmicrohttpd is available from the main GNU FTP server via HTTP(S) and FTP. It can also be found on the GNU mirrors; please use a mirror if possible.
- Debian .deb package
- The debian package can be downloaded from the official debian archive. The respective packages for libmicrohttpd are libmicrohttpd and for development libmicrohttpd-dev.
- Tar Package
-
The latest version can be found on GNU mirrors.
If the mirror does not work, you should be able to find them on the
main FTP server.
Latest release is libmicrohttpd-latest.tar.gz.
- Windows
- Latest Windows binary is libmicrohttpd-latest-w32-bin.zip.
Documentation
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.
- Manual
- A manual for Libmicrohttpd
is available online, as is documentation for most GNU software.
You may also find more information about
Libmicrohttpd
by running
info libmicrohttpd
or
man libmicrohttpd,
or by looking at
/usr/share/doc/libmicrohttpd/,/usr/local/doc/libmicrohttpd/, or similar directories on your system. - Tutorial
- The GNU Libmicrohttpd tutorial is available as one document in PDF and HTML formats.
- Security audit 2025
- Ada Logics with support from the Sovereign Tech Agency performed a security audit of the source code of the GNU libmicrohttpd 2.x codebase in August 2025. All discovered issues were addressed. The full report is available here.
Mailing lists
Libmicrohttpd uses the libmicrohttpd mailinglist to discuss all aspects of Libmicrohttpd, including support, development, and enhancement requests, as well as bug reports.
Announcements about Libmicrohttpd and most other GNU software are made on info-gnu (archive).
Security reports that should not be made immediately public can be sent directly to the maintainers. If there is no response to an urgent issue, you can escalate to the general security mailing list for advice.
Getting involved
Development of Libmicrohttpd, and GNU in general, is a volunteer effort, and you can contribute. For information, please read How to help GNU. If you'd like to get involved, it's a good idea to join the discussion mailing list (see above).
- Development
- Known bugs and open feature requests are tracked in our bugtracker. 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.
- Git access
-
You can access the current development version of libmicrohttpd using
$ git clone https://git.gnunet.org/libmicrohttpd.git
Quick Introduction
- Dependencies
-
GNU Libmicrohttpd can be used without any dependencies; however,
for TLS (HTTPS) support it require
libgnutls.
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
GNU Libmicrohttpd without installing
libgnutls,libcurl,zzuforsocat. - Threading modes
MHD_USE_THREAD_PER_CONNECTION. In this mode, MHD starts one
thread to listen on the port for new connections and then spawns a new
thread to handle each connection. This mode 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 mode, MHD_USE_SELECT_INTERNALLY, uses
only a single thread to handle listening on the port and processing of
requests. This mode 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 mode can be a great choice. Note that MHD will
still start a single thread for itself – this way, the main program
can continue with its operations after calling MHD_daemon_start.
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 mode if you want to block on providing response data in the
callback, or the last mode if you want to use a more event-driven
mode with one big select loop.
The third mode combines a thread pool with
the MHD_USE_SELECT_INTERNALLY mode, which can benefit
implementations that require scalability. As said before, by default
this mode only uses a single thread. When combined with the thread pool option, it
is possible to handle multiple connections with multiple threads. The
number of threads is specified using the
MHD_OPTION_THREAD_POOL_SIZE; any value greater than one for
this option will activate the use of the thread pool. In contrast to
the MHD_USE_THREAD_PER_CONNECTION mode (where each thread
handles one and only one connection), threads in the pool can handle a
large number of concurrent connections. Using
MHD_USE_SELECT_INTERNALLY in combination with a thread pool
is typically the most scalable (but also hardest to debug) mode of
operation for MHD.
The fourth threading mode (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 threading modes.
struct MHD_Response
objects. A response consists of a set of HTTP headers and a (possibly
empty) body. The three main ways to create a response are either by
specifying a given (fixed-size) body
(MHD_create_response_from_data), by providing a function of
type MHD_ContentReaderCallback which provides portions of the
response as needed or by providing an open file descriptor
(MHD_create_response_from_fd). 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. Finally, using a file descriptor
can be used on Linux systems to use the highly efficient
sendfile call for the file transfer.
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 may be
delayed until sending of the response is complete on all connections
that have the response in the queue.
MHD_queue_response will fail (and return
MHD_NO).
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 mode 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.
