#![cfg(feature = "hyper")]
use std::convert::Infallible;
use bytes::Bytes;
use http_body_util::{BodyExt, Empty, Full};
use hyper::service::service_fn;
use hyper::{Request, Response};
use runite::hyper_rt::{RuniteExecutor, RuniteTimer};
use runite::io::AsyncReadExt;
use runite::net::{TcpListener, TcpStream};
async fn hello(_req: Request<hyper::body::Incoming>) -> Result<Response<Full<Bytes>>, Infallible> {
Ok(Response::new(Full::new(Bytes::from_static(
b"hello from runite",
))))
}
#[runite::test]
async fn http1_server_with_timer_serves_request() {
let listener = TcpListener::bind("127.0.0.1:0").await.expect("bind");
let addr = listener.local_addr().expect("addr");
let server = runite::spawn(async move {
let (stream, _peer) = listener.accept().await.expect("accept");
hyper::server::conn::http1::Builder::new()
.timer(RuniteTimer)
.header_read_timeout(std::time::Duration::from_secs(5))
.serve_connection(stream, service_fn(hello))
.await
.expect("serve http1 connection");
});
let mut client = TcpStream::connect(addr).await.expect("connect");
client
.write_all(b"GET / HTTP/1.1\r\nhost: localhost\r\nconnection: close\r\n\r\n")
.await
.expect("write request");
let mut response = Vec::new();
client
.read_to_end(&mut response)
.await
.expect("read response");
let response = String::from_utf8_lossy(&response);
assert!(response.starts_with("HTTP/1.1 200 OK"), "got: {response}");
assert!(response.ends_with("hello from runite"), "got: {response}");
server.await.expect("server task");
}
#[runite::test]
async fn http2_client_server_round_trip() {
let listener = TcpListener::bind("127.0.0.1:0").await.expect("bind");
let addr = listener.local_addr().expect("addr");
let server = runite::spawn(async move {
let (stream, _peer) = listener.accept().await.expect("accept");
let _ = hyper::server::conn::http2::Builder::new(RuniteExecutor)
.timer(RuniteTimer)
.serve_connection(stream, service_fn(hello))
.await;
});
let stream = TcpStream::connect(addr).await.expect("connect");
let (mut sender, connection) = hyper::client::conn::http2::handshake(RuniteExecutor, stream)
.await
.expect("h2 handshake");
runite::spawn(async move {
let _ = connection.await;
});
let request = Request::builder()
.method("GET")
.uri(format!("http://{addr}/"))
.body(Empty::<Bytes>::new())
.expect("request");
let response = sender.send_request(request).await.expect("send h2 request");
assert_eq!(response.status(), 200);
let body = response
.into_body()
.collect()
.await
.expect("collect h2 body")
.to_bytes();
assert_eq!(&body[..], b"hello from runite");
drop(sender); server.await.expect("server task");
}
#[cfg(unix)]
#[runite::test]
async fn http1_over_unix_stream() {
let (server_io, client_io) = runite::net::unix::UnixStream::pair().expect("pair");
let server = runite::spawn(async move {
hyper::server::conn::http1::Builder::new()
.timer(RuniteTimer)
.serve_connection(server_io, service_fn(hello))
.await
.expect("serve over unix stream");
});
let (mut sender, connection) = hyper::client::conn::http1::handshake(client_io)
.await
.expect("handshake over unix stream");
runite::spawn(async move {
let _ = connection.await;
});
let request = Request::builder()
.method("GET")
.uri("http://localhost/")
.header("host", "localhost")
.header("connection", "close")
.body(Empty::<Bytes>::new())
.expect("request");
let response = sender.send_request(request).await.expect("send request");
assert_eq!(response.status(), 200);
let body = response
.into_body()
.collect()
.await
.expect("body")
.to_bytes();
assert_eq!(&body[..], b"hello from runite");
server.await.expect("server task");
}