hyper-reverse-proxy/tests/test_http.rs

108 lines
3.2 KiB
Rust
Raw Normal View History

use hyper::server::conn::AddrStream;
2022-04-12 14:41:51 +00:00
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Client, Request, Response, Server, StatusCode, Uri};
use std::convert::Infallible;
use std::net::{IpAddr, SocketAddr};
2022-04-12 14:41:51 +00:00
use test_context::test_context;
use test_context::AsyncTestContext;
use tokio::sync::oneshot::Sender;
use tokio::task::JoinHandle;
use tokiotest_httpserver::handler::HandlerBuilder;
2022-04-12 14:41:51 +00:00
use tokiotest_httpserver::{take_port, HttpTestContext};
struct ProxyTestContext {
sender: Sender<()>,
proxy_handler: JoinHandle<Result<(), hyper::Error>>,
http_back: HttpTestContext,
2022-04-12 14:41:51 +00:00
port: u16,
}
#[test_context(ProxyTestContext)]
#[tokio::test]
async fn test_get_error_500(ctx: &mut ProxyTestContext) {
2022-04-12 14:41:51 +00:00
let client = Client::new();
let resp = client
.request(
Request::builder()
.header("keep-alive", "treu")
.method("GET")
.uri(ctx.uri("/500"))
.body(Body::from(""))
.unwrap(),
)
.await
.unwrap();
assert_eq!(500, resp.status());
}
#[test_context(ProxyTestContext)]
#[tokio::test]
async fn test_get(ctx: &mut ProxyTestContext) {
2022-04-12 14:41:51 +00:00
ctx.http_back.add(
HandlerBuilder::new("/foo")
.status_code(StatusCode::OK)
.build(),
);
let resp = Client::new().get(ctx.uri("/foo")).await.unwrap();
assert_eq!(200, resp.status());
}
2022-04-12 14:41:51 +00:00
async fn handle(
client_ip: IpAddr,
req: Request<Body>,
backend_port: u16,
) -> Result<Response<Body>, Infallible> {
match hyper_reverse_proxy::call(
client_ip,
format!("http://127.0.0.1:{}", backend_port).as_str(),
req,
)
.await
{
Ok(response) => Ok(response),
Err(_) => Ok(Response::builder().status(502).body(Body::empty()).unwrap()),
}
}
#[async_trait::async_trait]
impl AsyncTestContext for ProxyTestContext {
async fn setup() -> ProxyTestContext {
let http_back: HttpTestContext = AsyncTestContext::setup().await;
let (sender, receiver) = tokio::sync::oneshot::channel::<()>();
let bp_to_move = http_back.port;
let make_svc = make_service_fn(move |conn: &AddrStream| {
let remote_addr = conn.remote_addr().ip();
let back_port = bp_to_move;
async move {
Ok::<_, Infallible>(service_fn(move |req| handle(remote_addr, req, back_port)))
}
});
let port = take_port();
let addr = SocketAddr::new("127.0.0.1".parse().unwrap(), port);
2022-04-12 14:41:51 +00:00
let server = Server::bind(&addr)
.serve(make_svc)
.with_graceful_shutdown(async {
receiver.await.ok();
});
let proxy_handler = tokio::spawn(server);
ProxyTestContext {
sender,
proxy_handler,
http_back,
2022-04-12 14:41:51 +00:00
port,
}
}
async fn teardown(self) {
let _ = AsyncTestContext::teardown(self.http_back);
let _ = self.sender.send(()).unwrap();
let _ = tokio::join!(self.proxy_handler);
}
}
impl ProxyTestContext {
pub fn uri(&self, path: &str) -> Uri {
2022-04-12 14:41:51 +00:00
format!("http://{}:{}{}", "localhost", self.port, path)
.parse::<Uri>()
.unwrap()
}
2022-04-12 14:41:51 +00:00
}