MCPcopy Create free account
hub / github.com/actix/examples / forward_reqwest

Function forward_reqwest

http-proxy/src/main.rs:56–114  ·  view source on GitHub ↗

Same as `forward` but uses `reqwest` as the client used to forward the request.

(
    req: HttpRequest,
    mut payload: web::Payload,
    method: actix_web::http::Method,
    peer_addr: Option<PeerAddr>,
    url: web::Data<Url>,
    client: web::Data<reqwest::Client>,
)

Source from the content-addressed store, hash-verified

54
55/// Same as `forward` but uses `reqwest` as the client used to forward the request.
56async fn forward_reqwest(
57 req: HttpRequest,
58 mut payload: web::Payload,
59 method: actix_web::http::Method,
60 peer_addr: Option<PeerAddr>,
61 url: web::Data<Url>,
62 client: web::Data<reqwest::Client>,
63) -> Result<HttpResponse, Error> {
64 let path = req
65 .uri()
66 .path()
67 .strip_prefix(REQWEST_PREFIX)
68 .unwrap_or(req.uri().path());
69
70 let mut new_url = (**url).clone();
71 new_url.set_path(path);
72 new_url.set_query(req.uri().query());
73
74 let (tx, rx) = mpsc::unbounded_channel();
75
76 actix_web::rt::spawn(async move {
77 while let Some(chunk) = payload.next().await {
78 tx.send(chunk).unwrap();
79 }
80 });
81
82 let forwarded_req = client
83 .request(
84 reqwest::Method::from_bytes(method.as_str().as_bytes()).unwrap(),
85 new_url,
86 )
87 .body(reqwest::Body::wrap_stream(UnboundedReceiverStream::new(rx)));
88
89 // TODO: This forwarded implementation is incomplete as it only handles the unofficial
90 // X-Forwarded-For header but not the official Forwarded one.
91 let forwarded_req = match peer_addr {
92 Some(PeerAddr(addr)) => forwarded_req.header("x-forwarded-for", addr.ip().to_string()),
93 None => forwarded_req,
94 };
95
96 let res = forwarded_req
97 .send()
98 .await
99 .map_err(error::ErrorInternalServerError)?;
100
101 let mut client_resp =
102 HttpResponse::build(actix_web::http::StatusCode::from_u16(res.status().as_u16()).unwrap());
103
104 // Remove `Connection` as per
105 // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection#Directives
106 for (header_name, header_value) in res.headers().iter().filter(|(h, _)| *h != "connection") {
107 client_resp.insert_header((
108 actix_web::http::header::HeaderName::from_bytes(header_name.as_ref()).unwrap(),
109 actix_web::http::header::HeaderValue::from_bytes(header_value.as_ref()).unwrap(),
110 ));
111 }
112
113 Ok(client_resp.streaming(res.bytes_stream()))

Callers

nothing calls this directly

Calls 1

as_strMethod · 0.80

Tested by

no test coverage detected