#![allow(clippy::disallowed_types)]
mod common;
use std::time::Duration;
use iroh_http_core::{ffi_serve, IrohEndpoint, RequestPayload, ServeOptions, ALPN, ALPN_DUPLEX};
fn server_addr(server_ep: &IrohEndpoint) -> iroh::EndpointAddr {
let mut addr = iroh::EndpointAddr::new(server_ep.raw().id());
for a in common::server_addrs(server_ep) {
addr = addr.with_ip_addr(a);
}
addr
}
#[tokio::test]
async fn serve_loop_rejects_non_http_alpn() {
let (server_ep, client_ep) = common::make_pair().await;
let addr = server_addr(&server_ep);
let _serve = ffi_serve(
server_ep.clone(),
ServeOptions::default(),
|_p: RequestPayload| {},
);
let conn = client_ep
.raw()
.connect(addr, ALPN_DUPLEX)
.await
.expect("duplex ALPN negotiates — the server advertises it");
assert_eq!(conn.alpn(), ALPN_DUPLEX);
let err = tokio::time::timeout(Duration::from_secs(5), conn.closed())
.await
.expect("server should close the non-HTTP connection, not hang");
match err {
iroh::endpoint::ConnectionError::ApplicationClosed(info) => {
assert_eq!(&info.reason[..], b"unexpected ALPN");
}
other => panic!("expected an application close, got: {other:?}"),
}
}
#[tokio::test]
async fn serve_loop_times_out_slow_request_head() {
let (server_ep, client_ep) = common::make_pair().await;
let addr = server_addr(&server_ep);
let opts = ServeOptions {
request_timeout_ms: Some(200),
..Default::default()
};
let _serve = ffi_serve(server_ep.clone(), opts, |_p: RequestPayload| {});
let conn = client_ep
.raw()
.connect(addr, ALPN)
.await
.expect("HTTP ALPN negotiates");
let (mut send, mut recv) = conn.open_bi().await.expect("open bistream");
send.write_all(b"GET / HTTP/1.1\r\nHost: x\r\n")
.await
.expect("write partial head");
let read = tokio::time::timeout(Duration::from_secs(5), recv.read_to_end(1024)).await;
assert!(
read.is_ok(),
"server must time out a slow request head instead of hanging",
);
drop(send);
}