Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple Rust Reverse Proxy
extern crate hyper;
extern crate url;
static HOST: &'static str = "www.google.com";
macro_rules! ret_err(
($e:expr) => {{
match $e {
Ok(v) => v,
Err(e) => { println!("Line {}: {}", line!(), e); return; }
}
}}
);
/// Given a `hyper::uri::RequestUri`, rewrite it to a `Url` substituting `HOST`
/// for the domain.
fn create_proxy_url(uri: hyper::uri::RequestUri, host: &str) -> Result<url::Url, url::ParseError> {
use hyper::uri::RequestUri::*;
match uri {
AbsolutePath(val) => url::Url::parse(&format!("http://{}{}", host, val)),
AbsoluteUri(_) => Err(url::ParseError::InvalidScheme), //todo: rewrite uri
_ => Err(url::ParseError::InvalidScheme)
}
}
//todo move mut to the type
fn proxy_request(mut request: hyper::server::Request, host: &str) -> Result<hyper::client::Response, hyper::Error> {
use hyper::header::Host;
let mut client = hyper::Client::new();
// Read in the request body.
let mut request_body: Vec<u8> = Vec::new();
try!(::std::io::copy(&mut request, &mut request_body));
// The host header must be changed for compatibility with v-hosts.
let mut headers = request.headers;
headers.set(Host {
hostname: host.to_string(),
port: None
});
// Rewrite the target url from the client's request.
let url = try!(create_proxy_url(request.uri, host));
// Build and send the proxy's request.
let proxy_response = try!(
client.request(request.method, url)
.headers(headers)
.body(&request_body[..])
.send());
return Ok(proxy_response);
}
fn handler(request: hyper::server::Request, mut response: hyper::server::Response<hyper::net::Fresh>) -> () {
let mut proxy_response = ret_err!(proxy_request(request, HOST));
// Copy the proxy's response headers verbatim into the server's response
// headers.
*response.status_mut() = proxy_response.status.clone();
*response.headers_mut() = proxy_response.headers.clone();
// Write the headers and rewrite the proxy's response body to the client.
let mut response = ret_err!(response.start());
ret_err!(::std::io::copy(&mut proxy_response, &mut response));
ret_err!(response.end());
}
fn main() {
let server = hyper::Server::http(handler);
ret_err!(server.listen("127.0.0.1:3000"));
}
@chrmod

This comment has been minimized.

Copy link

@chrmod chrmod commented Apr 24, 2017

cross referencing another approach https://gist.github.com/infinityb/600c22ae549cecf43244

@juanibiapina

This comment has been minimized.

Copy link

@juanibiapina juanibiapina commented Aug 30, 2017

This is not handling query params, is it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment