1use crate::error::{Error, Result};
4use crate::headers::Headers;
5use crate::version::HttpVersion;
6use bytes::Bytes;
7use http::Method;
8use std::time::Duration;
9use url::Url;
10
11pub trait IntoUrl {
13 fn into_url(self) -> Result<Url>;
14}
15
16impl IntoUrl for Url {
17 fn into_url(self) -> Result<Url> {
18 Ok(self)
19 }
20}
21
22impl IntoUrl for &Url {
23 fn into_url(self) -> Result<Url> {
24 Ok(self.clone())
25 }
26}
27
28impl IntoUrl for &str {
29 fn into_url(self) -> Result<Url> {
30 Url::parse(self).map_err(Error::from)
31 }
32}
33
34impl IntoUrl for String {
35 fn into_url(self) -> Result<Url> {
36 Url::parse(&self).map_err(Error::from)
37 }
38}
39
40impl IntoUrl for http::Uri {
41 fn into_url(self) -> Result<Url> {
42 Url::parse(&self.to_string()).map_err(Error::from)
43 }
44}
45
46impl IntoUrl for &http::Uri {
47 fn into_url(self) -> Result<Url> {
48 Url::parse(&self.to_string()).map_err(Error::from)
49 }
50}
51
52#[derive(Clone, Debug, Default)]
54pub enum Body {
55 #[default]
56 Empty,
57 Bytes(Bytes),
58 Text(String),
59 Json(Vec<u8>),
60 Form(String),
61 Raw(Vec<u8>),
62}
63
64impl Body {
65 pub fn empty() -> Self {
66 Body::Empty
67 }
68
69 pub fn is_empty(&self) -> bool {
70 matches!(self, Body::Empty)
71 }
72
73 pub fn into_bytes(self) -> Result<Bytes> {
74 Ok(match self {
75 Body::Empty => Bytes::new(),
76 Body::Bytes(bytes) => bytes,
77 Body::Text(text) => Bytes::from(text.into_bytes()),
78 Body::Json(bytes) => Bytes::from(bytes),
79 Body::Form(text) => Bytes::from(text.into_bytes()),
80 Body::Raw(bytes) => Bytes::from(bytes),
81 })
82 }
83}
84
85impl From<Bytes> for Body {
86 fn from(value: Bytes) -> Self {
87 Body::Bytes(value)
88 }
89}
90
91impl From<Vec<u8>> for Body {
92 fn from(value: Vec<u8>) -> Self {
93 Body::Raw(value)
94 }
95}
96
97impl From<&[u8]> for Body {
98 fn from(value: &[u8]) -> Self {
99 Body::Raw(value.to_vec())
100 }
101}
102
103impl From<String> for Body {
104 fn from(value: String) -> Self {
105 Body::Text(value)
106 }
107}
108
109impl From<&str> for Body {
110 fn from(value: &str) -> Self {
111 Body::Text(value.to_string())
112 }
113}
114
115#[derive(Clone, Debug)]
117pub struct Request {
118 pub(crate) method: Method,
119 pub(crate) url: Url,
120 pub(crate) headers: Headers,
121 pub(crate) body: Body,
122 pub(crate) version: Option<HttpVersion>,
123 pub(crate) timeout: Option<Duration>,
124}
125
126impl Request {
127 pub fn new(method: Method, url: Url) -> Self {
128 Self {
129 method,
130 url,
131 headers: Headers::new(),
132 body: Body::Empty,
133 version: None,
134 timeout: None,
135 }
136 }
137
138 pub fn method(&self) -> &Method {
139 &self.method
140 }
141
142 pub fn url(&self) -> &Url {
143 &self.url
144 }
145
146 pub fn headers(&self) -> &Headers {
147 &self.headers
148 }
149
150 pub fn body(&self) -> &Body {
151 &self.body
152 }
153
154 pub fn version(&self) -> Option<HttpVersion> {
155 self.version
156 }
157
158 pub fn timeout(&self) -> Option<Duration> {
159 self.timeout
160 }
161}
162
163#[derive(Clone, Debug, Default)]
165pub enum RedirectPolicy {
166 #[default]
167 None,
168 Limited(u32),
169}