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