karyon_jsonrpc/server/http/
mod.rs1mod h1h2;
4#[cfg(feature = "http3")]
5mod h3;
6
7use std::{net::SocketAddr, sync::Arc};
8
9use bytes::Bytes;
10use http_body_util::Full;
11use hyper::{Response, StatusCode};
12
13use karyon_core::async_runtime::net::TcpListener;
14
15#[cfg(feature = "http3")]
16use karyon_core::async_util::select;
17
18use karyon_net::Endpoint;
19
20pub(super) use crate::hyper_exec::HyperExecutor;
21
22use crate::{
23 error::{Error, Result},
24 server::Server,
25};
26
27pub(super) const MAX_HTTP_BODY_SIZE: u64 = 1024 * 1024;
29
30pub(super) const ERR_METHOD_NOT_ALLOWED: &str = r#"{"jsonrpc":"2.0","error":{"code":-32600,"message":"Only POST method is accepted"},"id":null}"#;
32pub(super) const ERR_BODY_TOO_LARGE: &str =
33 r#"{"jsonrpc":"2.0","error":{"code":-32600,"message":"Request body too large"},"id":null}"#;
34pub(super) const ERR_READ_BODY: &str = r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Failed to read request body"},"id":null}"#;
35
36pub(crate) struct HttpServer {
38 tcp_listener: TcpListener,
39 #[cfg(feature = "http3")]
40 quic_endpoint: Option<karyon_net::quic::QuicEndpoint>,
41}
42
43impl HttpServer {
44 pub(crate) async fn new(endpoint: &Endpoint) -> Result<Self> {
46 let addr = SocketAddr::try_from(endpoint.clone())?;
47 let tcp_listener = TcpListener::bind(addr).await?;
48 Ok(Self {
49 tcp_listener,
50 #[cfg(feature = "http3")]
51 quic_endpoint: None,
52 })
53 }
54
55 #[cfg(feature = "http3")]
57 pub(crate) async fn new_h3(
58 endpoint: &Endpoint,
59 quic_config: karyon_net::quic::ServerQuicConfig,
60 ) -> Result<Self> {
61 let addr = SocketAddr::try_from(endpoint.clone())?;
62 let tcp_listener = TcpListener::bind(addr).await?;
63 let actual_addr = tcp_listener.local_addr()?;
64 let quic_ep_addr = Endpoint::new_quic_addr(actual_addr);
65 let quic_endpoint =
66 karyon_net::quic::QuicEndpoint::listen(&quic_ep_addr, quic_config).await?;
67 Ok(Self {
68 tcp_listener,
69 quic_endpoint: Some(quic_endpoint),
70 })
71 }
72
73 pub(crate) fn local_endpoint(&self) -> Result<Endpoint> {
74 let addr = self.tcp_listener.local_addr()?;
75 format!("http://{addr}/")
76 .parse()
77 .map_err(|e: karyon_net::Error| Error::HttpError(e.to_string()))
78 }
79}
80
81pub(crate) async fn accept_loop(server: Arc<Server>, http_server: &HttpServer) -> Result<()> {
83 #[cfg(feature = "http3")]
84 if let Some(ref quic_ep) = http_server.quic_endpoint {
85 loop {
86 select(
87 h1h2::accept_tcp(&server, &http_server.tcp_listener),
88 h3::accept_h3(&server, quic_ep),
89 )
90 .await;
91 }
92 }
93
94 loop {
95 h1h2::accept_tcp(&server, &http_server.tcp_listener).await;
96 }
97}
98
99pub(super) fn json_response(status: StatusCode, body: &str) -> Response<Full<Bytes>> {
102 Response::builder()
103 .status(status)
104 .header("Content-Type", "application/json")
105 .body(Full::new(Bytes::from(body.to_string())))
106 .unwrap()
107}
108
109pub(super) fn json_response_bytes(status: StatusCode, body: Vec<u8>) -> Response<Full<Bytes>> {
110 Response::builder()
111 .status(status)
112 .header("Content-Type", "application/json")
113 .body(Full::new(Bytes::from(body)))
114 .unwrap()
115}