1//! An HTTP client.
2
3pub use crate::wit::zed::extension::http_client::{
4 HttpMethod, HttpRequest, HttpResponse, HttpResponseStream, HttpResponseWithStatus,
5 RedirectPolicy, fetch, fetch_fallible, fetch_stream,
6};
7
8impl HttpRequest {
9 /// Returns a builder for an [`HttpRequest`].
10 pub fn builder() -> HttpRequestBuilder {
11 HttpRequestBuilder::new()
12 }
13
14 /// Executes the [`HttpRequest`] with [`fetch`].
15 pub fn fetch(&self) -> Result<HttpResponse, String> {
16 fetch(self)
17 }
18
19 /// Like [`fetch`], except it doesn't treat any status codes as errors.
20 pub fn fetch_fallible(&self) -> Result<HttpResponseWithStatus, String> {
21 fetch_fallible(self)
22 }
23
24 /// Executes the [`HttpRequest`] with [`fetch_stream`].
25 pub fn fetch_stream(&self) -> Result<HttpResponseStream, String> {
26 fetch_stream(self)
27 }
28}
29
30/// A builder for an [`HttpRequest`].
31#[derive(Clone)]
32pub struct HttpRequestBuilder {
33 method: Option<HttpMethod>,
34 url: Option<String>,
35 headers: Vec<(String, String)>,
36 body: Option<Vec<u8>>,
37 redirect_policy: RedirectPolicy,
38}
39
40impl Default for HttpRequestBuilder {
41 fn default() -> Self {
42 Self::new()
43 }
44}
45
46impl HttpRequestBuilder {
47 /// Returns a new [`HttpRequestBuilder`].
48 pub fn new() -> Self {
49 HttpRequestBuilder {
50 method: None,
51 url: None,
52 headers: Vec::new(),
53 body: None,
54 redirect_policy: RedirectPolicy::NoFollow,
55 }
56 }
57
58 /// Sets the HTTP method for the request.
59 pub fn method(mut self, method: HttpMethod) -> Self {
60 self.method = Some(method);
61 self
62 }
63
64 /// Sets the URL for the request.
65 pub fn url(mut self, url: impl Into<String>) -> Self {
66 self.url = Some(url.into());
67 self
68 }
69
70 /// Adds a header to the request.
71 pub fn header(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
72 self.headers.push((name.into(), value.into()));
73 self
74 }
75
76 /// Adds the specified headers to the request.
77 pub fn headers(mut self, headers: impl IntoIterator<Item = (String, String)>) -> Self {
78 self.headers.extend(headers);
79 self
80 }
81
82 /// Sets the body of the request.
83 pub fn body(mut self, body: impl Into<Vec<u8>>) -> Self {
84 self.body = Some(body.into());
85 self
86 }
87
88 /// Sets the redirect policy for the request.
89 pub fn redirect_policy(mut self, policy: RedirectPolicy) -> Self {
90 self.redirect_policy = policy;
91 self
92 }
93
94 /// Builds the [`HttpRequest`].
95 pub fn build(self) -> Result<HttpRequest, String> {
96 let method = self.method.ok_or_else(|| "Method not set".to_string())?;
97 let url = self.url.ok_or_else(|| "URL not set".to_string())?;
98
99 Ok(HttpRequest {
100 method,
101 url,
102 headers: self.headers,
103 body: self.body,
104 redirect_policy: self.redirect_policy,
105 })
106 }
107}