pub use hyper;
use hyper::{Body, StatusCode, Uri};
pub use hyper::{Request as HttpRequest, Response as HttpResponse};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use thiserror::Error;
use crate::{
error::{ProtocolErrorType, SerializableProtocolError},
ProtocolError, ServiceResponse,
};
#[cfg(any(feature = "http-client"))]
pub mod client;
#[cfg(any(feature = "http-server"))]
pub mod server;
pub mod util;
const API_KEY_HEADER: &str = "X-API-Key";
const SSE_DATA_PREFIX: &str = "data: ";
#[derive(Debug, Error, Serialize, Deserialize)]
#[error("{error}")]
pub struct ProtocolHttpError {
pub error: String,
}
impl Into<StatusCode> for ProtocolErrorType {
fn into(self) -> StatusCode {
match self {
ProtocolErrorType::BadRequest => StatusCode::BAD_REQUEST,
ProtocolErrorType::Unauthorized => StatusCode::UNAUTHORIZED,
ProtocolErrorType::Internal => StatusCode::INTERNAL_SERVER_ERROR,
ProtocolErrorType::NotFound => StatusCode::NOT_FOUND,
ProtocolErrorType::HttpMethodNotAllowed => StatusCode::METHOD_NOT_ALLOWED,
}
}
}
impl From<StatusCode> for ProtocolErrorType {
fn from(code: StatusCode) -> Self {
match code {
StatusCode::BAD_REQUEST => ProtocolErrorType::BadRequest,
StatusCode::UNAUTHORIZED => ProtocolErrorType::Unauthorized,
StatusCode::INTERNAL_SERVER_ERROR => ProtocolErrorType::Internal,
StatusCode::NOT_FOUND => ProtocolErrorType::NotFound,
StatusCode::METHOD_NOT_ALLOWED => ProtocolErrorType::HttpMethodNotAllowed,
_ => ProtocolErrorType::Internal,
}
}
}
pub enum ModalHttpResponse {
Single(HttpResponse<Body>),
Event(Value),
}
#[async_trait::async_trait]
pub trait RequestHttpConvert<Request> {
async fn from_http_request(
request: HttpRequest<Body>,
) -> Result<Option<Request>, ProtocolError>;
fn to_http_request(&self, base_url: &Uri) -> Result<Option<HttpRequest<Body>>, ProtocolError>;
}
#[async_trait::async_trait]
pub trait ResponseHttpConvert<Request, Response>
where
Request: Clone,
Response: ResponseHttpConvert<Request, Response>,
{
async fn from_http_response(
response: ModalHttpResponse,
original_request: &Request,
) -> Result<Option<ServiceResponse<Response>>, ProtocolError>;
fn to_http_response(
response: ServiceResponse<Response>,
) -> Result<Option<ModalHttpResponse>, ProtocolError>;
}
#[derive(Debug, Serialize, Deserialize)]
pub struct HttpNotificationPayload {
pub result: Option<Value>,
pub error: Option<SerializableProtocolError>,
}
impl From<Result<Option<Value>, ProtocolError>> for HttpNotificationPayload {
fn from(result: Result<Option<Value>, ProtocolError>) -> Self {
let result =
result.and_then(|r| r.ok_or_else(|| generic_error(ProtocolErrorType::NotFound)));
let (result, error) = match result {
Ok(result) => (Some(result), None),
Err(e) => (None, Some(e.into())),
};
Self { result, error }
}
}
impl Into<Result<Value, ProtocolError>> for HttpNotificationPayload {
fn into(self) -> Result<Value, ProtocolError> {
if let Some(e) = self.error {
return Err(e.into());
}
self.result
.ok_or_else(|| generic_error(ProtocolErrorType::NotFound))
}
}
pub fn generic_error(error_type: ProtocolErrorType) -> ProtocolError {
let status: StatusCode = error_type.clone().into();
let error = Box::new(ProtocolHttpError {
error: status.to_string(),
});
ProtocolError { error_type, error }
}