Low level HTTP server library in Rust

Overview

tiny-http

Build Status tiny_http on Crates.io

Documentation

Tiny but strong HTTP server in Rust. Its main objectives are to be 100% compliant with the HTTP standard and to provide an easy way to create an HTTP server.

What does tiny-http handle?

  • Accepting and managing connections to the clients
  • Parsing requests
  • Requests pipelining
  • Transfer-Encoding and Content-Encoding (not fully implemented yet)
  • Turning user input (eg. POST input) into a contiguous UTF-8 string (not implemented yet)
  • Ranges (not implemented yet)
  • HTTPS
  • Connection: upgrade (used by websockets)

Tiny-http handles everything that is related to client connections and data transfers and encoding.

Everything else (parsing the values of the headers, multipart data, routing, etags, cache-control, HTML templates, etc.) must be handled by your code. If you want to create a website in Rust, I strongly recommend using a framework instead of this library.

Installation

Add this to the Cargo.toml file of your project:

[dependencies]
tiny_http = "0.6"

Don't forget to add the external crate:

extern crate tiny_http;

Usage

use tiny_http::{Server, Response};

let server = Server::http("0.0.0.0:8000").unwrap();

for request in server.incoming_requests() {
    println!("received request! method: {:?}, url: {:?}, headers: {:?}",
        request.method(),
        request.url(),
        request.headers()
    );

    let response = Response::from_string("hello world");
    request.respond(response);
}

Speed

Tiny-http was designed with speed in mind:

  • Each client connection will be dispatched to a thread pool. Each thread will handle one client. If there is no thread available when a client connects, a new one is created. Threads that are idle for a long time (currently 5 seconds) will automatically die.
  • If multiple requests from the same client are being pipelined (ie. multiple requests are sent without waiting for the answer), tiny-http will read them all at once and they will all be available via server.recv(). Tiny-http will automatically rearrange the responses so that they are sent in the right order.
  • One exception to the previous statement exists when a request has a large body (currently > 1kB), in which case the request handler will read the body directly from the stream and tiny-http will wait for it to be read before processing the next request. Tiny-http will never wait for a request to be answered to read the next one.
  • When a client connection has sent its last request (by sending Connection: close header), the thread will immediately stop reading from this client and can be reclaimed, even when the request has not yet been answered. The reading part of the socket will also be immediately closed.
  • Decoding the client's request is done lazily. If you don't read the request's body, it will not be decoded.

Examples

Examples of tiny-http in use:

  • heroku-tiny-http-hello-world - A simple web application demonstrating how to deploy tiny-http to Heroku
  • crate-deps - A web service that generates images of dependency graphs for crates hosted on crates.io
  • rouille - Web framework built on tiny-http

License

