Skip to content

Instantly share code, notes, and snippets.

@lsk569937453
Last active March 1, 2024 09:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lsk569937453/b42a8cfce21bd20c5da8737db1f5a1b1 to your computer and use it in GitHub Desktop.
Save lsk569937453/b42a8cfce21bd20c5da8737db1f5a1b1 to your computer and use it in GitHub Desktop.
Hyper v1 gateway performance problem
[package]
name = "hyper_1"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
name = "silverwind"
path = "src/main.rs"
[dependencies]
hyper = { version = "1.2.0", features = ["full"] }
tokio = { version = "1.36.0", features = ["full"] }
hyper-util = { version = "0.1.3", features = ["full"] }
bytes = "1"
http-body-util = { version = "0.1.0"}
anyhow = { version = "1.0.80" }
use anyhow::anyhow;
use hyper::{server::conn::http1, service::service_fn};
use std::net::SocketAddr;
use tokio::net::TcpListener;
use bytes::Bytes;
use http_body_util::{combinators::BoxBody, BodyExt, Full};
use hyper::body::Incoming;
use hyper::{Request, Response, Uri};
use hyper_util::client::legacy::{connect::HttpConnector, Client};
use hyper_util::rt::TokioIo;
use std::convert::Infallible;
use tokio::runtime;
#[tokio::main]
async fn main() {
if let Err(err) = start_with_error().await {
println!("Failed to serve the connection: {:?}", err);
}
}
async fn check(uri: Uri) -> Result<(), anyhow::Error> {
let backend_path = uri.path_and_query().ok_or(anyhow!(""))?.as_str();
Ok(())
}
async fn do_req(
client: Client<HttpConnector, BoxBody<Bytes, Infallible>>,
req: Request<BoxBody<Bytes, Infallible>>,
) -> Result<Response<BoxBody<Bytes, Infallible>>, Infallible> {
let uri = req.uri().clone();
check(uri)
.await
.map_err(|_| -> Infallible { unreachable!() })?;
let response_incoming = client
.request(req)
.await
.map_err(|_| -> Infallible { unreachable!() })?;
let res = response_incoming
.map(|b| b.boxed())
.map(|item| item.map_err(|_| -> Infallible { unreachable!() }).boxed());
Ok(res)
}
async fn start_with_error() -> Result<(), Box<dyn std::error::Error>> {
let in_addr: SocketAddr = ([0, 0, 0, 0], 6667).into();
let out_addr_clone = "http://backend:8080";
let listener = TcpListener::bind(in_addr).await?;
println!("Listening on http://{}", in_addr);
println!("Proxying on http://{}", out_addr_clone);
let client = Client::builder(hyper_util::rt::TokioExecutor::new()).build(HttpConnector::new());
loop {
let (stream, _) = listener.accept().await?;
let io = TokioIo::new(stream);
let client_clone = client.clone();
let service = service_fn(move |mut req: Request<Incoming>| {
let client_clone1 = client_clone.clone();
let uri_now: hyper::http::uri::Uri = out_addr_clone.parse().unwrap();
*req.uri_mut() = uri_now.clone();
let req = req.map(|item| item.map_err(|_| -> Infallible { unreachable!() }).boxed());
do_req(client_clone1, req)
});
tokio::task::spawn(async move {
if let Err(err) = http1::Builder::new()
.preserve_header_case(true)
.title_case_headers(true)
.serve_connection(io, service)
.await
{
println!("Failed to serve the connection: {:?}", err);
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment