|
5 | 5 | [](https://crates.io/crates/oxhttp) |
6 | 6 | [](https://docs.rs/oxhttp) |
7 | 7 |
|
8 | | -OxHTTP is a simple and naive synchronous implementation of [HTTP 1.1](https://httpwg.org/http-core/) in Rust. |
9 | | -It provides both a client and a server. |
10 | | -It does not aim to be a fully-working-in-all-cases HTTP implementation |
11 | | -but to be only a simple one to be use in simple usecases. |
| 8 | +OxHTTP is a small synchronous [HTTP/1.1](https://httpwg.org/http-core/) client and server for Rust. |
| 9 | +It uses blocking I/O and threads and intentionally implements only a subset of HTTP. |
| 10 | + |
| 11 | +The `client` and `server` Cargo features are enabled by default. |
| 12 | +When default features are disabled, either can be enabled independently. |
| 13 | + |
| 14 | +Optional features: |
| 15 | + |
| 16 | +- `flate2`: enables automatic decoding of `gzip` and `deflate` response bodies in the client. |
| 17 | +- `native-tls`: enables HTTPS using the platform's native TLS implementation. |
| 18 | +- `rustls-ring-native`: enables HTTPS using [Rustls](https://github.com/rustls/rustls), [Ring](https://github.com/briansmith/ring), and the platform's certificate store. |
| 19 | +- `rustls-ring-webpki`: enables HTTPS using [Rustls](https://github.com/rustls/rustls), [Ring](https://github.com/briansmith/ring), and the [Common CA Database](https://www.ccadb.org/). |
| 20 | + provided by `webpki-roots`. |
| 21 | +- `rustls-aws-lc-native`: enables HTTPS using [Rustls](https://github.com/rustls/rustls), [AWS Libcrypto for Rust](https://github.com/aws/aws-lc-rs), and the platform's certificate store. |
| 22 | +- `rustls-aws-lc-webpki`: enables HTTPS using [Rustls](https://github.com/rustls/rustls), [AWS Libcrypto for Rust](https://github.com/aws/aws-lc-rs), and the [Common CA Database](https://www.ccadb.org/). |
| 23 | + provided by `webpki-roots`. |
12 | 24 |
|
13 | 25 | ## Client |
14 | 26 |
|
15 | | -OxHTTP provides [a client](https://docs.rs/oxhttp/latest/oxhttp/struct.Client.html). |
16 | | -It aims at following the basic concepts of the [Web Fetch standard](https://fetch.spec.whatwg.org/) without the bits |
17 | | -specific to web browsers (context, CORS...). |
18 | | - |
19 | | -HTTPS is supported behind the disabled by default features. |
20 | | -To enable it, you need to enable one of the following features: |
21 | | - |
22 | | -* `native-tls` to use the current system native implementation. |
23 | | -* `rustls-ring-webpki` to use [Rustls](https://github.com/rustls/rustls) with |
24 | | - the [Ring](https://github.com/briansmith/ring) cryptographic library and |
25 | | - the [Common CA Database](https://www.ccadb.org/). |
26 | | -* `rustls-ring-native` to use [Rustls](https://github.com/rustls/rustls) with |
27 | | - the [Ring](https://github.com/briansmith/ring) cryptographic library and the host certificates. |
28 | | -* `rustls-aws-lc-webpki` to use [Rustls](https://github.com/rustls/rustls) with |
29 | | - the [AWS Libcrypto for Rust](https://github.com/aws/aws-lc-rs) and |
30 | | - the [Common CA Database](https://www.ccadb.org/). |
31 | | -* `rustls-aws-lc-native` to use [Rustls](https://github.com/rustls/rustls) with |
32 | | - the [AWS Libcrypto for Rust](https://github.com/aws/aws-lc-rs) and the host certificates. |
| 27 | +OxHTTP provides [a client](https://docs.rs/oxhttp/latest/oxhttp/struct.Client.html) based on the core concepts of the |
| 28 | +[Fetch standard](https://fetch.spec.whatwg.org/), excluding browser-specific behavior such as CORS and browsing |
| 29 | +contexts. |
| 30 | + |
| 31 | +HTTPS requires one of the optional TLS features listed above. Redirects are not followed by default; use |
| 32 | +[`Client::with_redirection_limit`](https://docs.rs/oxhttp/latest/oxhttp/struct.Client.html#method.with_redirection_limit) |
| 33 | +to enable them. The client does not currently support authentication, HSTS, or persistent connections. |
33 | 34 |
|
34 | 35 | Example: |
35 | 36 |
|
36 | | -```rust |
| 37 | +```rust no_run |
37 | 38 | use oxhttp::Client; |
38 | | -use oxhttp::model::{Body, Request, Method, StatusCode, HeaderName}; |
39 | 39 | use oxhttp::model::header::CONTENT_TYPE; |
40 | | -use std::io::Read; |
| 40 | +use oxhttp::model::{Body, Request, StatusCode}; |
41 | 41 |
|
42 | 42 | let client = Client::new(); |
43 | | -let response = client.request(Request::builder().uri("http://example.com").body(Body::empty()).unwrap()).unwrap(); |
| 43 | +let response = client |
| 44 | + .request( |
| 45 | + Request::builder() |
| 46 | + .uri("http://example.com") |
| 47 | + .body(Body::empty()) |
| 48 | + .unwrap(), |
| 49 | + ) |
| 50 | + .unwrap(); |
44 | 51 | assert_eq!(response.status(), StatusCode::OK); |
45 | 52 | assert_eq!(response.headers().get(CONTENT_TYPE).unwrap(), "text/html"); |
46 | 53 |
|
47 | | -let body = response.into_body().to_string().unwrap(); |
| 54 | +let _body = response.into_body().to_string().unwrap(); |
48 | 55 | ``` |
49 | 56 |
|
50 | 57 | ## Server |
51 | 58 |
|
52 | 59 | OxHTTP provides [a threaded HTTP server](https://docs.rs/oxhttp/latest/oxhttp/struct.Server.html). |
53 | | -It is still a work in progress. Use at your own risks behind a reverse proxy! |
| 60 | +The server starts one thread per connection. It is still a work in progress; use it with care and place it behind a |
| 61 | +reverse proxy when exposing it to untrusted traffic. |
54 | 62 |
|
55 | 63 | Example: |
56 | 64 |
|
57 | 65 | ```rust no_run |
58 | | -use std::net::{Ipv4Addr, Ipv6Addr}; |
59 | 66 | use oxhttp::Server; |
60 | 67 | use oxhttp::model::{Body, Response, StatusCode}; |
| 68 | +use std::net::{Ipv4Addr, Ipv6Addr}; |
61 | 69 | use std::time::Duration; |
62 | 70 |
|
63 | | -// Builds a new server that returns a 404 everywhere except for "/" where it returns the body 'home' |
64 | | -let mut server = Server::new( | request| { |
65 | | -if request.uri().path() == "/" { |
66 | | -Response::builder().body(Body::from("home")).unwrap() |
67 | | -} else { |
68 | | -Response::builder().status(StatusCode::NOT_FOUND).body(Body::empty()).unwrap() |
69 | | -} |
| 71 | +// Return "home" for "/" and 404 for every other path. |
| 72 | +let mut server = Server::new(|request| { |
| 73 | + if request.uri().path() == "/" { |
| 74 | + Response::builder().body(Body::from("home")).unwrap() |
| 75 | + } else { |
| 76 | + Response::builder() |
| 77 | + .status(StatusCode::NOT_FOUND) |
| 78 | + .body(Body::empty()) |
| 79 | + .unwrap() |
| 80 | + } |
70 | 81 | }); |
71 | | -// We bind the server to localhost on both IPv4 and v6 |
72 | | -server = server.bind((Ipv4Addr::LOCALHOST, 8080)).bind((Ipv6Addr::LOCALHOST, 8080)); |
73 | | -// Raise a timeout error if the client does not respond after 10s. |
| 82 | + |
| 83 | +// Bind to localhost over both IPv4 and IPv6. |
| 84 | +server = server |
| 85 | + .bind((Ipv4Addr::LOCALHOST, 8080)) |
| 86 | + .bind((Ipv6Addr::LOCALHOST, 8080)); |
| 87 | +// Raise a timeout error if the client does not respond within 10 seconds. |
74 | 88 | server = server.with_global_timeout(Duration::from_secs(10)); |
75 | | -// Limits the max number of concurrent connections to 128. |
| 89 | +// Limit the number of concurrent connections to 128. |
76 | 90 | server = server.with_max_concurrent_connections(128); |
77 | | -// We spawn the server and block on it |
| 91 | +// Spawn the server and wait for it to terminate. |
78 | 92 | server.spawn().unwrap().join().unwrap(); |
79 | 93 | ``` |
80 | 94 |
|
|
0 commit comments