hyper-reverse-proxy/README.md

90 lines
3.0 KiB
Markdown
Raw Normal View History

2019-02-16 17:46:52 +00:00
2017-07-15 06:23:12 +00:00
# hyper-reverse-proxy
[![Build Status](https://travis-ci.org/brendanzab/hyper-reverse-proxy.svg?branch=master)](https://travis-ci.org/brendanzab/hyper-reverse-proxy)
[![Documentation](https://docs.rs/hyper-reverse-proxy/badge.svg)](https://docs.rs/hyper-reverse-proxy)
[![Version](https://img.shields.io/crates/v/hyper-reverse-proxy.svg)](https://crates.io/crates/hyper-reverse-proxy)
[![License](https://img.shields.io/crates/l/hyper-reverse-proxy.svg)](https://github.com/brendanzab/hyper-reverse-proxy/blob/master/LICENSE)
2019-02-16 17:46:52 +00:00
A simple reverse proxy, to be used with [Hyper].
The implementation ensures that [Hop-by-hop headers] are stripped correctly in both directions,
and adds the client's IP address to a comma-space-separated list of forwarding addresses in the
`X-Forwarded-For` header.
2017-07-15 06:23:12 +00:00
2019-02-16 17:46:52 +00:00
The implementation is based on Go's [`httputil.ReverseProxy`].
2017-07-15 06:23:12 +00:00
2017-07-15 08:41:28 +00:00
[Hyper]: http://hyper.rs/
2019-02-16 17:46:52 +00:00
[Hop-by-hop headers]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
2017-07-15 06:23:12 +00:00
[`httputil.ReverseProxy`]: https://golang.org/pkg/net/http/httputil/#ReverseProxy
2019-02-16 17:46:52 +00:00
# Example
Add these dependencies to your `Cargo.toml` file.
2019-02-16 18:04:46 +00:00
```toml
2019-02-16 17:46:52 +00:00
[dependencies]
hyper-reverse-proxy = "0.3.0"
hyper = "0.12.24"
futures = "0.1"
```
The following example will set up a reverse proxy listening on `127.0.0.1:13900`,
and will proxy these calls:
* `"/target/first"` will be proxied to `http://127.0.0.1:13901`
* `"/target/second"` will be proxied to `http://127.0.0.1:13902`
* All other URLs will be handled by `debug_request` function, that will display request information.
```rust,no_run
extern crate hyper;
extern crate hyper_reverse_proxy;
extern crate futures;
use hyper::server::conn::AddrStream;
use hyper::{Body, Request, Response, Server};
use hyper::service::{service_fn, make_service_fn};
use futures::future::{self, Future};
type BoxFut = Box<Future<Item=Response<Body>, Error=hyper::Error> + Send>;
fn debug_request(req: Request<Body>) -> BoxFut {
let body_str = format!("{:?}", req);
let response = Response::new(Body::from(body_str));
Box::new(future::ok(response))
}
fn main() {
// This is our socket address...
let addr = ([127, 0, 0, 1], 13900).into();
2019-02-16 18:10:36 +00:00
// A `Service` is needed for every connection.
2019-02-16 17:46:52 +00:00
let make_svc = make_service_fn(|socket: &AddrStream| {
let remote_addr = socket.remote_addr();
service_fn(move |req: Request<Body>| { // returns BoxFut
// Auth
if req.uri().path().starts_with("/target/first") {
return hyper_reverse_proxy::call(remote_addr.ip(), "http://127.0.0.1:13901", req)
} else if req.uri().path().starts_with("/target/second") {
return hyper_reverse_proxy::call(remote_addr.ip(), "http://127.0.0.1:13902", req)
} else {
debug_request(req)
}
})
});
let server = Server::bind(&addr)
.serve(make_svc)
.map_err(|e| eprintln!("server error: {}", e));
println!("Running server on {:?}", addr);
// Run this server for... forever!
hyper::rt::run(server);
}
```