1use crate::error::HttpError;
4use bytes::Bytes;
5use http::{HeaderMap, Method, StatusCode};
6use sova_core::extend::BoxFuture;
7use std::time::Duration;
8
9#[derive(Debug, Clone)]
11pub struct OutRequest {
12 pub method: Method,
13 pub url: String,
14 pub headers: HeaderMap,
15 pub body: Option<Bytes>,
16 pub timeout: Option<Duration>,
17}
18
19#[derive(Debug, Clone)]
21pub struct OutResponse {
22 status: StatusCode,
23 headers: HeaderMap,
24 body: Bytes,
25}
26
27impl OutResponse {
28 pub fn new(status: StatusCode, headers: HeaderMap, body: Bytes) -> Self {
29 Self {
30 status,
31 headers,
32 body,
33 }
34 }
35
36 pub fn status(&self) -> StatusCode {
37 self.status
38 }
39
40 pub fn status_u16(&self) -> u16 {
41 self.status.as_u16()
42 }
43
44 pub fn headers(&self) -> &HeaderMap {
45 &self.headers
46 }
47
48 pub fn bytes(&self) -> &Bytes {
49 &self.body
50 }
51
52 pub fn text(&self) -> Result<String, HttpError> {
53 String::from_utf8(self.body.to_vec()).map_err(|e| HttpError::Other(e.to_string()))
54 }
55
56 pub fn json<T: serde::de::DeserializeOwned>(&self) -> Result<T, HttpError> {
57 serde_json::from_slice(&self.body).map_err(|e| HttpError::Other(e.to_string()))
58 }
59
60 pub fn error_for_status(self) -> Result<Self, HttpError> {
62 let code = self.status.as_u16();
63 if code >= 400 {
64 Err(HttpError::Status(code))
65 } else {
66 Ok(self)
67 }
68 }
69}
70
71pub trait Transport: Send + Sync {
72 fn send(&self, req: OutRequest) -> BoxFuture<Result<OutResponse, HttpError>>;
73}