Crate generic_async_http_client

Source
Expand description

Project Status: Active – The project has reached a stable, usable state and is being actively developed. Crates.io Released API docs MIT licensed

A generic async HTTP request create.

It is meant to be a thin wrapper around various HTTP clients and handles TLS, serialization and parsing.

The main goal is to allow binaries (that pull in some libraries that make use of a HTTP client) to specify what implementation should be used.

And if there is a Proxy. If not specified auto detection is performed by looking at HTTP_PROXY.

Also, you can Mock the webserver side for tests.

§Features

You need to specify via features what crates are used to do the actual work.

feature flagMeaning
use_hyperUse hyper for HTTP GitHub Workflow Status
use_async_h1Use async_h1 for HTTP GitHub Workflow Status
rustls_byocAdd support for HTTPS via rustls - You need to set a CryptoProvider
rustls_ringLike rustls_byoc but use ring for crypto
rustls_aws_lc_rsLike rustls_byoc but use aws-lc-rs for crypto
rustls_fipsLike rustls_byoc but use aws-lc-rs in FIPS mode for crypto
proxiesAdd support for Socks5 and HTTP proxy
hyper_native_tlsUse hyper for HTTP and do HTTPS via native_tls GitHub Workflow Status
async_native_tlsUse async_h1 for HTTP and do HTTPS via native_tls GitHub Workflow Status
http2Use http2 if available (only works with use_hyper)

Without anything specified you will end up with No HTTP backend was selected. If you use this crate for a library, please reexport the appropriate features.

§Motivation

Rust offers different async runtimes that - on a high level - offer the same thing: asynchronous functions for files, sockets and so on.

So if you write a lib and need some basic stuff (like an http client) you sometimes have to make choices that are not what your crates users would have liked. For example: I wrote a webserver based on hyper and wanted to add ACME. A crate I found did what I needed but used async-h1 and async-std. While that worked, it did increase the binary size and crates I depend on by a good amount.

So I wrote this. You can specify which backend to use. In the Webserver case, using tokio which is already a dependency VS async-std did lead to 81 less crates and a 350kB smaller binary. Using (and async-acme):

[profile.release]
lto = "fat"
codegen-units = 1

Also for http clients: there should be a way to add a proxy for all libs that use it.

§Plans

  1. Add Sessions - to make multiple requests more efficient
  2. Add a cookie jar for the sessions
  3. Allow a Body to be streamed from a server
  4. Allow a Body to be streamed to a server

§Example

#[derive(Serialize)]
struct ContactForm {
    email: String,
    text: String,
}
async fn post_form(form: &ContactForm) -> Result<(), Error> {
   let req = Request::post("http://example.com/").form(form)?;
   assert_eq!(req.exec().await?.text().await?, "ok");
   Ok(())
}

If performing more than one HTTP Request you should favor the use of [Session] over Request.

Modules§

proxyproxies

Structs§

Body
A Body for the Request. You will most likely use Request::body directly.
HeaderName
A HTTP Header Name
HeaderValue
A HTTP Header Value
Mocktest and mock_tests
Mock Responses and validate Requests. All responses of a thread will be checked against the Mock if at least one Endpoint is Mocked. Otherwise a normal web request is done
MockedEndpointtest and mock_tests
A mocked HTTP Endpoint.
Request
Builds a HTTP request, poll it to query
Response
The response of a webserver. Headers and Status are available from the start, the body must be polled/awaited again

Enums§

Error
MockErrtest and mock_tests