<div align="center">
<img src="./logo.png" alt="Http Extensions Logo" width="96">
# Http Extensions
[](https://crates.io/crates/http_extensions)
[](https://docs.rs/http_extensions)
[](https://crates.io/crates/http_extensions)
[](https://github.com/microsoft/oxidizer/actions/workflows/main.yml)
[](https://codecov.io/gh/microsoft/oxidizer)
[](../../LICENSE)
<a href="../.."><img src="../../logo.svg" alt="This crate was developed as part of the Oxidizer project" width="20"></a>
</div>
Shared HTTP types and extension traits for clients and servers.
This crate provides common HTTP functionality built on the popular [`http`][__link0] crate,
including flexible body handling, unified error types, and ergonomic extension traits
for working with HTTP requests and responses.
## Core Types
* [`HttpRequest`][__link1] and [`HttpResponse`][__link2] - Type aliases for requests and responses with [`HttpBody`][__link3]
* [`HttpRequestBuilder`][__link4] - Builder for constructing HTTP requests with a fluent API
* [`HttpResponseBuilder`][__link5] - Builder for constructing HTTP responses with a fluent API
* [`HttpBody`][__link6] - Flexible body type supporting text, binary, JSON, and streaming content
* [`HttpBodyBuilder`][__link7] - Builder for creating HTTP bodies with memory pool optimization
* [`HttpError`][__link8] - Unified error type with automatic backtraces and recovery classification
* [`RequestHandler`][__link9] - Trait for HTTP middleware and request processing pipelines
## Extension Traits
The crate provides extension traits that add convenience methods to standard HTTP types:
* [`StatusExt`][__link10] - Status code validation and recovery classification
* [`RequestExt`][__link11] - Extensions for HTTP requests
* [`ResponseExt`][__link12] - Response recovery classification with `Retry-After` support
* [`HttpRequestExt`][__link13] - Request cloning with body support
* [`HeaderMapExt`][__link14] - Header value extraction and parsing
* [`HeaderValueExt`][__link15] - Construction of [`HeaderValue`][__link16] from [`Bytes`][__link17]
* [`ExtensionsExt`][__link18] - Extensions for [`Extensions`][__link19] to extract URI template labels
## Quick Start
Here’s a complete example showing how to create an HTTP client, build a request,
and validate the response:
```rust
// Create a body builder for constructing request/response bodies
let body_builder = HttpBodyBuilder::new_fake();
// Create a fake handler that returns a successful response
// (This uses the `test-util` feature for testing; similar workflow applies to real clients)
let handler = FakeHandler::from(
HttpResponseBuilder::new(&body_builder)
.status(200)
.header("Content-Type", "application/json")
.text(r#"{"message": "Success"}"#)
.build()?,
);
// Build and send an HTTP request using the handler
let response = handler
.request_builder()
.get("https://api.example.com/data")
.header("Authorization", "Bearer token")
.fetch()
.await?;
// Validate that the response succeeded (returns error for `4xx/5xx` status codes)
let validated_response = response.ensure_success()?;
println!("response status: {}", validated_response.status());
```
**Note**: This example uses the `test-util` feature to create a `FakeHandler` for testing.
In production code, you would use a real HTTP client that implements the
[`RequestHandler`][__link20] trait, but the workflow remains the same: build requests with
[`HttpRequestBuilder`][__link21], send them through a handler, and validate responses with
[`StatusExt::ensure_success`][__link22].
## Integration with the HTTP Ecosystem
This crate builds on the popular [`http`][__link23] crate rather than inventing new types:
* Uses [`http::Request`][__link24] and [`http::Response`][__link25] as base types
* Reuses [`http::Method`][__link26], [`http::StatusCode`][__link27], and [`http::HeaderMap`][__link28]
* Implements standard traits like [`http_body::Body`][__link29] for ecosystem compatibility
* Works seamlessly with other Rust HTTP libraries
## Examples
### Validating Response Status
```rust
// Check if the response succeeded and return an error if not
let validated_response = response.ensure_success()?;
```
### Creating Request Bodies
```rust
// Create different body types
let text_body = builder.text("Hello, world!");
let binary_body = builder.slice(&[1, 2, 3, 4]);
let empty_body = builder.empty();
```
### Building HTTP Requests
```rust
let request = HttpRequestBuilder::new(&body_builder)
.get("https://api.example.com/data")
.text("Hello World")
.build()
.unwrap();
```
### Building HTTP Responses
```rust
let response = HttpResponseBuilder::new(&body_builder)
.status(200)
.header("Content-Type", "text/plain")
.body(body_builder.text("Success"))
.build()
.unwrap();
```
### Building Middleware with `RequestHandler`
```rust
struct LoggingMiddleware<S> {
inner: S,
}
impl<S: RequestHandler> Service<HttpRequest> for LoggingMiddleware<S> {
type Out = Result<HttpResponse>;
async fn execute(&self, request: HttpRequest) -> Self::Out {
println!("Processing request to: {}", request.uri());
let response = self.inner.execute(request).await?;
println!("Response status: {}", response.status());
Ok(response)
}
}
```
### Testing with `FakeHandler`
The `FakeHandler` type (available with the `test-util` feature) lets you mock HTTP responses
for testing without making actual network requests. This is useful for unit testing code
that depends on HTTP clients.
## Features
* `json` - Enables JSON serialization/deserialization support via `Json` type
* `test-util` - Enables fake implementations for testing
## Memory Management
Bodies created through [`HttpBodyBuilder`][__link30] use memory pools from [`bytesbuf`][__link31] to
reduce allocation overhead. When body data is consumed, memory is automatically recycled
for future requests. This makes the crate particularly efficient for high-throughput scenarios.
<hr/>
<sub>
This crate was developed as part of <a href="../..">The Oxidizer Project</a>. Browse this crate's <a href="https://github.com/microsoft/oxidizer/tree/main/crates/http_extensions">source code</a>.
</sub>
[__cargo_doc2readme_dependencies_info]: ggGmYW0CYXZlMC43LjJhdIQbLiTyV0MU86EbZU15e0PmecoboQ9jo59bnAEbyDXw04U13GlhYvRhcoQb8ws5BCyJXrMbtKOqwMaB35YbTeUgtnVoxOMbl-5qQusDAothZIWCZWJ5dGVzZjEuMTEuMYJoYnl0ZXNidWZlMC41LjOCZGh0dHBlMS40LjGCaWh0dHBfYm9keWUxLjAuMYJvaHR0cF9leHRlbnNpb25zZTAuNS4w
[__link0]: https://crates.io/crates/http/1.4.1
[__link1]: https://docs.rs/http_extensions/0.5.0/http_extensions/type.HttpRequest.html
[__link10]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=StatusExt
[__link11]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=RequestExt
[__link12]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=ResponseExt
[__link13]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=HttpRequestExt
[__link14]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=HeaderMapExt
[__link15]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=HeaderValueExt
[__link16]: https://docs.rs/http/1.4.1/http/?search=HeaderValue
[__link17]: https://docs.rs/bytes/1.11.1/bytes/?search=Bytes
[__link18]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=ExtensionsExt
[__link19]: https://docs.rs/http/1.4.1/http/?search=Extensions
[__link2]: https://docs.rs/http_extensions/0.5.0/http_extensions/type.HttpResponse.html
[__link20]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=RequestHandler
[__link21]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=HttpRequestBuilder
[__link22]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=StatusExt::ensure_success
[__link23]: https://crates.io/crates/http/1.4.1
[__link24]: https://docs.rs/http/1.4.1/http/?search=Request
[__link25]: https://docs.rs/http/1.4.1/http/?search=Response
[__link26]: https://docs.rs/http/1.4.1/http/?search=Method
[__link27]: https://docs.rs/http/1.4.1/http/?search=StatusCode
[__link28]: https://docs.rs/http/1.4.1/http/?search=HeaderMap
[__link29]: https://docs.rs/http_body/1.0.1/http_body/?search=Body
[__link3]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=HttpBody
[__link30]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=HttpBodyBuilder
[__link31]: https://crates.io/crates/bytesbuf/0.5.3
[__link4]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=HttpRequestBuilder
[__link5]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=HttpResponseBuilder
[__link6]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=HttpBody
[__link7]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=HttpBodyBuilder
[__link8]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=HttpError
[__link9]: https://docs.rs/http_extensions/0.5.0/http_extensions/?search=RequestHandler