//! Reverse proxy listening in "localhost:4000" will proxy all requests to "localhost:3000" //! endpoint. //! //! Run with //! //! ```not_rust //! cargo run -p example-reverse-proxy //! ``` use axum::{ body::Body, extract::{Request, State}, http::uri::Uri, response::{IntoResponse, Response}, routing::get, Router, }; use hyper::StatusCode; use hyper_util::{client::legacy::connect::HttpConnector, rt::TokioExecutor}; type Client = hyper_util::client::legacy::Client; #[tokio::main] async fn main() { tokio::spawn(server()); let client: Client = hyper_util::client::legacy::Client::<(), ()>::builder(TokioExecutor::new()) .build(HttpConnector::new()); let app = Router::new().route("/", get(handler)).with_state(client); let listener = tokio::net::TcpListener::bind("127.0.0.1:4000") .await .unwrap(); println!("listening on {}", listener.local_addr().unwrap()); axum::serve(listener, app).await.unwrap(); } async fn handler(State(client): State, mut req: Request) -> Result { let path = req.uri().path(); let path_query = req .uri() .path_and_query() .map(|v| v.as_str()) .unwrap_or(path); let uri = format!("http://127.0.0.1:3000{}", path_query); *req.uri_mut() = Uri::try_from(uri).unwrap(); Ok(client .request(req) .await .map_err(|_| StatusCode::BAD_REQUEST)? .into_response()) } async fn server() { let app = Router::new().route("/", get(|| async { "Hello, world!" })); let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") .await .unwrap(); println!("listening on {}", listener.local_addr().unwrap()); axum::serve(listener, app).await.unwrap(); }