nanohttp/lib.rs
1//! # nanohttp
2//!
3//! `nanohttp` is a small zero-dependency library for parsing HTTP requests and building HTTP
4//! responses.
5//!
6//! It is intended purely as an implementation of the HTTP protocol, and therefore does not
7//! handle things like routing, json serialization and deserialization, or building a HTTP server.
8//! See the examples below for how you can use it in combination with a TCP server and a runtime
9//! library such as [tokio](https://docs.rs/tokio/latest/tokio/) or
10//! [async-std](https://docs.rs/async-std/latest/async_std/) to build a custom HTTP server.
11//!
12//! This library is intended to abstract away the details of dealing with HTTP, without removing
13//! the need to understand how HTTP works at a high level. For example there are a few helper
14//! methods which will automatically set relevant headers. But for the most part, it is up to the
15//! consumer of the library to ensure that the correct headers are set, and generally ensure that
16//! the constructed HTTP response is valid. An example of this is ensuring that the `Location`
17//! header is set when returning a `303` response code.
18//!
19//! ## Examples
20//!
21//! Parse an incoming HTTP request.
22//!
23//! ```
24//! use nanohttp::{Request, Method};
25//!
26//! let req = "GET / HTTP/1.1\r\n";
27//! let res = Request::from_string(req).unwrap();
28//!
29//! assert_eq!(res.method, Method::GET);
30//! assert_eq!(res.path.uri, "/");
31//!
32//! ```
33//!
34//! Build a HTTP response, and convert it to a valid HTTP message.
35//!
36//! ```
37//! use nanohttp::{Response, Status, Header};
38//!
39//! let html = "<html><head></head><body><h1>Hello, world!</h1></body></html>";
40//! let res = Response::body(html)
41//! .header(Header::new("Content-Type", "text/html"))
42//! .header(Header::new("Content-Length", &html.len().to_string()))
43//! .status(Status::Ok);
44//!
45//! assert_eq!(res.to_string(), "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: 61\r\n\r\n<html><head></head><body><h1>Hello, world!</h1></body></html>");
46//!
47//! ```
48//!
49//! Use `nanohttp` to build a custom TCP server using only the
50//! [async-std](https://docs.rs/async-std/latest/async_std/) crate as a dependency.
51//!
52//! ```
53//! use std::str::from_utf8;
54//!
55//! use async_std::io::{ReadExt, WriteExt};
56//! use async_std::net::{TcpListener, TcpStream};
57//! use async_std::task;
58//!
59//! use nanohttp::{Method, Status, Request, Response};
60//!
61//! async fn handler(req: Request) -> Response {
62//! match req.path.uri.as_str() {
63//! "/" => match req.method {
64//! Method::GET => Response::empty().status(Status::Ok),
65//! _ => Response::empty().status(Status::NotAllowed),
66//! },
67//! "/hello" => match req.method {
68//! Method::GET => {
69//! let html = "<html><head><title>Hello, world!</title></head><body><h1>Hello, world!</h1></body></html>";
70//! Response::content(html, "text/html").status(Status::Ok)
71//! },
72//! _ => Response::empty().status(Status::NotAllowed),
73//! },
74//! _ => Response::empty().status(Status::NotFound),
75//! }
76//! }
77//!
78//! async fn handle_connection(mut connection: TcpStream) {
79//! let mut buffer = [0; 1024];
80//!
81//! connection.read(&mut buffer).await.unwrap();
82//!
83//! let req_text = from_utf8(&buffer).unwrap().trim_end_matches("\0");
84//!
85//! let req = Request::from_string(req_text).unwrap();
86//! let res = handler(req).await.to_string();
87//!
88//! let res_bytes = res.as_bytes();
89//!
90//! connection.write(res_bytes).await.unwrap();
91//! connection.flush().await.unwrap();
92//! }
93//!
94//! #[async_std::main]
95//! async fn main() {
96//! let listener = TcpListener::bind("127.0.0.1:8000").await.unwrap();
97//!
98//! loop {
99//! let (connection, _) = listener.accept().await.unwrap();
100//! task::spawn(async move {
101//! handle_connection(connection).await;
102//! });
103//! }
104//! }
105//! ```
106
107mod error;
108mod header;
109mod method;
110mod request;
111mod response;
112mod status;
113
114pub use error::{Error, ErrorType};
115pub use header::Header;
116pub use method::Method;
117pub use request::{Path, Request};
118pub use response::Response;
119pub use status::Status;