Forwards the incoming HTTP request using `awc`.
(
req: HttpRequest,
payload: web::Payload,
peer_addr: Option<PeerAddr>,
url: web::Data<Url>,
client: web::Data<Client>,
)
| 14 | |
| 15 | /// Forwards the incoming HTTP request using `awc`. |
| 16 | async fn forward( |
| 17 | req: HttpRequest, |
| 18 | payload: web::Payload, |
| 19 | peer_addr: Option<PeerAddr>, |
| 20 | url: web::Data<Url>, |
| 21 | client: web::Data<Client>, |
| 22 | ) -> Result<HttpResponse, Error> { |
| 23 | let mut new_url = (**url).clone(); |
| 24 | new_url.set_path(req.uri().path()); |
| 25 | new_url.set_query(req.uri().query()); |
| 26 | |
| 27 | let forwarded_req = client |
| 28 | .request_from(new_url.as_str(), req.head()) |
| 29 | .no_decompress(); |
| 30 | |
| 31 | // TODO: This forwarded implementation is incomplete as it only handles the unofficial |
| 32 | // X-Forwarded-For header but not the official Forwarded one. |
| 33 | let forwarded_req = match peer_addr { |
| 34 | Some(PeerAddr(addr)) => { |
| 35 | forwarded_req.insert_header(("x-forwarded-for", addr.ip().to_string())) |
| 36 | } |
| 37 | None => forwarded_req, |
| 38 | }; |
| 39 | |
| 40 | let res = forwarded_req |
| 41 | .send_stream(payload) |
| 42 | .await |
| 43 | .map_err(error::ErrorInternalServerError)?; |
| 44 | |
| 45 | let mut client_resp = HttpResponse::build(res.status()); |
| 46 | // Remove `Connection` as per |
| 47 | // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection#Directives |
| 48 | for (header_name, header_value) in res.headers().iter().filter(|(h, _)| *h != "connection") { |
| 49 | client_resp.insert_header((header_name.clone(), header_value.clone())); |
| 50 | } |
| 51 | |
| 52 | Ok(client_resp.streaming(res)) |
| 53 | } |
| 54 | |
| 55 | /// Same as `forward` but uses `reqwest` as the client used to forward the request. |
| 56 | async fn forward_reqwest( |