redevplugin_worker_sdk/
http.rs1use crate::api;
2use crate::error::{Error, Result};
3use crate::resource::{Handle, IO_FLAG_EOF, MAX_IO_CHUNK_BYTES};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7pub struct Header {
8 pub name: String,
9 pub value: String,
10}
11
12#[derive(Debug, Clone, Copy, Default, Serialize)]
13#[serde(rename_all = "snake_case")]
14pub enum RedirectMode {
15 #[default]
16 Follow,
17 Manual,
18 Error,
19}
20
21#[derive(Debug, Clone, Serialize)]
22pub struct HttpRequest {
23 pub method: String,
24 pub url: String,
25 #[serde(default)]
26 pub headers: Vec<Header>,
27 #[serde(default)]
28 pub redirect: RedirectMode,
29 #[serde(default)]
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub timeout_ms: Option<u32>,
32}
33
34pub type RequestOptions = HttpRequest;
35
36#[derive(Deserialize)]
37struct BeginResult {
38 upload_handle: u64,
39}
40
41#[derive(Deserialize)]
42struct FinishResult {
43 status: u16,
44 #[serde(default)]
45 headers: Vec<Header>,
46 final_url: String,
47 body_handle: u64,
48}
49
50pub struct RequestBody {
51 handle: Handle,
52}
53
54impl RequestBody {
55 pub fn begin(options: HttpRequest) -> Result<Self> {
56 let opened: BeginResult = api::call("net.http.begin", &options)?;
57 Ok(Self {
58 handle: Handle::new(opened.upload_handle)?,
59 })
60 }
61
62 pub fn write_all(&mut self, bytes: &[u8]) -> Result<()> {
63 for chunk in bytes.chunks(MAX_IO_CHUNK_BYTES) {
64 self.handle.write(chunk, 0)?;
65 }
66 Ok(())
67 }
68
69 pub fn finish(mut self) -> Result<Response> {
70 #[derive(Serialize)]
71 struct Arguments {
72 handle: u64,
73 }
74 let finished: FinishResult = api::call(
75 "net.http.finish",
76 &Arguments {
77 handle: self.handle.id(),
78 },
79 )?;
80 self.handle.disarm();
81 Ok(Response {
82 status: finished.status,
83 headers: finished.headers,
84 final_url: finished.final_url,
85 body: ResponseBody {
86 handle: Handle::new(finished.body_handle)?,
87 },
88 })
89 }
90
91 pub fn abort(mut self) -> Result<()> {
92 #[derive(Serialize)]
93 struct Arguments {
94 handle: u64,
95 }
96 let _: serde_json::Value = api::call(
97 "net.http.abort",
98 &Arguments {
99 handle: self.handle.id(),
100 },
101 )?;
102 self.handle.disarm();
103 Ok(())
104 }
105}
106
107pub struct HttpResponse {
108 pub status: u16,
109 pub headers: Vec<Header>,
110 pub final_url: String,
111 pub body: ResponseBody,
112}
113
114pub type Response = HttpResponse;
115
116pub struct ResponseBody {
117 handle: Handle,
118}
119
120impl ResponseBody {
121 pub fn read(&mut self, capacity: usize) -> Result<(Vec<u8>, u32)> {
122 self.handle.read(capacity)
123 }
124
125 pub fn read_all(mut self) -> Result<Vec<u8>> {
126 let mut result = Vec::new();
127 loop {
128 let (chunk, flags) = self.handle.read(MAX_IO_CHUNK_BYTES)?;
129 if chunk.is_empty() && flags & IO_FLAG_EOF == 0 {
130 return Err(Error::internal("HTTP response body made no progress"));
131 }
132 result.extend_from_slice(&chunk);
133 if flags & IO_FLAG_EOF != 0 {
134 self.handle.close()?;
135 return Ok(result);
136 }
137 }
138 }
139
140 pub fn close(mut self) -> Result<()> {
141 self.handle.close()
142 }
143}