|
| 1 | + |
1 | 2 | # hyper-reverse-proxy
|
2 | 3 |
|
3 | 4 | [](https://travis-ci.org/brendanzab/hyper-reverse-proxy)
|
4 | 5 | [](https://docs.rs/hyper-reverse-proxy)
|
5 | 6 | [](https://crates.io/crates/hyper-reverse-proxy)
|
6 | 7 | [](https://github.com/brendanzab/hyper-reverse-proxy/blob/master/LICENSE)
|
7 | 8 |
|
8 |
| -A simple reverse proxy, to be used with [Hyper] and [Tokio]. |
| 9 | +A simple reverse proxy, to be used with [Hyper]. |
| 10 | + |
| 11 | +The implementation ensures that [Hop-by-hop headers] are stripped correctly in both directions, |
| 12 | +and adds the client's IP address to a comma-space-separated list of forwarding addresses in the |
| 13 | +`X-Forwarded-For` header. |
9 | 14 |
|
10 |
| -The implementation was originally based on Go's [`httputil.ReverseProxy`]. |
| 15 | +The implementation is based on Go's [`httputil.ReverseProxy`]. |
11 | 16 |
|
12 | 17 | [Hyper]: http://hyper.rs/
|
13 |
| -[Tokio]: http://tokio.rs/ |
| 18 | +[Hop-by-hop headers]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html |
14 | 19 | [`httputil.ReverseProxy`]: https://golang.org/pkg/net/http/httputil/#ReverseProxy
|
| 20 | + |
| 21 | +# Example |
| 22 | + |
| 23 | +Add these dependencies to your `Cargo.toml` file. |
| 24 | + |
| 25 | +``` |
| 26 | +[dependencies] |
| 27 | +hyper-reverse-proxy = "0.3.0" |
| 28 | +hyper = "0.12.24" |
| 29 | +futures = "0.1" |
| 30 | +``` |
| 31 | + |
| 32 | +The following example will set up a reverse proxy listening on `127.0.0.1:13900`, |
| 33 | +and will proxy these calls: |
| 34 | + |
| 35 | +* `"/target/first"` will be proxied to `http://127.0.0.1:13901` |
| 36 | + |
| 37 | +* `"/target/second"` will be proxied to `http://127.0.0.1:13902` |
| 38 | + |
| 39 | +* All other URLs will be handled by `debug_request` function, that will display request information. |
| 40 | + |
| 41 | +```rust,no_run |
| 42 | +extern crate hyper; |
| 43 | +extern crate hyper_reverse_proxy; |
| 44 | +extern crate futures; |
| 45 | +
|
| 46 | +use hyper::server::conn::AddrStream; |
| 47 | +use hyper::{Body, Request, Response, Server}; |
| 48 | +use hyper::service::{service_fn, make_service_fn}; |
| 49 | +use futures::future::{self, Future}; |
| 50 | +
|
| 51 | +type BoxFut = Box<Future<Item=Response<Body>, Error=hyper::Error> + Send>; |
| 52 | +
|
| 53 | +fn debug_request(req: Request<Body>) -> BoxFut { |
| 54 | + let body_str = format!("{:?}", req); |
| 55 | + let response = Response::new(Body::from(body_str)); |
| 56 | + Box::new(future::ok(response)) |
| 57 | +} |
| 58 | +
|
| 59 | +fn main() { |
| 60 | +
|
| 61 | + // This is our socket address... |
| 62 | + let addr = ([127, 0, 0, 1], 13900).into(); |
| 63 | +
|
| 64 | + // A `Service` is needed for every connection, so this |
| 65 | + // creates one from our `hello_world` function. |
| 66 | + let make_svc = make_service_fn(|socket: &AddrStream| { |
| 67 | + let remote_addr = socket.remote_addr(); |
| 68 | + service_fn(move |req: Request<Body>| { // returns BoxFut |
| 69 | +
|
| 70 | + // Auth |
| 71 | + if req.uri().path().starts_with("/target/first") { |
| 72 | + return hyper_reverse_proxy::call(remote_addr.ip(), "http://127.0.0.1:13901", req) |
| 73 | + } else if req.uri().path().starts_with("/target/second") { |
| 74 | + return hyper_reverse_proxy::call(remote_addr.ip(), "http://127.0.0.1:13902", req) |
| 75 | + } else { |
| 76 | + debug_request(req) |
| 77 | + } |
| 78 | + }) |
| 79 | + }); |
| 80 | +
|
| 81 | + let server = Server::bind(&addr) |
| 82 | + .serve(make_svc) |
| 83 | + .map_err(|e| eprintln!("server error: {}", e)); |
| 84 | +
|
| 85 | + println!("Running server on {:?}", addr); |
| 86 | +
|
| 87 | + // Run this server for... forever! |
| 88 | + hyper::rt::run(server); |
| 89 | +} |
| 90 | +``` |
0 commit comments