|
1 | | -//! |
2 | | -//! A simple reverse proxy, to be used with [Hyper]. |
3 | | -//! |
4 | | -//! The implementation ensures that [Hop-by-hop headers] are stripped correctly in both directions, |
5 | | -//! and adds the client's IP address to a comma-space-separated list of forwarding addresses in the |
6 | | -//! `X-Forwarded-For` header. |
7 | | -//! |
8 | | -//! The implementation is based on Go's [`httputil.ReverseProxy`]. |
9 | | -//! |
10 | | -//! [Hyper]: http://hyper.rs/ |
11 | | -//! [Hop-by-hop headers]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html |
12 | | -//! [`httputil.ReverseProxy`]: https://golang.org/pkg/net/http/httputil/#ReverseProxy |
13 | | -//! |
14 | | -//! # Example |
15 | | -//! |
16 | | -//! Add these dependencies to your `Cargo.toml` file. |
17 | | -//! |
18 | | -//! ```toml |
19 | | -//! [dependencies] |
20 | | -//! hyper-reverse-proxy = "0.5" |
21 | | -//! hyper = { version = "0.14", features = ["full"] } |
22 | | -//! tokio = { version = "1", features = ["full"] } |
23 | | -//! ``` |
24 | | -//! |
25 | | -//! To enable support for connecting to downstream HTTPS servers, enable the `https` feature: |
26 | | -//! |
27 | | -//! ```toml |
28 | | -//! hyper-reverse-proxy = { version = "0.4", features = ["https"] } |
29 | | -//! ``` |
30 | | -//! |
31 | | -//! The following example will set up a reverse proxy listening on `127.0.0.1:13900`, |
32 | | -//! and will proxy these calls: |
33 | | -//! |
34 | | -//! * `"/target/first"` will be proxied to `http://127.0.0.1:13901` |
35 | | -//! |
36 | | -//! * `"/target/second"` will be proxied to `http://127.0.0.1:13902` |
37 | | -//! |
38 | | -//! * All other URLs will be handled by `debug_request` function, that will display request information. |
39 | | -//! |
40 | | -//! ```rust,no_run |
41 | | -//! use hyper::server::conn::AddrStream; |
42 | | -//! use hyper::service::{make_service_fn, service_fn}; |
43 | | -//! use hyper::{Body, Request, Response, Server, StatusCode}; |
44 | | -//! use hyper_reverse_proxy::ReverseProxy; |
45 | | -//! use hyper_trust_dns::{RustlsHttpsConnector, TrustDnsResolver}; |
46 | | -//! use std::net::IpAddr; |
47 | | -//! use std::{convert::Infallible, net::SocketAddr}; |
48 | | -//! |
49 | | -//! lazy_static::lazy_static! { |
50 | | -//! static ref PROXY_CLIENT: ReverseProxy<RustlsHttpsConnector> = { |
51 | | -//! ReverseProxy::new( |
52 | | -//! hyper::Client::builder().build::<_, hyper::Body>(TrustDnsResolver::default().into_rustls_webpki_https_connector()), |
53 | | -//! ) |
54 | | -//! }; |
55 | | -//! } |
56 | | -//! |
57 | | -//! fn debug_request(req: &Request<Body>) -> Result<Response<Body>, Infallible> { |
58 | | -//! let body_str = format!("{:?}", req); |
59 | | -//! Ok(Response::new(Body::from(body_str))) |
60 | | -//! } |
61 | | -//! |
62 | | -//! async fn handle(client_ip: IpAddr, req: Request<Body>) -> Result<Response<Body>, Infallible> { |
63 | | -//! if req.uri().path().starts_with("/target/first") { |
64 | | -//! match PROXY_CLIENT.call(client_ip, "http://127.0.0.1:13901", req) |
65 | | -//! .await |
66 | | -//! { |
67 | | -//! Ok(response) => { |
68 | | -//! Ok(response) |
69 | | -//! }, |
70 | | -//! Err(_error) => { |
71 | | -//! Ok(Response::builder() |
72 | | -//! .status(StatusCode::INTERNAL_SERVER_ERROR) |
73 | | -//! .body(Body::empty()) |
74 | | -//! .unwrap())}, |
75 | | -//! } |
76 | | -//! } else if req.uri().path().starts_with("/target/second") { |
77 | | -//! match PROXY_CLIENT.call(client_ip, "http://127.0.0.1:13902", req) |
78 | | -//! .await |
79 | | -//! { |
80 | | -//! Ok(response) => Ok(response), |
81 | | -//! Err(_error) => Ok(Response::builder() |
82 | | -//! .status(StatusCode::INTERNAL_SERVER_ERROR) |
83 | | -//! .body(Body::empty()) |
84 | | -//! .unwrap()), |
85 | | -//! } |
86 | | -//! } else { |
87 | | -//! debug_request(&req) |
88 | | -//! } |
89 | | -//! } |
90 | | -//! |
91 | | -//! #[tokio::main] |
92 | | -//! async fn main() { |
93 | | -//! let bind_addr = "127.0.0.1:8000"; |
94 | | -//! let addr: SocketAddr = bind_addr.parse().expect("Could not parse ip:port."); |
95 | | -//! |
96 | | -//! let make_svc = make_service_fn(|conn: &AddrStream| { |
97 | | -//! let remote_addr = conn.remote_addr().ip(); |
98 | | -//! async move { Ok::<_, Infallible>(service_fn(move |req| handle(remote_addr, req))) } |
99 | | -//! }); |
100 | | -//! |
101 | | -//! let server = Server::bind(&addr).serve(make_svc); |
102 | | -//! |
103 | | -//! println!("Running server on {:?}", addr); |
104 | | -//! |
105 | | -//! if let Err(e) = server.await { |
106 | | -//! eprintln!("server error: {}", e); |
107 | | -//! } |
108 | | -//! } |
109 | | -//! |
110 | | -//! ``` |
| 1 | +#![doc = include_str!("../README.md")] |
| 2 | + |
111 | 3 | #[macro_use] |
112 | 4 | extern crate tracing; |
113 | 5 |
|
|
0 commit comments