This repository contains a simple implementation of an HTTP server using Rust. It is intended to be used as a tool for learning the basics of Rust, intentionally leaving some of the basic server functionality unimplemented so that developers can build off of this implementation and further their understanding of Rust.
This section provides supporting steps and documentation for developing locally.
Before jumping into the code, there are a few prerequisites.
-
Local development should be done from a UNIX-based machine - use Linux, MacOS, or WSL2 if you're on a Windows machine.
-
GitHub access should be managed through an SSH key in your UNIX environment. If you're unfamiliar with this process start here.
-
pre-commit should be installed globally on your machine for linting and validating your code prior to pushing up to GitHub.
-
Rust should be installed globally on your machine for compiling and running code.
-
Optionally, the Rust-Analyzer extension can be installed in VS Code for a better development experience.
-
Clone the repository (if this is your first time).
git clone git@github.com:dgonzo27/rust-http.git
-
Navigate into the repository directory.
cd rust-http
-
Ensure pre-commit is enabled for this repository.
pre-commit install
-
Compile the Rust code.
cargo build
-
Run the Rust code.
cargo run
-
Test out the routes defined in
src/website_handler.rs
from your browser.-
127.0.0.1:8080
-
127.0.0.1:8080/hello
-
-
Test out a traversal attack from a new terminal window.
echo "GET /../../../../../proc/meminfo HTTP/1.1\r\n" | nc 127.0.0.1 8080
-
Stop the server.
ctrl + c
-
Run pre-commit against all files.
pre-commit run --all-files
This section provides guidance on furthering this solution to make it more robust.
HTTP requests and responses are implemented in the src/http/request.rs
and src/http/response.rs
files, respectively. Line 33 of the src/http/request.rs
file shows an example string slice we can expect to receive from our request buffer:
GET /search?name=rustacean&sort=1 HTTP/1.1\r\nHEADERS
In our current implementation, the HTTP headers are ignored in both the request and response. A great first task would be to extend the implementation so that these headers can be read and returned properly.
The implementation of our server exists in the src/server.rs
file. This implementation is based on a single thread, which is not best practice in a production-scenario. Explore the thread and sync modules from the Rust standard library and convert the single-threaded server into a multi-threaded server.
After getting familiar with multi-threaded principles, you are encouraged to dive into the world of asynchronous Rust. A popular asynchronous runtime for Rust is called Tokio. It's been built and used by large organizations like AWS, Azure, Discord, Facebook, Dropbox and more - so be sure to check it out!