From d29cfd7b9db126ca2422a56ca1304cbc1ed82cf9 Mon Sep 17 00:00:00 2001 From: Afifurrohman Date: Tue, 2 Apr 2024 13:43:46 +0000 Subject: [PATCH 1/3] feat: Update reverse proxy example to support both http and https --- examples/reverse-proxy/Cargo.toml | 2 +- examples/reverse-proxy/src/main.rs | 28 +++++++++++++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/examples/reverse-proxy/Cargo.toml b/examples/reverse-proxy/Cargo.toml index e28165730e..482e453c2a 100644 --- a/examples/reverse-proxy/Cargo.toml +++ b/examples/reverse-proxy/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = { path = "../../axum" } -hyper = { version = "1.0.0", features = ["full"] } +hyper-tls = {version = "0.6.0", features = ["vendored"]} hyper-util = { version = "0.1.1", features = ["client-legacy"] } tokio = { version = "1", features = ["full"] } diff --git a/examples/reverse-proxy/src/main.rs b/examples/reverse-proxy/src/main.rs index db39124670..dca020cbda 100644 --- a/examples/reverse-proxy/src/main.rs +++ b/examples/reverse-proxy/src/main.rs @@ -1,6 +1,8 @@ -//! Reverse proxy listening in "localhost:4000" will proxy all requests to "localhost:3000" +//! Reverse proxy listening in "localhost:4000" will proxy all `GET` requests to "localhost:3000" except for path /https is example.com //! endpoint. //! +//! On unix like OS: make sure `ca-certificates` is installed. +//! //! Run with //! //! ```not_rust @@ -12,13 +14,13 @@ use axum::{ extract::{Request, State}, http::uri::Uri, response::{IntoResponse, Response}, - routing::get, - Router, + routing, Router, }; -use hyper::StatusCode; +use axum::http::{header::HOST, StatusCode}; +use hyper_tls::HttpsConnector; use hyper_util::{client::legacy::connect::HttpConnector, rt::TokioExecutor}; -type Client = hyper_util::client::legacy::Client; +type Client = hyper_util::client::legacy::Client, Body>; #[tokio::main] async fn main() { @@ -26,9 +28,11 @@ async fn main() { let client: Client = hyper_util::client::legacy::Client::<(), ()>::builder(TokioExecutor::new()) - .build(HttpConnector::new()); + .build(HttpsConnector::new()); - let app = Router::new().route("/", get(handler)).with_state(client); + let app = Router::new() + .fallback(routing::get(handler)) + .with_state(client); let listener = tokio::net::TcpListener::bind("127.0.0.1:4000") .await @@ -45,10 +49,16 @@ async fn handler(State(client): State, mut req: Request) -> Result, mut req: Request) -> Result Date: Tue, 2 Apr 2024 14:14:26 +0000 Subject: [PATCH 2/3] fix(ci): Format `Cargo.toml` and perform cargo fmt --- examples/reverse-proxy/Cargo.toml | 2 +- examples/reverse-proxy/src/main.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/reverse-proxy/Cargo.toml b/examples/reverse-proxy/Cargo.toml index 482e453c2a..2bedfe1a74 100644 --- a/examples/reverse-proxy/Cargo.toml +++ b/examples/reverse-proxy/Cargo.toml @@ -5,6 +5,6 @@ edition = "2021" [dependencies] axum = { path = "../../axum" } -hyper-tls = {version = "0.6.0", features = ["vendored"]} +hyper-tls = { version = "0.6.0", features = ["vendored"] } hyper-util = { version = "0.1.1", features = ["client-legacy"] } tokio = { version = "1", features = ["full"] } diff --git a/examples/reverse-proxy/src/main.rs b/examples/reverse-proxy/src/main.rs index dca020cbda..575f7c84cf 100644 --- a/examples/reverse-proxy/src/main.rs +++ b/examples/reverse-proxy/src/main.rs @@ -9,6 +9,7 @@ //! cargo run -p example-reverse-proxy //! ``` +use axum::http::{header::HOST, StatusCode}; use axum::{ body::Body, extract::{Request, State}, @@ -16,7 +17,6 @@ use axum::{ response::{IntoResponse, Response}, routing, Router, }; -use axum::http::{header::HOST, StatusCode}; use hyper_tls::HttpsConnector; use hyper_util::{client::legacy::connect::HttpConnector, rt::TokioExecutor}; @@ -51,7 +51,7 @@ async fn handler(State(client): State, mut req: Request) -> Result Date: Fri, 10 May 2024 15:08:52 +0000 Subject: [PATCH 3/3] refactor: add some informative header (`X-Forwarded-For`, `X-Forwarded-Host`, `X-Forwarded-Proto`, `Forwarded`) --- examples/reverse-proxy/src/main.rs | 63 ++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/examples/reverse-proxy/src/main.rs b/examples/reverse-proxy/src/main.rs index 575f7c84cf..cc176680ed 100644 --- a/examples/reverse-proxy/src/main.rs +++ b/examples/reverse-proxy/src/main.rs @@ -1,5 +1,5 @@ -//! Reverse proxy listening in "localhost:4000" will proxy all `GET` requests to "localhost:3000" except for path /https is example.com -//! endpoint. +//! Reverse proxy listening in "localhost:4000" will proxy all `GET` requests to "localhost:3000" +//! except for path /https is example.com endpoint. //! //! On unix like OS: make sure `ca-certificates` is installed. //! @@ -9,6 +9,8 @@ //! cargo run -p example-reverse-proxy //! ``` +use axum::extract::ConnectInfo; +use axum::http::header::FORWARDED; use axum::http::{header::HOST, StatusCode}; use axum::{ body::Body, @@ -19,6 +21,7 @@ use axum::{ }; use hyper_tls::HttpsConnector; use hyper_util::{client::legacy::connect::HttpConnector, rt::TokioExecutor}; +use std::net::SocketAddr; type Client = hyper_util::client::legacy::Client, Body>; @@ -38,16 +41,31 @@ async fn main() { .await .unwrap(); println!("listening on {}", listener.local_addr().unwrap()); - axum::serve(listener, app).await.unwrap(); + axum::serve( + listener, + app.into_make_service_with_connect_info::(), + ) + .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); +async fn handler( + State(client): State, + ConnectInfo(addr): ConnectInfo, + mut req: Request, +) -> Result { + let uri = req.uri(); + + let ip = addr.ip().to_string(); + let host = uri + .authority() + .map(|a| a.as_str()) + .unwrap_or("127.0.0.1:4000") + .to_string(); + let proto = uri.scheme_str().unwrap_or("http").to_string(); + + let path = uri.path(); + let path_query = uri.path_and_query().map(|v| v.as_str()).unwrap_or(path); let mut uri = format!("http://127.0.0.1:3000{}", path_query); if path == "/https" { @@ -56,13 +74,32 @@ async fn handler(State(client): State, mut req: Request) -> Result