DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
cloudevents.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file cloudevents.cpp
6 * @brief CloudEvents v1.0 structured-JSON build + binary-header read.
7 */
8
10
11#if DETWS_ENABLE_CLOUDEVENTS
12
14#include <string.h>
15
16static bool ce_present(const char *s)
17{
18 return s != nullptr && s[0] != '\0';
19}
20
21// CloudEvents 1.0 JSON attribute names emitted in more than one branch below; named once so the
22// (typo-prone) spec keys stay identical across the has-data / no-data paths. (Flash-resident.)
23static const char *const CE_KEY_DATACONTENTTYPE = "datacontenttype";
24static const char *const CE_KEY_DATA = "data";
25
26size_t cloudevents_build_json(char *buf, size_t cap, const CloudEvent *ce)
27{
28 if (!buf || cap == 0 || !ce)
29 return 0;
30 // The three context attributes id/source/type are REQUIRED (CloudEvents 1.0).
31 if (!ce_present(ce->id) || !ce_present(ce->source) || !ce_present(ce->type))
32 return 0;
33
34 JsonWriter w(buf, cap);
35 w.begin_object();
36 w.kv_str("specversion", "1.0");
37 w.kv_str("id", ce->id);
38 w.kv_str("source", ce->source);
39 w.kv_str("type", ce->type);
40 if (ce_present(ce->subject))
41 w.kv_str("subject", ce->subject);
42
43 // data: a pre-formatted JSON value (verbatim) or a plain string (escaped).
44 if (ce->data_json && ce->data_json[0] != '\0')
45 {
46 w.kv_str(CE_KEY_DATACONTENTTYPE, ce_present(ce->datacontenttype) ? ce->datacontenttype : "application/json");
47 w.key(CE_KEY_DATA);
48 w.raw(ce->data_json);
49 }
50 else if (ce->data_str)
51 {
52 if (ce_present(ce->datacontenttype))
53 w.kv_str(CE_KEY_DATACONTENTTYPE, ce->datacontenttype);
54 w.kv_str(CE_KEY_DATA, ce->data_str);
55 }
56 else if (ce_present(ce->datacontenttype))
57 {
58 w.kv_str(CE_KEY_DATACONTENTTYPE, ce->datacontenttype);
59 }
60
61 w.end_object();
62 return w.ok() ? strnlen(buf, cap) : 0;
63}
64
65bool cloudevents_from_headers(const HttpReq *req, CloudEvent *out)
66{
67 if (!req || !out)
68 return false;
69 memset(out, 0, sizeof(*out));
70 out->id = http_get_header(req, "ce-id");
71 out->source = http_get_header(req, "ce-source");
72 out->type = http_get_header(req, "ce-type");
73 out->subject = http_get_header(req, "ce-subject");
74 out->datacontenttype = http_get_header(req, "Content-Type");
75 return ce_present(out->id) && ce_present(out->source) && ce_present(out->type);
76}
77
78#endif // DETWS_ENABLE_CLOUDEVENTS
Builds a JSON document into a fixed caller buffer, no heap.
Definition json.h:59
CloudEvents v1.0 (CNCF) event envelope - structured JSON build + binary (ce-* header) read....
const char * http_get_header(const HttpReq *req, const char *key)
Look up a header value by name (case-insensitive).
Layer 6 (Presentation) - zero-heap JSON: a bounded writer and top-level reader.
Fully-parsed HTTP/1.1 request.