http.rsannotatedhttp.rssource94 lines · 2.7 KB · raw

The service's request and response as plain values: no HTTP library's types, so the same layer serves a native server, a Worker's fetch handler and a test.

4use ::log::error;
5use serde::Serialize;
6use whiskers_ports::Diagnostic;

The largest request body served. A picture arrives as base64 inside the body: a few at 1024 pixels is a few hundred kilobytes. The adapter reads at most MAX_BODY + 1 bytes; a body that long is refused.

11pub const MAX_BODY: usize = 8 * 1024 * 1024;
13#[derive(Clone, Debug, PartialEq, Eq)]
14pub enum Method {
15    Post,

Any other method, by name (only ever answered with 405).

17    Other(String),
18}

What the adapter managed to read of the request body.

21#[derive(Clone, Debug, PartialEq, Eq)]
22pub enum Body {
23    Text(String),

The body could not be read (a device that dropped off wifi halfway, or not text).

25    Unreadable(Diagnostic),
26}
28#[derive(Clone, Debug, PartialEq, Eq)]
29pub struct Request {
30    pub method: Method,
31    pub path: String,
32    pub body: Body,
33}
34
35impl Request {
36    pub fn post(path: &str, body: impl Into<String>) -> Self {
37        Self { method: Method::Post, path: path.to_owned(), body: Body::Text(body.into()) }
38    }
39}

What a response carries, which the adapter turns into its server's header.

42#[derive(Clone, Copy, Debug, PartialEq, Eq)]
43pub enum Content {

No body and no content type.

45    None,

application/json.

47    Json,

Plain text, UTF-8 (text/plain; charset=UTF-8).

49    Text,

audio/mpeg.

51    Mpeg,
52}
54#[derive(Clone, Debug, PartialEq, Eq)]
55pub struct Response {
56    pub status: u16,
57    pub content: Content,
58    pub body: Vec<u8>,
59}
60
61impl Response {
62    pub fn empty(status: u16) -> Self {
63        Self { status, content: Content::None, body: Vec::new() }
64    }
65
66    pub fn json(status: u16, body: String) -> Self {
67        Self { status, content: Content::Json, body: body.into_bytes() }
68    }
69
70    pub fn text(status: u16, body: String) -> Self {
71        Self { status, content: Content::Text, body: body.into_bytes() }
72    }
73
74    pub fn bytes(status: u16, content: Content, body: Vec<u8>) -> Self {
75        Self { status, content, body }
76    }

value as a 200 JSON reply. (A reply type of ours that cannot be serialised is a bug, answered as a 500 and logged, never a panic in a request.)

80    pub fn of<T: Serialize>(value: &T) -> Self {
81        match serde_json::to_string(value) {
82            Ok(json) => Self::json(200, json),
83            Err(e) => {
84                error!("a reply does not serialise: {e}");
85                Self::empty(500)
86            }
87        }
88    }

The body as text, for tests and logs that know it is.

91    pub fn text_body(&self) -> String {
92        String::from_utf8_lossy(&self.body).into_owned()
93    }
94}