updates to hyper 0.12.16
This commit is contained in:
parent
d45b2f71d0
commit
692d287ee4
21
Cargo.toml
21
Cargo.toml
@ -1,12 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "hyper-reverse-proxy"
|
name = "hyper-reverse-proxy"
|
||||||
version = "0.2.1"
|
version = "0.3.0"
|
||||||
authors = ["Brendan Zabarauskas <bjzaba@yahoo.com.au>"]
|
authors = ["Brendan Zabarauskas <bjzaba@yahoo.com.au>", "Felipe Noronha <felipenoris@gmail.com>"]
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
description = "A simple reverse proxy, to be used with Hyper and Tokio."
|
description = "A simple reverse proxy, to be used with Hyper and Tokio."
|
||||||
homepage = "https://github.com/brendanzab/hyper-reverse-proxy"
|
homepage = "https://github.com/felipenoris/hyper-reverse-proxy"
|
||||||
documentation = "https://docs.rs/hyper-reverse-proxy"
|
documentation = "https://docs.rs/hyper-reverse-proxy"
|
||||||
repository = "https://github.com/brendanzab/hyper-reverse-proxy"
|
repository = "https://github.com/felipenoris/hyper-reverse-proxy"
|
||||||
keywords = ["http", "hyper"]
|
keywords = ["http", "hyper"]
|
||||||
categories = ["network-programming", "web-programming"]
|
categories = ["network-programming", "web-programming"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
@ -18,12 +18,7 @@ include = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures = "0.1.14"
|
hyper = "0.12.16"
|
||||||
hyper = "0.11.0"
|
futures = "0.1"
|
||||||
lazy_static = "0.2"
|
lazy_static = "1.1"
|
||||||
unicase = "2.0.0"
|
unicase = "2.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
error-chain = "0.10.0"
|
|
||||||
tokio-core = "0.1.8"
|
|
||||||
tokio-signal = "0.1.2"
|
|
||||||
|
111
src/lib.rs
Normal file
111
src/lib.rs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
|
||||||
|
extern crate hyper;
|
||||||
|
extern crate futures;
|
||||||
|
extern crate lazy_static;
|
||||||
|
extern crate unicase;
|
||||||
|
|
||||||
|
use hyper::Body;
|
||||||
|
use std::net::IpAddr;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use hyper::header::{HeaderMap, HeaderValue};
|
||||||
|
use hyper::{Request, Response, Client, Uri, StatusCode};
|
||||||
|
use futures::future::{self, Future};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
type BoxFut = Box<Future<Item=Response<Body>, Error=hyper::Error> + Send>;
|
||||||
|
|
||||||
|
fn is_hop_header(name: &str) -> bool {
|
||||||
|
use unicase::Ascii;
|
||||||
|
|
||||||
|
// A list of the headers, using `unicase` to help us compare without
|
||||||
|
// worrying about the case, and `lazy_static!` to prevent reallocation
|
||||||
|
// of the vector.
|
||||||
|
lazy_static! {
|
||||||
|
static ref HOP_HEADERS: Vec<Ascii<&'static str>> = vec![
|
||||||
|
Ascii::new("Connection"),
|
||||||
|
Ascii::new("Keep-Alive"),
|
||||||
|
Ascii::new("Proxy-Authenticate"),
|
||||||
|
Ascii::new("Proxy-Authorization"),
|
||||||
|
Ascii::new("Te"),
|
||||||
|
Ascii::new("Trailers"),
|
||||||
|
Ascii::new("Transfer-Encoding"),
|
||||||
|
Ascii::new("Upgrade"),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
HOP_HEADERS.iter().any(|h| h == &name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a clone of the headers without the [hop-by-hop headers].
|
||||||
|
///
|
||||||
|
/// [hop-by-hop headers]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
|
||||||
|
fn remove_hop_headers(headers: &HeaderMap<HeaderValue>) -> HeaderMap<HeaderValue> {
|
||||||
|
let mut result = HeaderMap::new();
|
||||||
|
for (k, v) in headers.iter() {
|
||||||
|
if !is_hop_header(k.as_str()) {
|
||||||
|
result.insert(k.clone(), v.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_proxied_response<B>(mut response: Response<B>) -> Response<B> {
|
||||||
|
*response.headers_mut() = remove_hop_headers(response.headers());
|
||||||
|
response
|
||||||
|
}
|
||||||
|
|
||||||
|
fn forward_uri<B>(forward_url: &str, req: &Request<B>) -> Uri {
|
||||||
|
let forward_uri = match req.uri().query() {
|
||||||
|
Some(query) => format!("{}{}?{}", forward_url, req.uri().path(), query),
|
||||||
|
None => format!("{}{}", forward_url, req.uri().path()),
|
||||||
|
};
|
||||||
|
|
||||||
|
Uri::from_str(forward_uri.as_str()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_proxied_request<B>(client_ip: IpAddr, forward_url: &str, mut request: Request<B>) -> Request<B> {
|
||||||
|
*request.headers_mut() = remove_hop_headers(request.headers());
|
||||||
|
*request.uri_mut() = forward_uri(forward_url, &request);
|
||||||
|
|
||||||
|
// Add forwarding information in the headers
|
||||||
|
match request.headers_mut().entry("x-forwarded-for") {
|
||||||
|
Ok(hyper::header::Entry::Vacant(entry)) => {
|
||||||
|
let addr = format!("{}", client_ip);
|
||||||
|
entry.insert(addr.parse().unwrap());
|
||||||
|
},
|
||||||
|
|
||||||
|
Ok(hyper::header::Entry::Occupied(mut entry)) => {
|
||||||
|
let addr = format!("{}, {}", entry.get().to_str().unwrap(), client_ip);
|
||||||
|
entry.insert(addr.parse().unwrap());
|
||||||
|
},
|
||||||
|
|
||||||
|
_ => (), // silently fails to add x-forwarded-for header
|
||||||
|
}
|
||||||
|
|
||||||
|
request
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call(client_ip: IpAddr, forward_uri: &str, request: Request<Body>) -> BoxFut {
|
||||||
|
|
||||||
|
let proxied_request = create_proxied_request(client_ip, forward_uri, request);
|
||||||
|
|
||||||
|
let client = Client::new();
|
||||||
|
let response = client.request(proxied_request).then(|response| {
|
||||||
|
|
||||||
|
let proxied_response = match response {
|
||||||
|
Ok(response) => create_proxied_response(response),
|
||||||
|
Err(error) => {
|
||||||
|
println!("Error: {}", error); // TODO: Configurable logging
|
||||||
|
Response::builder()
|
||||||
|
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
|
.body(Body::empty())
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
future::ok(proxied_response)
|
||||||
|
});
|
||||||
|
|
||||||
|
Box::new(response)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user