Skip to content

Instantly share code, notes, and snippets.

@meganehouser
Last active January 21, 2019 19:51
Show Gist options
  • Save meganehouser/d5e1b47eb2873797ebdc440b0ed482df to your computer and use it in GitHub Desktop.
Save meganehouser/d5e1b47eb2873797ebdc440b0ed482df to your computer and use it in GitHub Desktop.
Simple http proxy on hyper and tokio
[package]
name = "proxy"
version = "0.1.0"
authors = ["meganehouser"]
[dependencies]
tokio-core = "0.1"
tokio-io = "0.1"
hyper = { git = "https://github.com/hyperium/hyper", branch="master"}
hyper-tls = { git = "https://github.com/hyperium/hyper-tls", branch="master"}
futures = "0.1.11"
extern crate tokio_core;
extern crate tokio_io;
extern crate futures;
extern crate hyper;
extern crate hyper_tls;
use std::net::SocketAddr;
use tokio_core::reactor::{Core, Handle};
use tokio_core::net::TcpListener;
use futures::Future;
use futures::stream::Stream;
use hyper::client::{self, Client};
use hyper::server::{self, Service, Http};
use hyper::error::Error;
use hyper_tls::HttpsConnector;
struct Proxy {
handle: Handle,
}
impl Service for Proxy {
type Request = server::Request;
type Response = server::Response;
type Error = Error;
type Future = Box<Future<Item=Self::Response, Error = Error>>;
fn call(&self, req: server::Request) -> Self::Future {
let method = req.method().clone();
let uri = req.uri().clone();
let mut client_req = client::Request::new(method, uri);
client_req.headers_mut().extend(req.headers().iter());
client_req.set_body(req.body());
let client = Client::configure()
.connector(HttpsConnector::new(4, &self.handle))
.build(&self.handle);
let resp = client.request(client_req)
.then(move |result| {
match result {
Ok(client_resp) => {
Ok(server::Response::new()
.with_status(client_resp.status())
.with_headers(client_resp.headers().clone())
.with_body(client_resp.body()))
}
Err(e) => {
println!("{:?}", &e);
Err(e)
}
}
});
Box::new(resp)
}
}
fn main() {
let srv_addr: SocketAddr = "127.0.0.1:8888".parse().unwrap();
let http = Http::new();
let mut core = Core::new().unwrap();
let handle = core.handle();
let listener = TcpListener::bind(&srv_addr, &handle).unwrap();
let server = listener.incoming()
.for_each(|(sock, addr)| {
let service = Proxy { handle: handle.clone() };
http.bind_connection(&handle, sock, addr, service);
Ok(())
});
core.run(server).unwrap();
}
@chrmod
Copy link

chrmod commented Apr 26, 2017

which version of hyper is in use here?

@chrmod
Copy link

chrmod commented Apr 26, 2017

@meganehouser can I publish this code under AGPL-3.0 ?

@vandenoever
Copy link

This builds with this Cargo.toml:

[package]
name = "proxy"
version = "0.1.0"
authors = []

[dependencies]
tokio-core = "*"
tokio-io = "*"
futures = "*"
hyper = { git = "https://github.com/hyperium/hyper", branch = "master"  }

I've tested it with Firefox as a SOCKS v4 proxy. It handles the http requests fine but sometimes hangs / becomes unresponsive.

Many sites use https now, so that's the next challenge. 😉

@meganehouser
Copy link
Author

@chrmod You can use this method on your code.

@vandenoever This code is toy proxy implemension and not support HTTPS. Have a nice challenge!!

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