Skip to content

Add event_type: name SSE events after their topic or a header (#142) - #153

Merged
bpacholek merged 1 commit into
mainfrom
fix-142-event-types
Sep 27, 2026
Merged

bpacholek merged 1 commit into
mainfrom
fix-142-event-types

Conversation

@bpacholek

Copy link
Copy Markdown
Contributor

Summary

Closes #142.

Every message went out as event: message, with its topic inside the JSON data. A page therefore handled everything in one listener and routed it itself.

Changes

  • New directive event_type:
    • message (the default): nothing changes.
    • topic: the event is named after the message's topic, without topic_prefix, so a page can call addEventListener('orders', …).
    • header <name>: the event is named after that header of the NATS message. NATS header names are case-sensitive.
  • Fallback to message. A name must be 1–100 bytes of [A-Za-z0-9._:-]. It must also not be one of the reserved names: connected (the handshake), reset (Send the recreated-stream reset as a reset event (#133 follow-up) #147), open or error. An event named error would reach the page's onerror as if the connection had failed. Otherwise, or when the header is missing, the event is named message. The JSON data never changes.
  • Plumbing.
    • Parsed in caddyfile.go (event_type header <name>, with an error for a missing name or an extra argument).
    • Validated and defaulted in provision.go. The JSON fields are event_type and event_type_header; a header name without header mode, or an invalid header name, is rejected.
    • Documented in the README (listing, event_type section, event format), CONFIGURATION, the website listing and the CHANGELOG.
    • A new /typed route in Caddyfile.test runs event_type topic.

Tests

  • Unit.
    • TestIsUsableEventName and TestIsValidHeaderName tables.
    • TestHandler_EventName, over every mode and fallback, including a header with an embedded \nevent: forged.
  • Fuzz. FuzzFormatMessageEventMatchesReference now also varies the event-type mode and the header value. It is checked against a regex-based reference implementation; 20 s of fuzzing ran clean. There is no committed corpus with the old signature.
  • Integration. TestHandler_EventTypeFromTheTopicOrAHeader, against a real server: a header set on the published NATS message names the event, and one without it falls back to message.
  • Directive. Caddyfile full-config DeepEqual, parse-error rows, validation rows and JSON rows.
  • Functional. The scenario "Events are named after their topic" on /typed; 32/32. The full suite passes under -race, and staticcheck and golangci-lint are clean.
  • Mutation.
    • gremlins: helpers.go 128 killed, 0 lived (12 not covered: the formatter's escaping cases, already checked by hand in the baseline); caddyfile.go 40/0; provision.go 206/0 (16 not covered, the baseline's); serve.go 209/0.
    • 13 hand mutants, all killed. They cover each reserved name, both mode cases, the formatter's use of the name, the Caddyfile header name and extra-argument check, the default, and the three validation checks.
  • Example stack.
    • /typed?topic=numbers&topic=letters gives connected, letters, numbers, letters, ….
    • /events keeps message.

🤖 Generated with Claude Code

Every message went out as `event: message`, with its topic inside the
JSON data, so a page handled all of them in one listener and routed
them itself.

event_type topic names each event after its topic, without topic_prefix.
event_type header <name> uses that header of the NATS message. A name
must be 1 to 100 bytes of [A-Za-z0-9._:-] and must not be one NUTS or
EventSource uses itself (connected, reset, open, error): an event named
error would reach the page's onerror handler. Otherwise, and for a
message without the header, the event keeps the name message. The
default, message, changes nothing.

Closes #142

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Sep 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@bpacholek
bpacholek merged commit d039c9e into main Sep 27, 2026
5 checks passed
@bpacholek
bpacholek deleted the fix-142-event-types branch September 27, 2026 23:58
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.

Optional SSE event types taken from the topic or a message header

1 participant