/webserv

A high-performance, non-blocking C++ web server emulating NGINX functionality

Primary LanguageC++GNU Affero General Public License v3.0AGPL-3.0

Webserv

GIF showing an interactive website served with Webserv

Table of Contents


Overview

Webserv is a high-performance, non-blocking web server designed to replicate NGINX's functionality.
Developed in C++ for MacOS and Linux, it serves static websites, supports large file uploads and downloads, and is configurable to a high degree, just like NGINX.
It implements the HTTP protocol standards as defined in RFC 9112, RFC 9110, and RFC 3986.

Features

  • Multiple virtual servers IPv4 & IPv6 compatibles
  • Customizable route serving, error pages, redirections, response codes
  • Default index files for directory requests
  • Limit on allowed request methods & client body size, directory listing on/off toggling
  • CGI support for external program execution (RFC 3875)
  • PHP and Perl interactive website examples with cookie and session management
  • Multiple testers allowing a perfect CI flow

Installation

source configure && make install

You can change the installation directory with the INSTALLDIR variable in the configure file. By default, it is installed in $HOME/.local.


Usage

webserv [configuration file]

Provide your own configuration file as first argument. Without it, $INSTALLDIR/etc/webserv/default.conf is used as the default one.
The file default.conf of this repository is used to run all the provided tests and examples.

The server root is the $INSTALLDIR/var/www/webserv directory. After installation, it is a copy of the www directory of this repository.
As with NGINX, use the root or alias directives in the virtual servers of your configuration file, to set a custom relative or absolute path for the files served in response to a request.

How requests are processed

The requested are processed the same way as NGINX:

  1. Virtual servers listen to an address[:port] pair. If no port is given, they listen on port 8000. Without a given listen directive, they listen to *:8000.
  2. When a request reaches the web server through an address[:port] pair, the server_name directive selects which corresponding virtual server will serve it. If the request’s Host header field does not match any virtual server name, the first virtual server with a matching address[:port] is used.
  3. The selected virtual server searches for the most specific prefix location regardless of the listed order. Then it checks nested extension locations in the order listed. The first matching expression is the location used. If no expression matches the request, then the most specific prefix location found earlier is used.

Configuration

The configuration file's structure is the same as the NGINX structure, with only the server{} and location{} blocks.

The directives are inherited: a child context inherits the settings of its parent level. For example, a server{} block directive is inherited by all the location{} blocks in it. However, when the same directive is defined again in a child context, it overrides the parent value.

Here are all the directives
Directive
(links to NGINX version)
Syntax Default Informations
listen listen address[:port]; listen *:8000; An address may be a hostname, a IPv4, or a IPv6 in square brackets (e.g.[::1]).
server_name server_name name ...; server_name ""; Names are case-insensitive. An IP is also a valid name.
root root path; root html; Sets the root directory for requests.
alias alias path; / Defines a replacement for the specified location.
index index file; index index.html; Defines a file used as an index.
return return code [text]; / return code URL; / return URL; / Specifies a redirect URL (for codes 301, 302, 303, 307, and 308) or the response body text (for other codes). A redirect URL can be a URI local to this server.
error_page error_page code ... uri; / Defines the URI that will be shown for the specified error(s).
cgi_pass cgi_pass path; / Defines a script to execute for requests at this specific location.
client_max_body_size client_max_body_size size; / Sets the maximum allowed size of the client request body.
ignore_except ignore_except method ...; / Ignores the location match for requests with the given method(s).
limit_except limit_except method ...; / Returns 403 for requests with the given method(s).
hide_limit_rule hide_limit_rule on / off; hide_limit_rule off; Returns 405 instead of 403 for requests hitting limit_except.
autoindex autoindex on / off; autoindex off; Enables or disables the directory listing output.
hide_directory hide_directory on / off; hide_directory off; Returns 404 instead of 403 for requests hitting a directory without autoindex.

Debugging and Logs

make debug

The compiled debug version is the webserv_debug binary at the root of this repository. It has far more verbose and helpful logs.

Logs are stored in $INSTALLDIR/var/log/webserv.log, and in /tmp/webserv.log for the debug version.
If their size exceeds 20MB, they rotate in a new file, appending “.old“ to the previous one.


Testing

Three testing suites are provided:

  • An extensive Python tester for HTTP protocol and configuration directives compliance
  • A 42 tester for load stress-testing and large file exchanges with multiple clients
  • A GoogleTest suite for configuration parsing and possible directives' values

Run the tests from the root of this repository with:

./tests/run_tests.sh

To enable the GoogleTest suite, you need to have CMake installed, then run:

make test

Important

To run correctly, the testers expect the default.conf file of this repository, and $INSTALLDIR/var/www/webserv to have at least the content of the www directory of this repository.

Testers.mp4

Uninstallation

Tip

source configure -u

This unsets the webserv-specific environment variables, cleans the PATH variable if relevant, removes the installed binary, and all the webserv-related files (after asking for confirmation).

Caution

make uninstall

This removes the installed binary, the $INSTALLDIR/etc/webserv configuration directory, and the $INSTALLDIR/var/www/webserv directory serving your files (without asking for confirmation).


Documentation

For more details on the HTTP protocol: