1use std::collections::HashMap;
2
3use crate::*;
4
5pub struct HttpResponse {
8 memory: Memory,
9 status: u16,
10 headers: HashMap<String, String>,
11}
12
13impl HttpResponse {
14 pub fn into_memory(self) -> Memory {
15 self.memory
16 }
17
18 pub fn status_code(&self) -> u16 {
19 self.status
20 }
21
22 pub fn as_memory(&self) -> &Memory {
23 &self.memory
24 }
25
26 pub fn body(&self) -> Vec<u8> {
27 self.memory.to_vec()
28 }
29
30 pub fn json<T: serde::de::DeserializeOwned>(&self) -> Result<T, Error> {
31 let x = serde_json::from_slice(&self.body())?;
32 Ok(x)
33 }
34
35 pub fn headers(&self) -> &HashMap<String, String> {
36 &self.headers
37 }
38
39 pub fn header(&self, s: impl AsRef<str>) -> Option<&str> {
40 self.headers.get(s.as_ref()).map(|x| x.as_ref())
41 }
42}
43
44pub fn request<T: ToMemory>(
47 req: &extism_manifest::HttpRequest,
48 body: Option<T>,
49) -> Result<HttpResponse, Error> {
50 let enc = serde_json::to_vec(req)?;
51 let req = Memory::from_bytes(enc)?;
52 let body = match body {
53 Some(b) => Some(b.to_memory()?),
54 None => None,
55 };
56 let data = body.as_ref().map(|x| x.offset()).unwrap_or(0);
57 let offs = unsafe { extism::http_request(req.offset(), data) };
58 let status = unsafe { extism::http_status_code() };
59 let len = unsafe { extism::length_unsafe(offs) };
60
61 let headers = unsafe { extism::http_headers() };
62 let headers = if headers == 0 {
63 HashMap::new()
64 } else {
65 if let Some(h) = Memory::find(headers) {
66 let Json(j) = h.to()?;
67 h.free();
68 j
69 } else {
70 HashMap::new()
71 }
72 };
73
74 Ok(HttpResponse {
75 memory: Memory(MemoryHandle {
76 offset: offs,
77 length: len,
78 }),
79 status: status as u16,
80 headers,
81 })
82}