|
| 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 | +//! ``` |
| 19 | +//! [dependencies] |
| 20 | +//! hyper-reverse-proxy = "0.3.0" |
| 21 | +//! hyper = "0.12.24" |
| 22 | +//! futures = "0.1" |
| 23 | +//! ``` |
| 24 | +//! |
| 25 | +//! The following example will set up a reverse proxy listening on `127.0.0.1:13900`, |
| 26 | +//! and will proxy these calls: |
| 27 | +//! |
| 28 | +//! * `"/target/first"` will be proxied to `http://127.0.0.1:13901` |
| 29 | +//! |
| 30 | +//! * `"/target/second"` will be proxied to `http://127.0.0.1:13902` |
| 31 | +//! |
| 32 | +//! * All other URLs will be handled by `debug_request` function, that will display request information. |
| 33 | +//! |
| 34 | +//! ```rust,no_run |
| 35 | +//! extern crate hyper; |
| 36 | +//! extern crate hyper_reverse_proxy; |
| 37 | +//! extern crate futures; |
| 38 | +//! |
| 39 | +//! use hyper::server::conn::AddrStream; |
| 40 | +//! use hyper::{Body, Request, Response, Server}; |
| 41 | +//! use hyper::service::{service_fn, make_service_fn}; |
| 42 | +//! use futures::future::{self, Future}; |
| 43 | +//! |
| 44 | +//! type BoxFut = Box<Future<Item=Response<Body>, Error=hyper::Error> + Send>; |
| 45 | +//! |
| 46 | +//! fn debug_request(req: Request<Body>) -> BoxFut { |
| 47 | +//! let body_str = format!("{:?}", req); |
| 48 | +//! let response = Response::new(Body::from(body_str)); |
| 49 | +//! Box::new(future::ok(response)) |
| 50 | +//! } |
| 51 | +//! |
| 52 | +//! fn main() { |
| 53 | +//! |
| 54 | +//! // This is our socket address... |
| 55 | +//! let addr = ([127, 0, 0, 1], 13900).into(); |
| 56 | +//! |
| 57 | +//! // A `Service` is needed for every connection, so this |
| 58 | +//! // creates one from our `hello_world` function. |
| 59 | +//! let make_svc = make_service_fn(|socket: &AddrStream| { |
| 60 | +//! let remote_addr = socket.remote_addr(); |
| 61 | +//! service_fn(move |req: Request<Body>| { // returns BoxFut |
| 62 | +//! |
| 63 | +//! // Auth |
| 64 | +//! if req.uri().path().starts_with("/target/first") { |
| 65 | +//! return hyper_reverse_proxy::call(remote_addr.ip(), "http://127.0.0.1:13901", req) |
| 66 | +//! } else if req.uri().path().starts_with("/target/second") { |
| 67 | +//! return hyper_reverse_proxy::call(remote_addr.ip(), "http://127.0.0.1:13902", req) |
| 68 | +//! } else { |
| 69 | +//! debug_request(req) |
| 70 | +//! } |
| 71 | +//! }) |
| 72 | +//! }); |
| 73 | +//! |
| 74 | +//! let server = Server::bind(&addr) |
| 75 | +//! .serve(make_svc) |
| 76 | +//! .map_err(|e| eprintln!("server error: {}", e)); |
| 77 | +//! |
| 78 | +//! println!("Running server on {:?}", addr); |
| 79 | +//! |
| 80 | +//! // Run this server for... forever! |
| 81 | +//! hyper::rt::run(server); |
| 82 | +//! } |
| 83 | +//! ``` |
| 84 | +//! |
1 | 85 |
|
2 | 86 | extern crate hyper;
|
3 | 87 | extern crate futures;
|
|
0 commit comments