Skip to content

fix: align HTTP binding with the CloudEvents spec - #676

Open
eisen0419 wants to merge 1 commit into
cloudevents:mainfrom
eisen0419:675-fix-http-binding-interop
Open

eisen0419 wants to merge 1 commit into
cloudevents:mainfrom
eisen0419:675-fix-http-binding-interop

Conversation

@eisen0419

Copy link
Copy Markdown

Fixes #675
Fixes: #675

Proposed Changes

Align HTTP protocol binding media-type matching, falsy JSON data handling, and ce- header percent-encoding/decoding with the CloudEvents HTTP Protocol Binding v1.0.2 specification.

Summary

 HTTP.toEvent / HTTP.binary / HTTP.structured
   getMode(headers)
-    startsWith("application/cloudevents") -> Mode.STRUCTURED
+    contentTypeEssence(ct)                # trim + lowercase + strip "; ..." params
+    startsWith("application/cloudevents-batch") -> Mode.BATCH
+    startsWith("application/cloudevents")       -> Mode.STRUCTURED
   parserForContentType(ct)
+    exact registered key -> essence key -> parameterized match -> */json | */*+json
   parseStructured / JSONParser.parse
-    if (payload[key]) eventObj[key] = ... # dropped 0, false, "", null
+    if (hasOwnProperty && payload[key] !== undefined) eventObj[key] = ...
+    JSON.parse(payload) first; quote only legacy non-JSON bare strings
   headers (ce-*)
+    encode: UTF-8 percent-encode SP, '"', '%', and outside U+0021..U+007E
+    decode: trim OWS -> unwrap single quoted-string -> single UTF-8 percent-decode

Description

  1. Content-Type media-type normalization (§3 / §3.1.1 / §3.2.1): Extract the normalized type/subtype essence (case-insensitive, parameters stripped, OWS trimmed) when selecting structured/batch/binary mode and resolving parsers, while still honoring custom entries registered on parserByContentType. application/cloudevents-batch* is classified before application/cloudevents*, and unregistered type/json or type/*+json media types fall back to JSONParser.
  2. Falsy JSON data and JSON primitives: Preserve 0, false, "", and null in structured mode instead of dropping falsy values, and parse valid JSON primitives in JSONParser.parse before falling back to legacy raw-string quoting.
  3. ce- header percent-encoding (§3.1.3.2): Percent-encode string ce- header values on egress (including non-ASCII UTF-8 such as €, spaces, ", %, and control characters, preventing Node ERR_INVALID_CHAR in httpTransport) and decode incoming ce- headers via OWS trim, optional RFC 7230 quoted-string unescaping, and a single fatal UTF-8 percent-decode pass (ValidationError on malformed UTF-8).

Evidence

  • Before:
    • HTTP.toEvent({ headers: { "content-type": "application/cloudevents+json; charset=UTF-8" }, body }) threw ValidationError: Missing required attributes: id, source, type (fell through to binary mode) or Unsupported content type.
    • Structured events with data: 0, false, "", or null returned event.data === undefined; binary JSON bodies "0", "false", "null" stayed strings.
    • emitterFor(httpTransport(...))(new CloudEvent({ ..., subject: "Euro €" })) threw TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["ce-subject"].
  • After:
    • npm test passes cleanly (remark, eslint, schema build, tsc, webpack browser bundle, all 7 conformance scenarios / 38 steps, and 281 Mocha tests including test/integration/http_binding_interop_test.ts).

Merge Danger

Door: Two-way

Self-contained changes in universal HTTP message/header/parser helpers (src/parsers.ts, src/message/http/index.ts, src/message/http/headers.ts) with no public API signature changes or new dependencies.

Blast Radius: Narrow

Scoped to HTTP binding header serialization/parsing and JSONParser media-type lookup; existing custom parserByContentType overrides, binary Buffer passthrough, non-string boolean/integer extension headers, and Kafka/MQTT bindings remain unchanged.

Normalize Content-Type media types, keep falsy JSON data, and
percent-encode ce- header values per the HTTP protocol binding.

Signed-off-by: eisen0419 <usetoken0419@gmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HTTP binding: Content-Type matched as exact string, falsy data dropped, and ce- headers not percent-encoded

1 participant