use std::{net::SocketAddr, str::FromStr, time::Duration};
use spacegate_kernel::{
listener::SgListen,
service::{
http_gateway,
http_route::{match_request::HttpPathMatchRewrite, HttpBackend, HttpRoute, HttpRouteRule},
},
};
use tokio_rustls::rustls::ServerConfig;
use tokio_util::sync::CancellationToken;
#[tokio::test]
async fn test_https() {
tokio::spawn(gateway());
tokio::spawn(axum_server());
tokio::time::sleep(Duration::from_millis(200)).await;
let client = reqwest::Client::builder().danger_accept_invalid_certs(true).build().unwrap();
let echo = client.post("https://[::]:9443/tls/echo").body("1").send().await.expect("fail to send").text().await.expect("fail to get text");
println!("echo: {}", echo);
let echo = client.get("https://[::]:9443/baidu").send().await.expect("fail to send").text().await.expect("fail to get text");
println!("echo: {}", echo);
let echo = client.post("http://[::]:9443/tls/echo").body("1").send().await.expect_err("should be error");
eprintln!("echo: {}", echo);
let echo = client.post("http://[::]:9080/tls/echo").body("1").send().await.expect("fail to send").text().await.expect("fail to get text");
println!("echo: {}", echo);
}
async fn gateway() {
let cancel = CancellationToken::default();
let gateway = http_gateway::Gateway::builder("test_multi_part")
.http_routers([(
"test_upload".to_string(),
HttpRoute::builder()
.rule(HttpRouteRule::builder().match_item(HttpPathMatchRewrite::prefix("/tls")).backend(HttpBackend::builder().host("[::]").port(9003).build()).build())
.rule(
HttpRouteRule::builder()
.match_item(HttpPathMatchRewrite::prefix("/baidu"))
.backend(HttpBackend::builder().schema("https").host("www.baidu.com").port(443).build())
.build(),
)
.build(),
)])
.build();
let cert = include_bytes!("test_https/.cert");
let key = include_bytes!("test_https/.key");
let _ = tokio_rustls::rustls::crypto::ring::default_provider().install_default();
let tls_config = ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(
rustls_pemfile::certs(&mut cert.as_slice()).filter_map(Result::ok).collect(),
rustls_pemfile::private_key(&mut key.as_slice()).ok().flatten().expect("fail to get key"),
)
.expect("fail to build tls config");
let http_listener = SgListen::new(SocketAddr::from_str("[::]:9080").expect("invalid host"), cancel.child_token()).with_service(gateway.as_service().http());
let https_listener = SgListen::new(SocketAddr::from_str("[::]:9443").expect("invalid host"), cancel.child_token()).with_service(gateway.as_service().https(tls_config));
let task = tokio::spawn(async move {
http_listener.listen().await.expect("fail to listen");
});
let task_tls = tokio::spawn(async move {
https_listener.listen().await.expect("fail to listen");
});
let (_, _) = tokio::join!(task, task_tls);
}
async fn axum_server() {
use axum::{response::IntoResponse, serve, Router};
pub async fn echo(text: String) -> impl IntoResponse {
text
}
serve(
tokio::net::TcpListener::bind("[::]:9003").await.expect("fail to bind"),
Router::new().route("/tls/echo", axum::routing::post(echo)),
)
.await
.expect("fail to serve");
}