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 &String {
41 fn into_url(self) -> Result<Url> {
42 Url::parse(self).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
52impl IntoUrl for &http::Uri {
53 fn into_url(self) -> Result<Url> {
54 Url::parse(&self.to_string()).map_err(Error::from)
55 }
56}
57
58#[derive(Clone, Debug, Default)]
60pub enum Body {
61 #[default]
62 Empty,
63 Bytes(Bytes),
64 Text(String),
65 Json(Vec<u8>),
66 Form(String),
67 Raw(Vec<u8>),
68}
69
70impl Body {
71 pub fn empty() -> Self {
72 Body::Empty
73 }
74
75 pub fn is_empty(&self) -> bool {
76 matches!(self, Body::Empty)
77 }
78
79 pub fn into_bytes(self) -> Result<Bytes> {
80 Ok(match self {
81 Body::Empty => Bytes::new(),
82 Body::Bytes(bytes) => bytes,
83 Body::Text(text) => Bytes::from(text.into_bytes()),
84 Body::Json(bytes) => Bytes::from(bytes),
85 Body::Form(text) => Bytes::from(text.into_bytes()),
86 Body::Raw(bytes) => Bytes::from(bytes),
87 })
88 }
89}
90
91impl From<Bytes> for Body {
92 fn from(value: Bytes) -> Self {
93 Body::Bytes(value)
94 }
95}
96
97impl From<Vec<u8>> for Body {
98 fn from(value: Vec<u8>) -> Self {
99 Body::Raw(value)
100 }
101}
102
103impl From<&[u8]> for Body {
104 fn from(value: &[u8]) -> Self {
105 Body::Raw(value.to_vec())
106 }
107}
108
109impl From<String> for Body {
110 fn from(value: String) -> Self {
111 Body::Text(value)
112 }
113}
114
115impl From<&str> for Body {
116 fn from(value: &str) -> Self {
117 Body::Text(value.to_string())
118 }
119}
120
121#[derive(Clone, Debug)]
123pub struct Request {
124 pub(crate) method: Method,
125 pub(crate) url: Url,
126 pub(crate) headers: Headers,
127 pub(crate) body: Body,
128 pub(crate) version: Option<HttpVersion>,
129 pub(crate) timeout: Option<Duration>,
130}
131
132impl Request {
133 pub fn new(method: Method, url: Url) -> Self {
134 Self {
135 method,
136 url,
137 headers: Headers::new(),
138 body: Body::Empty,
139 version: None,
140 timeout: None,
141 }
142 }
143
144 pub fn method(&self) -> &Method {
145 &self.method
146 }
147
148 pub fn url(&self) -> &Url {
149 &self.url
150 }
151
152 pub fn headers(&self) -> &Headers {
153 &self.headers
154 }
155
156 pub fn body(&self) -> &Body {
157 &self.body
158 }
159
160 pub fn version(&self) -> Option<HttpVersion> {
161 self.version
162 }
163
164 pub fn timeout(&self) -> Option<Duration> {
165 self.timeout
166 }
167}
168
169#[derive(Clone, Debug, Default)]
171pub enum RedirectPolicy {
172 #[default]
173 None,
174 Limited(u32),
175}