This project is licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in tiny-http by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Comments
  • Relicense under dual MIT/Apache-2.0

    Relicense under dual MIT/Apache-2.0

    Hi, it would be cool to relicense tiny-http under the dual license terms MIT OR Apache-2.0 (at the choice of the licensees) that are common in the Rust community.

    To signify consent, please comment with the following:

    I agree with relicensing my contributions to this work to the dual MIT/Apache-2.0 license.
    

    Thanks!

    Contributor checkoff:

    • [x] @tomaka
    • [x] @frewsxcv
    • [x] @Eijebong
    • [x] @moises-silva
    • [x] @ashleysommer
    • [ ] @spk
    • [ ] @erickt
    • [x] @ebfe
    • [x] @PENGUINLIONG
    • [x] @zaneli
    • [x] @tomprogrammer
    • [x] @romanz
    • [x] @phildawes
    • [x] @ordepdev
    • [x] @nikolaplejic
    • [x] @mb64
    • [x] @djc
    • [x] @algesten
    opened by est31 18
  • Fix HTTPS request deadlock

    Fix HTTPS request deadlock

    Fixes #144.

    HTTPS requests were previously running into a deadlock when trying to respond to requests in cases:

    • To respond to the request, a lock needs to be obtained for the openssl TLS socket.
    • However, meanwhile, this code is using that lock to try to read any subsequent requests.
    • But no more requests are going to be sent by the browser until it gets a response to the first one!

    This modifies it to wait for each request to finish responding until it goes on to reading the next request. It works, but it's not perfect; here are some things it doesn't do:

    • It's potentially less parallelized with HTTPS than HTTP (but I'm not sure it's possible to do any better)
    • Responding to requests out of order with HTTPS won't work (this could conceivably be fixed with some check-is-ready-to-read to supply more requests if they're available)
    opened by mb64 12
  • [Question] How to create mock requests for writing tests?

    [Question] How to create mock requests for writing tests?

    As the title says, how would one go about creating mock requests for tests. The fields of tiny_http::Request are private so creating the struct does not work for me.

    opened by JonasRSV 10
  • Make Request testing easier

    Make Request testing easier

    Fixes #189.

    • Create MockRequest so downstream users can build Request-like objects for testing without exposing Request too much
    • Implement a builder pattern for MockRequest (i.e. the user can chain methods together to build the request they want)
    • Add into_reader() and headers() to Response so the user can inspect test results
    opened by bmgxyz 8
  • Fix RUSTSEC-2020-0031

    Fix RUSTSEC-2020-0031

    Without this fix:

    HTTP/1.1 400 Bad Request
    Server: tiny-http (Rust)
    Date: Sat,  2 Jan 2021 20:23:02 GMT
    Content-Type: application/json; charset=utf-8
    Content-Length: 163
    
    {"description":"could not read the body from the request, or could not execute the CGI program","cause":{"description":"Error while decoding chunks","cause":null}}
    

    With this fix:

    HTTP/1.1 400 Bad Request
    Server: tiny-http (Rust)
    Date: Sat,  9 Jan 2021 00:23:11 GMT
    Content-Length: 0
    

    Fixes #173.

    opened by therealbstern 8
  • what's the best way to test/match Method objects

    what's the best way to test/match Method objects

    I'm finding it awkward to construct and test Method objects. I've found myself doing clumsy things like:

    let get_ = tiny_http::Method::from_str("GET").unwrap();
    let put_ = tiny_http::Method::from_str("PUT").unwrap();
    if req.get_method().eq(&get_) || req.get_method().eq(&put_) { ... }
    

    is there a simpler way to construct and/or test values of type Method?

    It seems to me that modelling type Method as an enum might be simpler, easier and more efficient. Am I missing something?

    Still loving tiny-http! _Greg

    opened by GregDavidson 8
  • Add try_recv_timeout function to the server

    Add try_recv_timeout function to the server

    Please be warned I'm new to rust :)

    This allows giving up on receiving a request after a specified timeout duration.

    It's working for me.

    I wouldn't strictly need this if I knew how to kill/stop the thread pool from another thread and force the recv() to unblock. In C you can kill the thread and if blocked on a syscall you get an error back from the syscall, you can check EINTR and decide whether to quit or issue the syscall again. I'm not sure how one would implement such a thing in rust, so the next best thing was to simply timeout on recv() and I can check out on my app once in a while for a shutdown flag.

    opened by moises-silva 7
  • Unblock the accept thread on shutdown

    Unblock the accept thread on shutdown

    I'd like to find a better way, but, this works and is not completely awful, is it? :)

    If this is not acceptable I'd like to initiate a discussion on ideas on how to handle shutdown correctly. Currently if tiny-http is used in a loadable module (I am using it inside a project that can load/unload modules from an interactive command line a system administrator controls), when the server goes out of scope the socket lingers because the thread never terminates unless there's a new tcp connection received (accept is a blocking call).

    An alternative to this would be to put the socket in non-blocking mode and then somehow poll() or select() on it with a timeout to check every sec for the shutdown flag (close trigger bool).

    I may be wrong, but I don't see many downsides to this implementation. The Drop() call could hang for a bit on unusual situations like the server being inaccessible to itself (e.g 127 -> 127 firewall blocking or whatever), but the connection will timeout and move on. Most cases are better off with this as far as I can tell.

    Thoughts?

    opened by moises-silva 6
  • Add option to use rustls 0.20.

    Add option to use rustls 0.20.

    This a minor update of #155 to use the latest version of rustls. I think this is useful because it allows tiny-http to serve TLS on platforms that don't have OpenSSL, like OpenBSD.

    opened by ghost 5
  • Maintenance Status

    Maintenance Status

    Hi Devs,

    Thanks for all the work that's gone into this library over the last few years!

    I want to check if there are plans to keep maintaining this crate. I've noticed that minor PRs have been left untouched for months, and while @frewsxcv has been triaging issues here and there, and @rawler has been reviewing PRs, there hasn't been much movement in the repo beyond security fixes.

    I also saw that @tomaka said they were no longer maintaining the crate at all.

    I've been extensively using Rouille and thus tiny-http in production for some time now, so if you do want to put the crate up for adoption, or if you just want someone else to deal with the issues and PRs, I'm ready to help.

    opened by bradfier 5
  • Add unblock method for graceful shutdown

    Add unblock method for graceful shutdown

    I hit the following problem and saw it in the issues too (#146) : how do you gracefully shutdown the server ? There is effectively no way of breaking out of incoming_requests() other than receiving a client request.

    Rust favors message passing. We can't kill threads or send them signals Unix style. We can only pass messages between threads via channels to tell them to shut down on their own (or with synchronization primitives such as condvar, or with shared memory under lock). After some research, it turns out the standard library does blocking IO (ie the accept method on TcpListener used by tiny-http). There really is no way to break out of it except with a client request (or on error). This is already dealt with by a previous commit by @moises-silva (cde7981) : on object destruction we briefly connect to the server to unblock the thread stuck on accept. (side note : for async IO look for mio)

    But a for loop on incoming_requests it still blocking. It's not stuck on accept but inside the message queue waiting on condvar for new client requests. This commit adds a special request variant that says to unblock the loop and return no client request (since there is none we just want to shutdown). I slightly modified the message_queue API (ie the pop method now returns an Option), which is internal. There are no changes on the public side, ie on server, except the addition of the unblock method that effectively unblocks one thread stuck in incoming_requests (or recv).

    Since there is no breaking change to the public API, all existing code work as previously. The addition of unblock() allows to implement graceful server shutdown by calling it from another thread. Hopefully the two tests added make its usage clear. Let me know what you think.

    opened by guillaumekoenig 5
  • Issue 56 - Add limit to size of headers

    Issue 56 - Add limit to size of headers

    Hello, I think it is required to not handle http headers and header fields of any size the clients might provide. (DOS, OOM)
    This PR limits the header body to 8192 bytes and the header lines to 2048 bytes. Popular servers (apache, nginx) have similar restrictions.

    When a client is going over the limits the HTTP status 431 Request Header Fields Too Large is returned.

    I've seen that it has been already the intention in #56 to implement this.
    I hope this PR is welcome.

    opened by kolbma 2
  • Support for unbuffered writes

    Support for unbuffered writes

    Hello, this PR aims to tackle one problem I had: streaming the output of a program while it is running over HTTP, similarly to the Github/GitLab CI "live" screens. In fact, the goal is to perform a request to the server with cURL inside a gitlab-ci job, and see the output unfolds as the program is executed:

    
                  web browser
    ----------    ------------> -------------------
    | CLIENT |                  |  GitLab CI job  |
    ----------   <------------  -------------------
                   streams the     |              ∧
                      output       |              |
                                   | executes     | prints the
                                   |              | output
                                   |              | "live"
                                   ∨              |
                                 -------------------
                                 |       cURL      |
                                 -------------------
                                  |               ∧
                                  |               | streaming
                                  | HTTP          | (chunked
                                  | query         | transfer)
                                  |               | of stdin
                                  |               | and stdout
                      spawns      ∨               |
    -----------  <------------   --------------------
    | program |                  | tiny-http server |
    -----------   ------------>  --------------------
                   sends stdout
                   and stdin in
                     a pipe
    

    Without this patch, the program executes in its entirety, and the output is sent all at once once the pipe where the program writes its output is closed.

    To achieve that goal, I submit two "sub-features":

    • The ability to disable buffering inside Response objects with the Response::with_buffered method. Enabling this will force the transfer encoding to be TransferEncoding::Chunked and will ask the chunks encoder to flush to its underlying writer on every write.
    • To get "instantaneous" write, disabling buffering in the chunks encoder is not enough, as the underlying writer returned when calling Server::recv() (ClientConnection.sink) is in fact a BufWriter wrapping the "real" output. The buffered_writer option in ServerConfig, when set to false while instantiating a new server, omits the BufWriter to write to the TcpStream withotu any buffering. The cost of that abstraction is that ClientConnection.sink now boxes the writer to be able to choose between BufWriter<RefinedTcpStream> or RefinedTcpStream dynamically, which means there is now one additional pointer deference. I do however expect the performance impact to be small as this pointer is then stored in an Arc<Mutex<>>, and I think locking/unlocking the mutex should be more costly that deferencing the pointer.

    I expect this to decrease performance when sending big files, which is why these two sub-features are disabled by default, and must explicitly be opted-in (by calling the with_buffered method for the first, and by instanciating the server with the buffered_writer setting for the second).

    Also note that the current iteration of this work breaks the current ABI, as it updates ServerConfig to add the buffered_writer option, and ServerConfig was already exposed through the Server::new function.

    opened by nightmared 0
  • Custom transports

    Custom transports

    See #172 and so on.

    This would also allow more flexibility with TLS, including TLS authentication (client certs? TLS-SRP? TLS-OPAQUE?). But the main use-case is still unix sockets and other transports.

    opened by SoniEx2 0
  • Use bounded thread pool

    Use bounded thread pool

    Server:: from_listener creates a util::TaskPool which has no limit on the number of threads. This makes tiny-http trivially vulnerable to thread exhaustion. Combined with #220, this behavior means that a single overload causes total and permanent server failure.

    opened by mleonhard 10
  • Continue serving requests after failing to spawn a thread

    Continue serving requests after failing to spawn a thread

    When the server fails to spawn a thread, a mutex gets poisoned and the server stops handling requests. It does not close its socket and Server::run does not panic.

    The mutex that gets poisoned is util::TaskPool.sharing.todo. TaskPool::spawn holds it while calling TaskPool::add_thread which can panic.

    Let's change it to handle thread spawn failure.

    • Wait for an existing thread to become free and then hand the request to it.
    • If there are no threads, sleep for 100ms and then try to spawn again.
    opened by mleonhard 3
Releases(0.12.0)
  • 0.12.0(Oct 6, 2022)

    • Bumped the minimum compiler version tested by CI to 1.56 - this is necessary due to an increasing number of dependencies introducing Cargo manifest features only supported on newer versions of Rust.

    • Add support for UNIX sockets Thanks to @ColonelThirtyTwo for adding support for binding to UNIX sockets when creating a tiny-http server. This change makes a few small breaking API modifications, if you are constructing ServerConfig manually you will need to use the new ListenAddr type rather than directly supplying a net::SocketAddr. Likewise Server::server_addr() will now return an enum that can represent either a TCP socket or a UNIX socket.

      Finally Request::remote_addr() now returns an Option<&SocketAddr> as UNIX sockets don't ever have a remote host.

    • Reduce required dependencies by switching to httpdate @esheppa replaced our internal HTTPDate type with the httpdate library (used extensively in the community by Hyper, Tokio and others) which reduces our baseline dependency tree from 18 crates to 5!

    • TestRequest::path no longer has a 'static bound, allowing for fuzzers to generate test request paths at runtime.

    • Unpinned zeroize so it can float around any stable ^1 version.

    New Contributors

    • @ColonelThirtyTwo made their first contribution in https://github.com/tiny-http/tiny-http/pull/224
    • @nhynes made their first contribution in https://github.com/tiny-http/tiny-http/pull/226
    • @ruuda made their first contribution in https://github.com/tiny-http/tiny-http/pull/225
    • @esheppa made their first contribution in https://github.com/tiny-http/tiny-http/pull/228

    Full Changelog: https://github.com/tiny-http/tiny-http/compare/0.11.0...0.12.0

    Source code(tar.gz)
    Source code(zip)
  • 0.11.0(Feb 25, 2022)

    • Add support for Rustls

      Thanks to @3xmblzj5 and @travispaul for their help in implementing Rustls as a drop-in replacement for OpenSSL, you can now build tiny-http with TLS support without any external dependencies! OpenSSL will remain the default implementation if you just enable the ssl feature, but you are strongly encouraged to use ssl-rustls where possible!

    • Fix incorrect certificate chain loading

      Fix a longstanding bug where we were only loading the first (i.e. the leaf) certificate from any PEM file supplied by the user.

    Source code(tar.gz)
    Source code(zip)
  • v0.10.0(Jan 12, 2022)

    • Replace chrono with time-rs

      chrono was only used to store and format DateTime into the slightly odd format required by RFC 7231, so to avoid the numerous RUSTSEC advisories generated by the localtime_r issue, we can just drop it entirely and switch to time-rs. Unfortunately this means we need to bump our minimum tested compiler version to 1.51, and as such this change requires a full minor release.

    Source code(tar.gz)
    Source code(zip)
  • 0.9.0(Oct 14, 2021)

    • Rust 2018 Refactor

    • Enable prompt responses, before the request has been fully read

      This isn't an API change, but does result in different behaviour to 0.8.2 and so justifies a minor version bump.

      HTTP requests now return a boxed FusedReader which drops the underlying reader once it reaches EOF, such that the reader no longer needs to be explicitly consumed and the server may now respond with e.g. a "413 Payload too large" without waiting for the whole reader.

    • Bumped the minimum compiler version tested by CI to 1.48 (the version supported in Debian Bullseye)

    Source code(tar.gz)
    Source code(zip)
  • 0.6.4(May 11, 2021)

    • Don't honour client TE for 1xx or 204 responses

      Where we're sending an Informational (1xx) or No Content (204) response, per the RFC we should never set a Transfer-Encoding header, regardless of what the client supplied in its TE header.

    Source code(tar.gz)
    Source code(zip)
Simple http server in Rust (Windows/Mac/Linux)

How it looks like? Screenshot Command Line Arguments Simple HTTP(s) Server 0.6.1 USAGE: simple-http-server [FLAGS] [OPTIONS] [--] [root] FLAGS:

LinFeng Qian 788 Dec 28, 2022
Akasio is a simple HTTP server that redirects traffic based on a JSON redirect table. This is its Rust implementation.

This page is inaccurate and is pending updates. Akasio (Rust) Description Akasio is a simple HTTP server that redirects traffic based on a JSON redire

K4YT3X 5 May 2, 2022
Archibald is my attempt at learning Rust and writing a HTTP 1.1 web server.

Archibald To be a butler, is to be able to maintain an even-temper, at all times. One must have exceptional personal hygiene and look sharp and profes

Daniel Cuthbert 4 Jun 20, 2022
Host These Things Please - a basic http server for hosting a folder fast and simply

http Host These Things Please - a basic HTTP server for hosting a folder fast and simply Selected features See the manpage for full list. Symlinks fol

thecoshman 367 Dec 23, 2022
Fully async-await http server framework

Saphir is a fully async-await http server framework for rust The goal is to give low-level control to your web stack (as hyper does) without the time

Richer Archambault 83 Dec 19, 2022
Node.js http server framework powered by Hyper native binding.

hnsjs POC project. Install this test package yarn add @hnsjs/core Support matrix node10 node12 node14 node15 Windows x64 ✓ ✓ ✓ ✓ Windows x32 ✓ ✓ ✓ ✓

LongYinan 18 Nov 23, 2022
RUSTENGINE is the high-assurance HTTP server.

RUSTENGINE Table of Contents RUSTENGINE Table of Contents About RUSTENGINE Inspiration with Rust Features Compares with Nginx Build & Run About this R

FUNNY SYSTEMS 10 Aug 27, 2021
OxHTTP is a very simple synchronous HTTP client and server

OxHTTP is a very simple synchronous implementation of HTTP 1.1 in Rust. It provides both a client and a server.

Oxigraph 13 Nov 29, 2022
A synchronous HTTP server built on hyper.

Astra Astra is a synchronous HTTP server built on top of hyper. use astra::{Body, Response, Server}; fn main() { Server::bind("localhost:3000")

Ibraheem Ahmed 23 Nov 27, 2022
Operator is a web server. You provide a directory and Operator serves it over HTTP.

Operator Operator is a web server. You provide a directory and Operator serves it over HTTP. It serves static files the way you'd expect, but it can a

Matt Kantor 6 Jun 6, 2022
An HTTP library for Rust

hyper A fast and correct HTTP implementation for Rust. HTTP/1 and HTTP/2 Asynchronous design Leading in performance Tested and correct Extensive produ

null 11k Jan 7, 2023
Live Server - Launch a local network server with live reload feature for static pages

Live Server - Launch a local network server with live reload feature for static pages

Lomirus 18 Nov 30, 2022
Static Web Server - a very small and fast production-ready web server suitable to serve static web files or assets

Static Web Server (or SWS abbreviated) is a very small and fast production-ready web server suitable to serve static web files or assets.

Jose Quintana 496 Jan 2, 2023
high (er) level language and compiler targeting the mindustry logic language

Copper Copper is a high level language and compiler that compiles to mindustry logic. The syntax is similar to rust, with some differences. (these wil

Rowan 2 Jun 27, 2022
[OUTDATED] A light HTTP framework for Rust

Rustful A light HTTP framework for Rust, with REST-like features. The main purpose of Rustful is to create a simple, modular and non-intrusive foundat

Erik Hedvall 873 Nov 12, 2022
:zap: fast http framework for rust

zap ⚡ The mission of zap is, to deliver a basic, but fast rust web server library. Documentation About This code is based on tokio's minihttp project,

Daniel Oltmanns 51 Jun 7, 2022
service_policy_kit is a Rust based toolkit for verifying HTTP services against policies.

Service Policy Kit service_policy_kit is a Rust based toolkit for verifying HTTP services against policies. You can: Build a complete testing framewor

null 19 Dec 5, 2022
🌟 For when you really just want to serve some files over HTTP right now!

miniserve - a CLI tool to serve files and dirs over HTTP For when you really just want to serve some files over HTTP right now! miniserve is a small,

Sven-Hendrik Haase 4.1k Dec 31, 2022
Add Facebook and Google authentication to your HTTP REST API in Actix-web

I created this project while learning Rust. Project shows how to handle Facebook and Google token verification in Rust using Actix-Web. Hope this help

null 37 Dec 31, 2022