linera_base/
http.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! Types used when performing HTTP requests.
5
6use allocative::Allocative;
7use custom_debug_derive::Debug;
8use linera_witty::{WitLoad, WitStore, WitType};
9use serde::{Deserialize, Serialize};
10
11use crate::hex_debug;
12
13/// An HTTP request.
14#[derive(Clone, Debug, Eq, PartialEq, WitLoad, WitStore, WitType)]
15#[witty(name = "http-request")]
16pub struct Request {
17    /// The [`Method`] used for the HTTP request.
18    pub method: Method,
19
20    /// The URL this request is intended to.
21    pub url: String,
22
23    /// The headers that should be included in the request.
24    pub headers: Vec<Header>,
25
26    /// The body of the request.
27    #[debug(with = "hex_debug")]
28    pub body: Vec<u8>,
29}
30
31impl Request {
32    /// Creates an HTTP GET [`Request`] for a `url`.
33    pub fn get(url: impl Into<String>) -> Self {
34        Request {
35            method: Method::Get,
36            url: url.into(),
37            headers: vec![],
38            body: vec![],
39        }
40    }
41
42    /// Creates an HTTP POST [`Request`] for a `url` with a `payload` that's arbitrary bytes.
43    pub fn post(url: impl Into<String>, payload: impl Into<Vec<u8>>) -> Self {
44        Request {
45            method: Method::Post,
46            url: url.into(),
47            headers: vec![],
48            body: payload.into(),
49        }
50    }
51}
52
53/// The method used in an HTTP request.
54#[derive(Clone, Copy, Debug, Eq, PartialEq, WitLoad, WitStore, WitType)]
55#[witty(name = "http-method")]
56pub enum Method {
57    /// A GET request.
58    Get,
59
60    /// A POST request.
61    Post,
62
63    /// A PUT request.
64    Put,
65
66    /// A DELETE request.
67    Delete,
68
69    /// A HEAD request.
70    Head,
71
72    /// A OPTIONS request.
73    Options,
74
75    /// A CONNECT request.
76    Connect,
77
78    /// A PATCH request.
79    Patch,
80
81    /// A TRACE request.
82    Trace,
83}
84
85#[cfg(with_reqwest)]
86impl From<Method> for reqwest::Method {
87    fn from(method: Method) -> Self {
88        match method {
89            Method::Get => reqwest::Method::GET,
90            Method::Post => reqwest::Method::POST,
91            Method::Put => reqwest::Method::PUT,
92            Method::Delete => reqwest::Method::DELETE,
93            Method::Head => reqwest::Method::HEAD,
94            Method::Options => reqwest::Method::OPTIONS,
95            Method::Connect => reqwest::Method::CONNECT,
96            Method::Patch => reqwest::Method::PATCH,
97            Method::Trace => reqwest::Method::TRACE,
98        }
99    }
100}
101
102/// A response for an HTTP request.
103#[derive(
104    Clone,
105    Debug,
106    Deserialize,
107    Eq,
108    Hash,
109    PartialEq,
110    Serialize,
111    WitLoad,
112    WitStore,
113    WitType,
114    Allocative,
115)]
116#[witty(name = "http-response")]
117pub struct Response {
118    /// The status code of the HTTP response.
119    pub status: u16,
120
121    /// The headers included in the response.
122    pub headers: Vec<Header>,
123
124    /// The body of the response.
125    #[debug(with = "hex_debug")]
126    #[serde(with = "serde_bytes")]
127    pub body: Vec<u8>,
128}
129
130impl Response {
131    /// Creates an HTTP [`Response`] with a user defined `status_code`.
132    pub fn new(status_code: u16) -> Self {
133        Response {
134            status: status_code,
135            headers: vec![],
136            body: vec![],
137        }
138    }
139
140    /// Creates an HTTP [`Response`] with an OK status code and the provided `body`.
141    pub fn ok(body: impl Into<Vec<u8>>) -> Self {
142        Response {
143            status: 200,
144            headers: vec![],
145            body: body.into(),
146        }
147    }
148
149    /// Creates an HTTP [`Response`] with an Unauthorized status code.
150    pub fn unauthorized() -> Self {
151        Response {
152            status: 401,
153            headers: vec![],
154            body: vec![],
155        }
156    }
157}
158
159/// A header for an HTTP request or response.
160#[derive(
161    Clone,
162    Debug,
163    Deserialize,
164    Eq,
165    Hash,
166    PartialEq,
167    Serialize,
168    WitLoad,
169    WitStore,
170    WitType,
171    Allocative,
172)]
173#[witty(name = "http-header")]
174pub struct Header {
175    /// The header name.
176    pub name: String,
177
178    /// The value of the header.
179    #[debug(with = "hex_debug")]
180    #[serde(with = "serde_bytes")]
181    pub value: Vec<u8>,
182}
183
184impl Header {
185    /// Creates a new [`Header`] with the provided `name` and `value`.
186    pub fn new(name: impl Into<String>, value: impl Into<Vec<u8>>) -> Self {
187        Header {
188            name: name.into(),
189            value: value.into(),
190        }
191    }
192}