Skip to content

flavify/Webserv

Repository files navigation

Webserv

Description

🌐 Webserv is a fully custom HTTP server written in C++17, designed to provide a deep understanding of the Hypertext Transfer Protocol (HTTP). Inspired by the principles and architecture of industry-standard servers like NGINX, this project was built from scratch to handle HTTP requests and responses, implement core web server functionality, and include advanced features such as file uploads, CGI execution, and serving static websites.

Much like NGINX, Webserv is designed to be:

  • πŸ›‘οΈ Resilient: Built to handle stress tests and high traffic without crashing.
  • ⚑ Efficient: Implements non-blocking I/O using poll() for scalable performance.
  • πŸ› οΈ Flexible: Supports multiple ports, virtual hosts, and customizable configurations.

Our implementation covers all mandatory requirements and extends functionality with bonus features for an enhanced user experience. Designed to be robust and fully compliant with HTTP 1.1 standards, Webserv has been rigorously tested against browsers and benchmarking tools like Siege, offering a solid foundation for anyone looking to explore or build modern web servers.

πŸ’‘ In essence, Webserv provides a simplified yet powerful approach to understanding and replicating the core functionalities of a web server like NGINX.

Table of Contents

  1. Description
  2. Lifecycle
  3. Prerequisites
  4. Installation
  5. Features
  6. Configuration
  7. Technical Details
  8. Testing and Benchmarking
  9. Curl Examples

Lifecycle

Prerequisites

  • C++17 Compiler: Ensure a compatible compiler is installed.
  • Make: Required for building the project.
  • Docker: Optional, for containerized deployment.

Installation

  1. Clone the Repository:
git clone https://github.com/dendeaisd/Webserv.git
cd Webserv
  1. Build the Server:
make
  1. Run the Server:
./webserv [configuration file]

If no configuration file is specified, it defaults to ./configs/default.conf.

Docker Deployment

To run the server in a Docker container:

make docker-run

Features

  • HTTP Methods: Supports GET, POST, PUT, etc. methods
  • Non-Blocking I/O: Utilizes poll() for efficient client handling.
  • Static File Serving: Delivers HTML, CSS, JavaScript, and image files.
  • File Uploads: Allows clients to upload files to the server and download them.
  • CGI Support: Executes scripts in various languages (e.g., Python, PHP, Ruby) based on configuration.
  • Custom Error Pages: Provides user-friendly error messages.
  • Cookies and Session Management: Implements stateful sessions; demonstrated with a To-Do application.

🌟Default Landing Page

Upon starting the server, the default landing page (IRIDESCENT) is accessible at:

http://localhost:[port]

Screenshot 2024-11-26 024810

Here you can see example of the features of the project like trying our ToDo App, the uploads page or various scripts showcasing the functionality of the CGI, when you open the menu on the top-right side of the page.

πŸ“‚ Serving Static Files

Example: Visit a static file served by the server.

http://localhost:[port]/index.html

Add your static HTML, CSS, and JS files in the directory defined in the root configuration.

πŸ“€ File Uploads

Upload files directly through the Uploads interface on the default page or via HTTP POST.

http://localhost:[port]/upload

πŸ’» CGI Execution

Run dynamic scripts written in various languages (e.g., Python, Perl, Ruby, Bash). Examples are available directly on the default page. Select a script to see its execution in real-time.

Examples:

  • Python Script: http://localhost:[port]/cgi-bin/hello.py
  • Ruby Script: http://localhost:[port]/cgi-bin/hello.rb

πŸ“ To-Do App

Explore a fully functional To-Do application that showcases cookie-based session management. Add, remove, or manage tasks, with session persistence.

http://localhost:[port]/todo

🚦 Custom Error Pages

Trigger custom error responses by accessing routes with missing permissions or non-existent resources.

Examples:

Screenshot 2024-11-26 033634

Screenshot 2024-11-26 033606

Screenshot 2024-11-26 033706

Configuration

The server's behavior is controlled by a configuration file that defines various settings, such as ports, error pages, routes, and upload locations. Below is an example of a configuration file and its features:

Example Configuration: default.conf

# Define server block
server {
  listen 8080;
  server_name localhost;

  # Root directory for the server
  root /var/www/html;

  # Default error pages
  error_page 404 /error_pages/404.html;
  error_page 403 /error_pages/403.html;

  # Route configuration
  location / {
    autoindex on;
    index index.html;
  }

  # File upload settings
  location /upload {
    upload_store /var/www/upload;
    upload_pass /cgi-bin/upload.cgi;
  }
}

Key configurations options

  • listen: Specifies the port the server will listen to.
  • server_name: Defines the host or domain name.
  • root: Sets the root directory from which files will be served.
  • error_page: Maps HTTP error codes (e.g., 404, 403) to custom error pages.
  • location: Defines specific routing behaviors:
  • autoindex: Enables directory listing if no index file is found.
  • index: Specifies the default file to serve when a directory is accessed.
  • upload_store and upload_pass: Configure file upload handling. This file serves as a template to demonstrate how to use the configuration system.

Additional configurations can be added to enable more advanced features like for example CGI handling.

Technical Details

The Webserv project is built using C++17, following object-oriented programming principles and modular design. Below is an overview of its core structure and how the server operates.

Entry Point: main.cpp

The server starts in main.cpp, where it:

  1. Processes the Command-Line Arguments:

    • Accepts an optional configuration file path as an argument.
    • Defaults to ./configs/default.conf if no argument is provided.
    • Validates the presence of the configuration file using access().
  2. Parses the Configuration File:

    • The ParseConfigFile class is used to read and validate the configuration file.
    • If the configuration is invalid or missing, the program exits with an error message.
  3. Initializes Components:

    • Logging: Configures logging using the Log singleton.
    • CGI Manager: Configures CGI routes via the CGIFileManager class.
  4. Starts the Server:

    • Creates and runs an instance of the Server class, passing the parsed configuration.

Exception Handling

main.cpp includes error handling to capture and log:

  • Socket Errors (e.g., binding or listening issues).
  • Poll Manager Errors (e.g., issues with non-blocking I/O).
  • General Exceptions for any unforeseen issues during runtime.

Modular Design

The project employs a modular structure for clear separation of concerns:

  • Networking: Managed by the Server class and supporting components.
  • Configuration: The ParseConfigFile class handles configuration parsing and validation.
  • Logging: The Log singleton enables debug-level logging for easier troubleshooting.
  • CGI Management: The CGIFileManager handles dynamic content and script execution.

To bypass chrome CORS policy

Paste this in chrome and disable the attr: chrome://flags/#block-insecure-private-network-requests

reference: https://developer.chrome.com/blog/cors-rfc1918-feedback

Benchmarking with siege

make docker-run
make re
./webserv
siege -b -c 100 -t 1m -T 2S http://127.0.0.1:8080/benchmark

Curl with detailed reporting

let's agree, curl is cute

curl -v -s -w "\n-------\n\nDNS Lookup: %{time_namelookup}\nConnect: %{time_connect}\nStart Transfer: %{time_starttransfer}\nTotal: %{time_total}\n" http://localhost:8080/cgi-bin/blocking.py

curl -o /dev/null -s -w "DNS Lookup: %{time_namelookup}\nConnect: %{time_connect}\nStart Transfer: %{time_starttransfer}\nTotal: %{time_total}\n" http://localhost:8080/cgi-bin/blocking.py

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •