HTTP/1.1 compatible web server in C++ using I/O multiplexing.
Webserv is crafted as part of the challenging curriculum at School 42, focusing on developing a HTTP server in C++ 98. Key requirements include:
- Non-blocking socket read/write using
poll()
(or equivalent). - Ensure the server never blocks(non-blocking I/O is necessary).
- Ensure the server never hangs indefinitely.
- Ability to serve a fully static website.
- Support for GET, POST, and DELETE methods.
- Capability to listen to multiple ports. These elements combine to create a robust, efficient web server.
- Languages: C++ 98, Makefile
- Web Technologies: HTML, CSS
- Additional Tools: Python
- Programming Concepts: Object Oriented Programming, Non-block I/O, I/O Multiplexing (kqueue), HTTP/1.1
http {
error_page 404 500 413 ./www/error/default.html;
index index.html ;
autoindex on;
server {
server_name localhost:4000;
listen 4000;
location / {
alias ./www/example/;
limit_except POST GET DELETE;
location /box/ {
limit_except GET;
}
}
location /abc/ {
alias ./www/example/;
}
}
server {
listen 42;
client_max_body_size 100;
location / {
alias ./www/example/;
}
}
}
This is how this program flows. Server, client sockets, and children’s PID are registered to kqueue.
- Server can process multiple requests simultaneously: We used
pipe()
to communicate with CGI processes. Whenever the buffer is full, the server registers an event(EVFILT_WRITE
) tokqueue
and moves on to another event inkqueue
- An idea from round-robin algorithm: Since we can queue events by using
kqueue(epoll)
, the server slices its I/O. However, we did not set timeout to maximize throughput.
- HTTP/1.1 Compliant: Supports GET, POST, and DELETE methods, along with features like HTTP pipelining and cookies.
- Nginx-like Configuration: Tree-shaped parsing for nested bracket
{}
configurations, resembling Nginx. - Efficient Configuration Access: A sophisticated mapping system reduces access time from O(N) to O(log N).
- Unblocking I/O: Since the server should support multiple requests simultaneously, I/O never falls into blocking mode.
- Class Destruction: Implemented smart pointers for efficient object management, adapting to C++ 98's limitations.
- Forking and Multithreading: Refined our approach to meet project requirements, gaining insights into process creation and management in Linux.
- Parsing Complexity: Developed efficient parsing strategies for both configuration files and HTTP requests. For configuration parsing, we've used bitmask to make the logic as simple as possible. For HTTP request paring, we used Nekipelov’s httpparser and modified it to fit our usage. That helped us a lot. Thank you!
Ensure you have a macOS environment and a C++ 98 compiler.
- Clone the repository:
git clone [repository link]
- Compile the project:
make re
at the root directory. - Run the server:
./webserv configs/example.conf
|
This project was a deep dive into web server mechanics, leveraging C++ with OOP and I/O multiplexing. Our journey was marked by constant problem-solving and code refinement, enhancing our collaboration and communication skills. Despite some initial challenges, the final product is a testament to our perseverance and commitment to learning.
Nginx
RFC 2616
RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1
HTTP Parser
GitHub - nekipelov/httpparser: HTTP request, response and urls parser
Kernel Queue
Kernel Queue: The Complete Guide On The Most Essential Technology For High-Performance I/O
MIT License