mirror of
https://github.com/actix/examples
synced 2024-11-30 17:14:35 +01:00
Add example of a full HTTP proxy, proxying body, header and method (#58)
This commit is contained in:
parent
61a4b3b23b
commit
e30915d98d
@ -47,6 +47,7 @@ script:
|
|||||||
cd form && cargo check && cd ..
|
cd form && cargo check && cd ..
|
||||||
cd hello-world && cargo check && cd ..
|
cd hello-world && cargo check && cd ..
|
||||||
cd http-proxy && cargo check && cd ..
|
cd http-proxy && cargo check && cd ..
|
||||||
|
cd http-full-proxy && cargo check && cd ..
|
||||||
cd json && cargo check && cd ..
|
cd json && cargo check && cd ..
|
||||||
cd juniper && cargo check && cd ..
|
cd juniper && cargo check && cd ..
|
||||||
cd middleware && cargo check && cd ..
|
cd middleware && cargo check && cd ..
|
||||||
|
@ -14,6 +14,7 @@ members = [
|
|||||||
"form",
|
"form",
|
||||||
"hello-world",
|
"hello-world",
|
||||||
"http-proxy",
|
"http-proxy",
|
||||||
|
"http-full-proxy",
|
||||||
"json",
|
"json",
|
||||||
"juniper",
|
"juniper",
|
||||||
"middleware",
|
"middleware",
|
||||||
|
12
http-full-proxy/Cargo.toml
Normal file
12
http-full-proxy/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "http-full-proxy"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Rotem Yaari"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
actix = "0.7.5"
|
||||||
|
actix-web = "0.7.13"
|
||||||
|
clap = "2.32.0"
|
||||||
|
futures = "0.1.25"
|
||||||
|
failure = "0.1.3"
|
||||||
|
url = "1.7.1"
|
10
http-full-proxy/README.md
Normal file
10
http-full-proxy/README.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
## HTTP Full proxy example
|
||||||
|
|
||||||
|
This proxy forwards all types of requests, including ones with body, to another HTTP server,
|
||||||
|
returning the response to the client.
|
||||||
|
|
||||||
|
To start:
|
||||||
|
|
||||||
|
``` shell
|
||||||
|
cargo run <listen addr> <listen port> <forward addr> <forward port>
|
||||||
|
```
|
123
http-full-proxy/src/main.rs
Normal file
123
http-full-proxy/src/main.rs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#![deny(warnings)]
|
||||||
|
extern crate actix;
|
||||||
|
extern crate actix_web;
|
||||||
|
extern crate clap;
|
||||||
|
extern crate failure;
|
||||||
|
extern crate futures;
|
||||||
|
extern crate url;
|
||||||
|
|
||||||
|
use actix_web::{
|
||||||
|
client, http, server, App, AsyncResponder, Error, HttpMessage, HttpRequest,
|
||||||
|
HttpResponse,
|
||||||
|
};
|
||||||
|
use clap::{value_t, Arg};
|
||||||
|
use futures::Future;
|
||||||
|
use std::net::ToSocketAddrs;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
struct AppState {
|
||||||
|
forward_url: Url,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppState {
|
||||||
|
pub fn init(forward_url: Url) -> AppState {
|
||||||
|
AppState { forward_url }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn forward(
|
||||||
|
req: &HttpRequest<AppState>,
|
||||||
|
) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||||
|
let mut new_url = req.state().forward_url.clone();
|
||||||
|
new_url.set_path(req.uri().path());
|
||||||
|
new_url.set_query(req.uri().query());
|
||||||
|
|
||||||
|
let mut forwarded_req = client::ClientRequest::build_from(req)
|
||||||
|
.no_default_headers()
|
||||||
|
.uri(new_url)
|
||||||
|
.streaming(req.payload())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if let Some(addr) = req.peer_addr() {
|
||||||
|
match forwarded_req.headers_mut().entry("x-forwarded-for") {
|
||||||
|
Ok(http::header::Entry::Vacant(entry)) => {
|
||||||
|
let addr = format!("{}", addr.ip());
|
||||||
|
entry.insert(addr.parse().unwrap());
|
||||||
|
}
|
||||||
|
Ok(http::header::Entry::Occupied(mut entry)) => {
|
||||||
|
let addr = format!("{}, {}", entry.get().to_str().unwrap(), addr.ip());
|
||||||
|
entry.insert(addr.parse().unwrap());
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
forwarded_req
|
||||||
|
.send()
|
||||||
|
.map_err(Error::from)
|
||||||
|
.and_then(move |resp| {
|
||||||
|
let mut client_resp = HttpResponse::build(resp.status());
|
||||||
|
for (header_name, header_value) in
|
||||||
|
resp.headers().iter().filter(|(h, _)| *h != "connection")
|
||||||
|
{
|
||||||
|
client_resp.header(header_name.clone(), header_value.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(client_resp.streaming(resp.payload()))
|
||||||
|
}).responder()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let matches = clap::App::new("HTTP Proxy")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("listen_addr")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("LISTEN ADDR")
|
||||||
|
.index(1)
|
||||||
|
.required(true),
|
||||||
|
).arg(
|
||||||
|
Arg::with_name("listen_port")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("LISTEN PORT")
|
||||||
|
.index(2)
|
||||||
|
.required(true),
|
||||||
|
).arg(
|
||||||
|
Arg::with_name("forward_addr")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("FWD ADDR")
|
||||||
|
.index(3)
|
||||||
|
.required(true),
|
||||||
|
).arg(
|
||||||
|
Arg::with_name("forward_port")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("FWD PORT")
|
||||||
|
.index(4)
|
||||||
|
.required(true),
|
||||||
|
).get_matches();
|
||||||
|
|
||||||
|
let listen_addr = matches.value_of("listen_addr").unwrap();
|
||||||
|
let listen_port = value_t!(matches, "listen_port", u16).unwrap_or_else(|e| e.exit());
|
||||||
|
|
||||||
|
let forwarded_addr = matches.value_of("forward_addr").unwrap();
|
||||||
|
let forwarded_port =
|
||||||
|
value_t!(matches, "forward_port", u16).unwrap_or_else(|e| e.exit());
|
||||||
|
|
||||||
|
let forward_url = Url::parse(&format!(
|
||||||
|
"http://{}",
|
||||||
|
(forwarded_addr, forwarded_port)
|
||||||
|
.to_socket_addrs()
|
||||||
|
.unwrap()
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
)).unwrap();
|
||||||
|
|
||||||
|
server::new(move || {
|
||||||
|
App::with_state(AppState::init(forward_url.clone())).default_resource(|r| {
|
||||||
|
r.f(forward);
|
||||||
|
})
|
||||||
|
}).workers(32)
|
||||||
|
.bind((listen_addr, listen_port))
|
||||||
|
.expect("Cannot bind listening port")
|
||||||
|
.system_exit()
|
||||||
|
.run();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user