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
//! Middleware to add an HTTP translation layer.
//!
//! Transforms a low-level service that uses Candid types ([`IcHttpRequest`] and [`IcHttpResponse`])
//! into one that uses types from the [http](https://crates.io/crates/http) crate.
//!
//! ```text
//! │ ▲
//! http::Request│ │http::Response
//! ┌─┴─────────────────────┴───┐
//! │ HttpResponseConverter │
//! └─┬─────────────────────▲───┘
//! │ │
//! ┌─▼─────────────────────┴───┐
//! │ HttpRequestConverter │
//! └─┬─────────────────────┬───┘
//! IcHttpRequest│ │IcHttpResponse
//! ▼ │
//! ┌─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┐
//! │ SERVICE │
//! └─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─┘
//! ```
//!
//! This brings several advantages:
//!
//! * Can re-use existing types like [`http::request::Builder`] or [`http::StatusCode`].
//! * Requests are automatically sanitized and canonicalized (e.g. header names are validated and lower cased).
//! * Can re-use existing middlewares, like from the [tower-http](https://crates.io/crates/tower-http) crate.
//!
//! # Examples
//!
//! ```rust
//! use canhttp::{http::{HttpConversionLayer }, MaxResponseBytesRequestExtension};
//! use ic_cdk_management_canister::{HttpRequestArgs as IcHttpRequest, HttpRequestResult as IcHttpResponse};
//! use tower::{Service, ServiceBuilder, ServiceExt, BoxError};
//!
//! async fn always_200_ok(request: IcHttpRequest) -> Result<IcHttpResponse, BoxError> {
//! Ok(IcHttpResponse {
//! status: 200_u8.into(),
//! ..Default::default()
//! })
//! }
//!
//! # #[tokio::main]
//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let mut service = ServiceBuilder::new()
//! .layer(HttpConversionLayer)
//! .service_fn(always_200_ok);
//!
//! let request = http::Request::post("https://internetcomputer.org")
//! .max_response_bytes(42) //IC-specific concepts are added to the request as extensions.
//! .header("Content-Type", "application/json")
//! .body(vec![])
//! .unwrap();
//!
//! let response = service.ready().await.unwrap().call(request).await.unwrap();
//!
//! assert_eq!(response.status(), http::StatusCode::OK);
//! # Ok(())
//! # }
//! ```
//!
//! [`IcHttpRequest`]: ic_cdk_management_canister::HttpRequestArgs
//! [`IcHttpResponse`]: ic_cdk_management_canister::HttpRequestResult
pub use ;
pub use ;
use crate;
use Layer;
/// Middleware that combines [`HttpRequestConverter`] to convert requests
/// and [`HttpResponseConverter`] to convert responses to a [`Service`].
///
/// See the [module docs](crate::http) for an example.
///
/// [`Service`]: tower::Service
;