use async_trait::async_trait; use hyper::{Body, Method, StatusCode}; use multilink::{ http::{ util::{ notification_sse_response, notification_sse_stream, parse_request, parse_response, serialize_to_http_request, serialize_to_http_response, validate_method, }, ModalHttpResponse, RequestHttpConvert, ResponseHttpConvert, }, jsonrpc::{JsonRpcMessage, JsonRpcNotification, JsonRpcRequest, JsonRpcResponse}, stdio::{RequestJsonRpcConvert, ResponseJsonRpcConvert}, util::parse_from_value, ProtocolError, ServiceResponse, }; use serde_json::Value; use super::{Request, Response}; const SAY_HELLO_HTTP_PATH: &str = "/say_hello"; const SAY_GREETING_HTTP_PATH: &str = "/say_greeting"; const SAY_HELLO_STREAM_HTTP_PATH: &str = "/say_hello_stream"; const SAY_HELLO_JSONRPC_METHOD: &str = "sayHello"; const SAY_GREETING_JSONRPC_METHOD: &str = "sayGreeting"; const SAY_HELLO_STREAM_JSONRPC_METHOD: &str = "sayHelloStream"; #[async_trait] impl RequestHttpConvert for Request { async fn from_http_request( request: hyper::Request, ) -> Result, ProtocolError> { let path = request.uri().path(); let request = match path { SAY_HELLO_HTTP_PATH => { validate_method(&request, Method::GET)?; Self::SayHello(parse_request(request).await?) } SAY_GREETING_HTTP_PATH => { validate_method(&request, Method::POST)?; Self::SayCustomGreeting(parse_request(request).await?) } SAY_HELLO_STREAM_HTTP_PATH => { validate_method(&request, Method::POST)?; Self::SayHelloStream(parse_request(request).await?) } _ => return Ok(None), }; Ok(Some(request)) } fn to_http_request( &self, base_url: &hyper::Uri, ) -> Result>, ProtocolError> { let request = match self { Self::SayHello(request) => { serialize_to_http_request(base_url, SAY_HELLO_HTTP_PATH, Method::GET, &request)? } Self::SayCustomGreeting(request) => { serialize_to_http_request(base_url, SAY_GREETING_HTTP_PATH, Method::POST, &request)? } Self::SayHelloStream(request) => serialize_to_http_request( base_url, SAY_HELLO_STREAM_HTTP_PATH, Method::POST, &request, )?, }; Ok(Some(request)) } } #[async_trait] impl ResponseHttpConvert for Response { async fn from_http_response( response: ModalHttpResponse, original_request: &Request, ) -> Result>, ProtocolError> { Ok(Some(match response { ModalHttpResponse::Single(response) => match original_request { Request::SayHello(_) => { ServiceResponse::Single(Self::SayHello(parse_response(response).await?)) } Request::SayCustomGreeting(_) => ServiceResponse::Single(Self::SayCustomGreeting( parse_response(response).await?, )), Request::SayHelloStream(_) => ServiceResponse::Multiple(notification_sse_stream( original_request.clone(), response, )), }, ModalHttpResponse::Event(event) => ServiceResponse::Single(match original_request { Request::SayHelloStream(_) => Self::SayHelloStream(parse_from_value(event)?), _ => return Ok(None), }), })) } fn to_http_response( response: ServiceResponse, ) -> Result, ProtocolError> { let response = match response { ServiceResponse::Single(response) => match response { Self::SayHello(response) => ModalHttpResponse::Single(serialize_to_http_response( &response, StatusCode::OK, )?), Self::SayCustomGreeting(response) => ModalHttpResponse::Single( serialize_to_http_response(&response, StatusCode::OK)?, ), Self::SayHelloStream(response) => { ModalHttpResponse::Event(serde_json::to_value(response).unwrap()) } }, ServiceResponse::Multiple(stream) => { // Output a single server-side event HTTP response ModalHttpResponse::Single(notification_sse_response(stream)) } }; Ok(Some(response)) } } impl RequestJsonRpcConvert for Request { fn from_jsonrpc_request(value: JsonRpcRequest) -> Result, ProtocolError> { Ok(Some(match value.method.as_str() { SAY_HELLO_JSONRPC_METHOD => Self::SayHello(value.parse_params()?), SAY_GREETING_JSONRPC_METHOD => Self::SayCustomGreeting(value.parse_params()?), SAY_HELLO_STREAM_JSONRPC_METHOD => Self::SayHelloStream(value.parse_params()?), _ => return Ok(None), })) } fn into_jsonrpc_request(&self) -> JsonRpcRequest { let (method, params) = match self { Self::SayHello(request) => ( SAY_HELLO_JSONRPC_METHOD, Some(serde_json::to_value(request).unwrap()), ), Self::SayCustomGreeting(request) => ( SAY_GREETING_JSONRPC_METHOD, Some(serde_json::to_value(request).unwrap()), ), Self::SayHelloStream(request) => ( SAY_HELLO_STREAM_JSONRPC_METHOD, Some(serde_json::to_value(request).unwrap()), ), }; JsonRpcRequest::new(method.to_string(), params) } } impl ResponseJsonRpcConvert for Response { fn from_jsonrpc_message( value: JsonRpcMessage, original_request: &Request, ) -> Result, ProtocolError> { match value { JsonRpcMessage::Response(resp) => { let result = resp.get_result()?; Ok(Some(match original_request { Request::SayHello(_) => Self::SayHello(parse_from_value(result)?), Request::SayCustomGreeting(_) => { Self::SayCustomGreeting(parse_from_value(result)?) } _ => return Ok(None), })) } JsonRpcMessage::Notification(resp) => { let result = resp.get_result()?; Ok(Some(match original_request { Request::SayHelloStream(_) => Self::SayHelloStream(parse_from_value(result)?), _ => return Ok(None), })) } _ => Ok(None), } } fn into_jsonrpc_message(response: Response, id: Value) -> JsonRpcMessage { let mut is_notification = false; let result = Ok(match response { Response::SayHello(response) => serde_json::to_value(response).unwrap(), Response::SayCustomGreeting(response) => serde_json::to_value(response).unwrap(), Response::SayHelloStream(response) => { is_notification = true; serde_json::to_value(response).unwrap() } }); match is_notification { true => JsonRpcNotification::new_with_result_params(result, id.to_string()).into(), false => JsonRpcResponse::new(result, id).into(), } } }