port lib to hyper 0.13 and future 0.3
This commit is contained in:
parent
b53642da26
commit
d838516387
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
/target/
|
/target/
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
/.idea
|
||||||
|
*.swp
|
||||||
|
15
Cargo.toml
15
Cargo.toml
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "hyper-reverse-proxy"
|
name = "hyper-reverse-proxy"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
authors = ["Brendan Zabarauskas <bjzaba@yahoo.com.au>", "Felipe Noronha <felipenoris@gmail.com>"]
|
authors = ["Brendan Zabarauskas <bjzaba@yahoo.com.au>", "Felipe Noronha <felipenoris@gmail.com>", "Jan Kantert <jan-hyper-reverse-proxy@kantert.net>"]
|
||||||
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/felipenoris/hyper-reverse-proxy"
|
homepage = "https://github.com/felipenoris/hyper-reverse-proxy"
|
||||||
@ -19,7 +19,10 @@ include = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
hyper = "0.12"
|
hyper = "0.13"
|
||||||
futures = "0.1"
|
futures = "0.3"
|
||||||
lazy_static = "1.3"
|
lazy_static = "1.4"
|
||||||
unicase = "2.3"
|
unicase = "2.6"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tokio = { version = "0.2", features = ["full"] }
|
||||||
|
122
src/lib.rs
122
src/lib.rs
@ -17,9 +17,10 @@
|
|||||||
//!
|
//!
|
||||||
//! ```toml
|
//! ```toml
|
||||||
//! [dependencies]
|
//! [dependencies]
|
||||||
//! hyper-reverse-proxy = "0.4"
|
//! hyper-reverse-proxy = "0.5"
|
||||||
//! hyper = "0.12"
|
//! hyper = "0.13"
|
||||||
//! futures = "0.1"
|
//! futures = "0.3"
|
||||||
|
//! tokio = { version = "0.2", features = ["full"] }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! The following example will set up a reverse proxy listening on `127.0.0.1:13900`,
|
//! The following example will set up a reverse proxy listening on `127.0.0.1:13900`,
|
||||||
@ -36,62 +37,59 @@
|
|||||||
//! use hyper::{Body, Request, Response, Server};
|
//! use hyper::{Body, Request, Response, Server};
|
||||||
//! use hyper::service::{service_fn, make_service_fn};
|
//! use hyper::service::{service_fn, make_service_fn};
|
||||||
//! use futures::future::{self, Future};
|
//! use futures::future::{self, Future};
|
||||||
|
//! use std::{convert::Infallible, net::SocketAddr};
|
||||||
|
//! use hyper::http::uri::InvalidUri;
|
||||||
|
//! use std::net::IpAddr;
|
||||||
//!
|
//!
|
||||||
//! type BoxFut = Box<Future<Item=Response<Body>, Error=hyper::Error> + Send>;
|
//! fn debug_request(req: Request<Body>) -> Result<Response<Body>, Infallible> {
|
||||||
//!
|
|
||||||
//! fn debug_request(req: Request<Body>) -> BoxFut {
|
|
||||||
//! let body_str = format!("{:?}", req);
|
//! let body_str = format!("{:?}", req);
|
||||||
//! let response = Response::new(Body::from(body_str));
|
//! Ok(Response::new(Body::from(body_str)))
|
||||||
//! Box::new(future::ok(response))
|
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
//! async fn handle(client_ip: IpAddr, req: Request<Body>) -> Result<Response<Body>, Infallible> {
|
||||||
//!
|
|
||||||
//! // This is our socket address...
|
|
||||||
//! let addr = ([127, 0, 0, 1], 13900).into();
|
|
||||||
//!
|
|
||||||
//! // A `Service` is needed for every connection.
|
|
||||||
//! let make_svc = make_service_fn(|socket: &AddrStream| {
|
|
||||||
//! let remote_addr = socket.remote_addr();
|
|
||||||
//! service_fn(move |req: Request<Body>| { // returns BoxFut
|
|
||||||
//!
|
|
||||||
//! if req.uri().path().starts_with("/target/first") {
|
//! if req.uri().path().starts_with("/target/first") {
|
||||||
//!
|
|
||||||
//! // will forward requests to port 13901
|
//! // will forward requests to port 13901
|
||||||
//! return hyper_reverse_proxy::call(remote_addr.ip(), "http://127.0.0.1:13901", req)
|
//! Ok(hyper_reverse_proxy::call(client_ip, "http://127.0.0.1:13901", req).await.unwrap())
|
||||||
//!
|
//!
|
||||||
//! } else if req.uri().path().starts_with("/target/second") {
|
//! } else if req.uri().path().starts_with("/target/second") {
|
||||||
//!
|
//!
|
||||||
//! // will forward requests to port 13902
|
//! // will forward requests to port 13902
|
||||||
//! return hyper_reverse_proxy::call(remote_addr.ip(), "http://127.0.0.1:13902", req)
|
//! Ok(hyper_reverse_proxy::call(client_ip, "http://127.0.0.1:13902", req).await.unwrap())
|
||||||
//!
|
//!
|
||||||
//! } else {
|
//! } else {
|
||||||
//! debug_request(req)
|
//! debug_request(req)
|
||||||
//! }
|
//! }
|
||||||
//! })
|
//! }
|
||||||
|
//!
|
||||||
|
//! #[tokio::main]
|
||||||
|
//! async fn main() {
|
||||||
|
//! let bind_addr = "127.0.0.1:8000";
|
||||||
|
//! let addr:SocketAddr = bind_addr.parse().expect("Could not parse ip:port.");
|
||||||
|
//!
|
||||||
|
//! let make_svc = make_service_fn(|conn: &AddrStream| {
|
||||||
|
//! let remote_addr = conn.remote_addr().ip();
|
||||||
|
//! async move {
|
||||||
|
//! Ok::<_, Infallible>(service_fn(move |req| handle(remote_addr, req)))
|
||||||
|
//! }
|
||||||
//! });
|
//! });
|
||||||
//!
|
//!
|
||||||
//! let server = Server::bind(&addr)
|
//! let server = Server::bind(&addr).serve(make_svc);
|
||||||
//! .serve(make_svc)
|
//!
|
||||||
//! .map_err(|e| eprintln!("server error: {}", e));
|
//! if let Err(e) = server.await {
|
||||||
|
//! eprintln!("server error: {}", e);
|
||||||
|
//! }
|
||||||
//!
|
//!
|
||||||
//! println!("Running server on {:?}", addr);
|
//! println!("Running server on {:?}", addr);
|
||||||
//!
|
|
||||||
//! // Run this server for... forever!
|
|
||||||
//! hyper::rt::run(server);
|
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use hyper::Body;
|
use hyper::header::{HeaderMap, HeaderValue};
|
||||||
|
use hyper::http::uri::InvalidUri;
|
||||||
|
use hyper::{Body, Client, Request, Response, StatusCode, Uri};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use std::str::FromStr;
|
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 {
|
fn is_hop_header(name: &str) -> bool {
|
||||||
use unicase::Ascii;
|
use unicase::Ascii;
|
||||||
@ -133,66 +131,58 @@ fn create_proxied_response<B>(mut response: Response<B>) -> Response<B> {
|
|||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
fn forward_uri<B>(forward_url: &str, req: &Request<B>) -> Uri {
|
fn forward_uri<B>(forward_url: &str, req: &Request<B>) -> Result<Uri, InvalidUri> {
|
||||||
let forward_uri = match req.uri().query() {
|
let forward_uri = match req.uri().query() {
|
||||||
Some(query) => format!("{}{}?{}", forward_url, req.uri().path(), query),
|
Some(query) => format!("{}{}?{}", forward_url, req.uri().path(), query),
|
||||||
None => format!("{}{}", forward_url, req.uri().path()),
|
None => format!("{}{}", forward_url, req.uri().path()),
|
||||||
};
|
};
|
||||||
|
|
||||||
Uri::from_str(forward_uri.as_str()).unwrap()
|
Uri::from_str(forward_uri.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_proxied_request<B>(client_ip: IpAddr, forward_url: &str, mut request: Request<B>) -> Request<B> {
|
fn create_proxied_request<B>(
|
||||||
|
client_ip: IpAddr,
|
||||||
|
forward_url: &str,
|
||||||
|
mut request: Request<B>,
|
||||||
|
) -> Result<Request<B>, InvalidUri> {
|
||||||
*request.headers_mut() = remove_hop_headers(request.headers());
|
*request.headers_mut() = remove_hop_headers(request.headers());
|
||||||
*request.uri_mut() = forward_uri(forward_url, &request);
|
*request.uri_mut() = forward_uri(forward_url, &request)?;
|
||||||
|
|
||||||
let x_forwarded_for_header_name = "x-forwarded-for";
|
let x_forwarded_for_header_name = "x-forwarded-for";
|
||||||
|
|
||||||
// Add forwarding information in the headers
|
// Add forwarding information in the headers
|
||||||
match request.headers_mut().entry(x_forwarded_for_header_name) {
|
match request.headers_mut().entry(x_forwarded_for_header_name) {
|
||||||
|
|
||||||
Ok(header_entry) => {
|
|
||||||
match header_entry {
|
|
||||||
hyper::header::Entry::Vacant(entry) => {
|
hyper::header::Entry::Vacant(entry) => {
|
||||||
let addr = format!("{}", client_ip);
|
entry.insert(client_ip.to_string().parse().unwrap());
|
||||||
entry.insert(addr.parse().unwrap());
|
}
|
||||||
},
|
|
||||||
|
|
||||||
hyper::header::Entry::Occupied(mut entry) => {
|
hyper::header::Entry::Occupied(mut entry) => {
|
||||||
let addr = format!("{}, {}", entry.get().to_str().unwrap(), client_ip);
|
let addr = format!("{}, {}", entry.get().to_str().unwrap(), client_ip);
|
||||||
entry.insert(addr.parse().unwrap());
|
entry.insert(addr.parse().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
// shouldn't happen...
|
pub async fn call(
|
||||||
Err(_) => panic!("Invalid header name: {}", x_forwarded_for_header_name),
|
client_ip: IpAddr,
|
||||||
}
|
forward_uri: &str,
|
||||||
|
request: Request<Body>,
|
||||||
request
|
) -> Result<Response<Body>, InvalidUri> {
|
||||||
}
|
let proxied_request = create_proxied_request(client_ip, &forward_uri, 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 client = Client::new();
|
||||||
let response = client.request(proxied_request).then(|response| {
|
let response = client.request(proxied_request).await;
|
||||||
|
|
||||||
let proxied_response = match response {
|
let proxied_response = match response {
|
||||||
Ok(response) => create_proxied_response(response),
|
Ok(response) => create_proxied_response(response),
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
println!("Error: {}", error); // TODO: Configurable logging
|
println!("Error: {}", error); // TODO: Configurable logging
|
||||||
Response::builder()
|
Response::builder()
|
||||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
.status(StatusCode::SERVICE_UNAVAILABLE)
|
||||||
.body(Body::empty())
|
.body(Body::empty())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
Ok(proxied_response)
|
||||||
|
|
||||||
future::ok(proxied_response)
|
|
||||||
});
|
|
||||||
|
|
||||||
Box::new(response)
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user