extism_pdk/
http.rs

1use std::collections::HashMap;
2
3use crate::*;
4
5/// A HttpResponse is used to wrap the memory returned by
6/// `extism_pdk::http::request`
7pub 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
44/// Execute `HttpRequest`, if `body` is not `None` then it will be sent as the
45/// request body.
46pub 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}