Created
June 25, 2017 21:58
-
-
Save cspinetta/266d238d605d4347e3aecf86e0e6cca2 to your computer and use it in GitHub Desktop.
currently with compile failed
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "toy-load-balancer" | |
version = "0.1.0" | |
authors = ["Cristian Spinetta <[email protected]>"] | |
[dependencies] | |
log = "0.3" | |
#env_logger="0.4.3" | |
pretty_env_logger = "0.1" | |
hyper = "0.11" | |
# basic dependencies from echo server before | |
futures = "0.1" | |
tokio-core = "0.1" | |
tokio-proto = "0.1" | |
tokio-service = "0.1" | |
tokio-pool = "0.1" | |
# our toy HTTP implementation | |
tokio-minihttp = { git = "https://github.com/tokio-rs/tokio-minihttp" } | |
# json | |
serde_derive = "1.0" | |
serde = "1.0" | |
serde_json = "1.0" | |
# misc support for thread pools, random numbers | |
futures-cpupool = "0.1" | |
rand = "0.3" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[macro_use] extern crate log; | |
extern crate pretty_env_logger; | |
extern crate hyper; | |
extern crate futures; | |
extern crate tokio_core; | |
extern crate tokio_pool; | |
use hyper::header::ContentLength; | |
use hyper::server::{Http, Request, Response, Service}; | |
use hyper::{Method, StatusCode}; | |
use std::ascii::AsciiExt; | |
use futures::{Stream, Future}; | |
use hyper::{Body, Chunk}; | |
use futures::future; | |
use futures::future::{Either, Map, FutureResult}; | |
use futures::stream::Concat2; | |
use std::io::{self, Write}; | |
use hyper::Client; | |
use tokio_core::reactor::Core; | |
use tokio_core::reactor::Handle; | |
use tokio_core::net::TcpListener; | |
use hyper::Uri; | |
use hyper::error::UriError; | |
use tokio_pool::TokioPool; | |
use std::sync::Arc; | |
use std::net::SocketAddr; | |
use std::cell::RefCell; | |
use std::mem; | |
use std::borrow::Borrow; | |
fn main() { | |
pretty_env_logger::init().unwrap(); | |
let (pool, join) = TokioPool::new(4) | |
.expect("Failed to create event loop"); | |
let addr: SocketAddr = "0.0.0.0:8080".parse().unwrap(); | |
let pool: Arc<TokioPool> = Arc::new(pool); | |
let service: Arc<Proxy> = Arc::new(Proxy { pool_ref: pool.clone() }); | |
let pool_ref: Arc<TokioPool> = pool.clone(); | |
let http: Arc<Http<Chunk>> = Arc::new(Http::new()); | |
pool.next_worker().spawn(move |handle| { | |
let listener = TcpListener::bind(&addr, handle).unwrap(); | |
listener.incoming().for_each(move |(socket, addr)| { | |
pool_ref.next_worker().spawn(move |handle| { | |
http.bind_connection(&handle.clone(), socket, addr, service); | |
Ok(()) | |
}); | |
Ok(()) | |
}).map_err(|err| { | |
error!("Error with TcpListener: {:?}", err); | |
}) | |
}); | |
join.join(); | |
} | |
#[derive(Clone)] | |
struct Proxy { | |
pool_ref: Arc<TokioPool> | |
} | |
impl Proxy { | |
fn create_proxy_url(&self, host: &str, uri: Uri) -> Result<Uri, UriError> { | |
format!("{}{}{}", host, uri.path(), uri.query().unwrap_or("")).parse() | |
} | |
} | |
impl Service for Proxy { | |
type Request = Request; | |
type Response = Response; | |
type Error = hyper::Error; | |
type Future = Box<Future<Item=Self::Response, Error = Self::Error>>; | |
fn call(&self, req: Self::Request) -> Self::Future { | |
let method = req.method().clone(); | |
let host = "http://localhost:8000"; // other host | |
let uri = self.create_proxy_url(host, req.uri().clone()) | |
.expect(&format!("Failed trying to parse uri. Origin: {:?}", &req.uri())); | |
let mut client_req = Request::new(method, uri); | |
client_req.headers_mut().extend(req.headers().iter()); | |
client_req.set_body(req.body()); | |
info!("Dispatching incoming connection: {:?}", client_req); | |
let new_handler = self.pool_ref.next_worker().handle().unwrap().clone(); | |
let client = Client::new(&new_handler); | |
let resp = client.request(client_req) | |
.then(move |result| { | |
match result { | |
Ok(client_resp) => { | |
Ok(client_resp) | |
} | |
Err(e) => { | |
error!("{:?}", &e); | |
Err(e) | |
} | |
} | |
}); | |
Box::new(resp) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment