1
0
mirror of https://github.com/actix/examples synced 2025-06-26 17:17:42 +02:00

Remove old http-proxy, use the full version as the official http-proxy example (closes #164)

This commit is contained in:
Rotem Yaari
2019-08-19 21:42:31 +03:00
parent 7abc37139c
commit bc7e9f5e6b
8 changed files with 100 additions and 208 deletions

View File

@ -1,52 +1,102 @@
use actix_web::client::Client;
use actix_web::{middleware, web, App, Error, HttpResponse, HttpServer};
use actix_web::{middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer};
use clap::{value_t, Arg};
use futures::Future;
use std::net::ToSocketAddrs;
use url::Url;
/// Stream client request response and then send body to a server response
fn index(client: web::Data<Client>) -> impl Future<Item = HttpResponse, Error = Error> {
client
.get("http://127.0.0.1:8081/")
.send()
.map_err(Error::from) // <- convert SendRequestError to an Error
.and_then(|mut resp| {
resp.body() // <- this is MessageBody type, resolves to complete body
.from_err() // <- convert PayloadError to an Error
.and_then(|body| {
// <- we got complete body, now send as server response
Ok(HttpResponse::Ok().body(body))
})
})
}
/// streaming client request to a streaming server response
fn streaming(
fn forward(
req: HttpRequest,
payload: web::Payload,
url: web::Data<Url>,
client: web::Data<Client>,
) -> impl Future<Item = HttpResponse, Error = impl Into<Error>> {
// send client request
client
.get("https://www.rust-lang.org/")
.send() // <- connect to host and send request
.map_err(Error::from) // <- convert SendRequestError to an Error
.and_then(|resp| {
// <- we received client response
Ok(HttpResponse::Ok()
// read one chunk from client response and send this chunk to a server response
// .from_err() converts PayloadError to an Error
.streaming(resp))
) -> impl Future<Item = HttpResponse, Error = Error> {
let mut new_url = url.get_ref().clone();
new_url.set_path(req.uri().path());
new_url.set_query(req.uri().query());
let forwarded_req = client
.request_from(new_url.as_str(), req.head())
.no_decompress();
let forwarded_req = if let Some(addr) = req.head().peer_addr {
forwarded_req.header("x-forwarded-for", format!("{}", addr.ip()))
} else {
forwarded_req
};
forwarded_req
.send_stream(payload)
.map_err(Error::from)
.map(|res| {
let mut client_resp = HttpResponse::build(res.status());
for (header_name, header_value) in res
.headers()
.iter()
.filter(|(h, _)| *h != "connection" && *h != "content-length")
{
client_resp.header(header_name.clone(), header_value.clone());
}
client_resp.streaming(res)
})
}
fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", "actix_server=info,actix_web=trace");
env_logger::init();
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();
HttpServer::new(|| {
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();
HttpServer::new(move || {
App::new()
.data(Client::new())
.data(forward_url.clone())
.wrap(middleware::Logger::default())
.service(web::resource("/streaming").to_async(streaming))
.service(web::resource("/").to_async(index))
.default_service(web::route().to_async(forward))
})
.bind("127.0.0.1:8080")?
.bind((listen_addr, listen_port))?
.system_exit()
.run()
}

View File

@ -1,20 +0,0 @@
use actix_web::{middleware, web, App, HttpResponse, HttpServer, Responder};
fn index(body: web::Bytes) -> impl Responder {
HttpResponse::Ok().body(body)
}
fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", "actix_server=info,actix_web=trace");
env_logger::init();
HttpServer::new(|| {
App::new()
// enable logger
.wrap(middleware::Logger::default())
.service(web::resource("/index.html").to(|| "Hello world!"))
.service(web::resource("/").to(index))
})
.bind("127.0.0.1:8081")?
.run()
}