dbs_uhttp/lib.rs
1// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3#![deny(missing_docs)]
4//! Minimal implementation of the [HTTP/1.0](https://tools.ietf.org/html/rfc1945)
5//! and [HTTP/1.1](https://www.ietf.org/rfc/rfc2616.txt) protocols.
6//!
7//! HTTP/1.1 has a mandatory header **Host**, but as this crate is only used
8//! for parsing API requests, this header (if present) is ignored.
9//!
10//! This HTTP implementation is stateless thus it does not support chunking or
11//! compression.
12//!
13//! ## Supported Headers
14//! The **dbs_uhttp** crate has support for parsing the following **Request**
15//! headers:
16//! - Content-Length
17//! - Expect
18//! - Transfer-Encoding
19//!
20//! The **Response** does not have a public interface for adding headers, but whenever
21//! a write to the **Body** is made, the headers **ContentLength** and **MediaType**
22//! are automatically updated.
23//!
24//! ### Media Types
25//! The supported media types are:
26//! - text/plain
27//! - application/json
28//!
29//! ## Supported Methods
30//! The supported HTTP Methods are:
31//! - GET
32//! - PUT
33//! - PATCH
34//!
35//! ## Supported Status Codes
36//! The supported status codes are:
37//!
38//! - Continue - 100
39//! - OK - 200
40//! - No Content - 204
41//! - Bad Request - 400
42//! - Not Found - 404
43//! - Internal Server Error - 500
44//! - Not Implemented - 501
45//!
46//! ## Example for parsing an HTTP Request from a slice
47//! ```
48//! use dbs_uhttp::{Request, Version};
49//!
50//! let request_bytes = b"GET http://localhost/home HTTP/1.0\r\n\r\n";
51//! let http_request = Request::try_from(request_bytes, None).unwrap();
52//! assert_eq!(http_request.http_version(), Version::Http10);
53//! assert_eq!(http_request.uri().get_abs_path(), "/home");
54//! ```
55//!
56//! ## Example for creating an HTTP Response
57//! ```
58//! use dbs_uhttp::{Body, MediaType, Response, StatusCode, Version};
59//!
60//! let mut response = Response::new(Version::Http10, StatusCode::OK);
61//! let body = String::from("This is a test");
62//! response.set_body(Body::new(body.clone()));
63//! response.set_content_type(MediaType::PlainText);
64//!
65//! assert!(response.status() == StatusCode::OK);
66//! assert_eq!(response.body().unwrap(), Body::new(body));
67//! assert_eq!(response.http_version(), Version::Http10);
68//!
69//! let mut response_buf: [u8; 126] = [0; 126];
70//! assert!(response.write_all(&mut response_buf.as_mut()).is_ok());
71//! ```
72//!
73//! `HttpConnection` can be used for automatic data exchange and parsing when
74//! handling a client, but it only supports one stream.
75//!
76//! For handling multiple clients use `HttpServer`, which multiplexes `HttpConnection`s
77//! and offers an easy to use interface. The server can run in either blocking or
78//! non-blocking mode. Non-blocking is achieved by using `epoll` to make sure
79//! `requests` will never block when called.
80//!
81//! ## Example for using the server
82//!
83//! ```
84//! use dbs_uhttp::{HttpServer, Response, StatusCode};
85//!
86//! let path_to_socket = "/tmp/example.sock";
87//! std::fs::remove_file(path_to_socket).unwrap_or_default();
88//!
89//! // Start the server.
90//! let mut server = HttpServer::new(path_to_socket).unwrap();
91//! server.start_server().unwrap();
92//!
93//! // Connect a client to the server so it doesn't block in our example.
94//! let mut socket = std::os::unix::net::UnixStream::connect(path_to_socket).unwrap();
95//!
96//! // Server loop processing requests.
97//! loop {
98//! for request in server.requests().unwrap() {
99//! let response = request.process(|request| {
100//! // Your code here.
101//! Response::new(request.http_version(), StatusCode::NoContent)
102//! });
103//! server.respond(response);
104//! }
105//! // Break this example loop.
106//! break;
107//! }
108//! ```
109
110mod common;
111mod connection;
112mod request;
113mod response;
114mod router;
115mod server;
116
117use crate::common::ascii;
118use crate::common::headers;
119
120pub use self::router::{EndpointHandler, HttpRoutes, RouteError};
121pub use crate::common::headers::{Encoding, Headers, MediaType};
122pub use crate::common::sock_ctrl_msg::ScmSocket;
123pub use crate::common::{Body, HttpHeaderError, Method, ServerError, SysError, Version};
124pub use crate::connection::{ConnectionError, HttpConnection};
125pub use crate::request::{Request, RequestError};
126pub use crate::response::{Response, ResponseHeaders, StatusCode};
127pub use crate::server::{HttpServer, ServerRequest, ServerResponse};