GET /sse
Returns a Server-Sent Events stream with WHATWG EventSource spec violations. Default sends payload lines with no `data:` prefix. Use ?mode= to isolate other violations: named events with no listeners, discontinuous id ordering, or mixed CRLF/LF line endings.
mode
missing-data-prefix (default; payload lines have no `data:` prefix; conforming EventSource clients ignore unrecognized field names and deliver empty event.data to handlers), event-without-listener (all events use named `event:` fields; EventSource.onmessage never fires; consumers need addEventListener for each event type), id-discontinuity (event ids go backwards `5, 3, 5, 1`; Last-Event-ID reconnect logic receives an unpredictable cursor and some clients reject out-of-order ids), crlf-mix (line endings alternate CRLF and LF within the same stream; parsers that normalize only one style misparse field boundaries).
control Compare against the well-formed counterpart: not.catastrophic.io/sse side-by-side
build a request:
expect: A text/event-stream response with one spec violation. EventSource clients react in mode-specific ways — usually silent: empty event data, missed events, broken reconnect cursor, or misparsed framing.
curl -sN 'https://chaos.catastrophic.io/sse?mode=missing-data-prefix' | head -40
import urllib.request
resp = urllib.request.urlopen("https://chaos.catastrophic.io/sse?mode=missing-data-prefix")
print("Content-Type:", resp.headers.get("Content-Type"))
print("X-Chaos-Sse-Mode:", resp.headers.get("X-Chaos-Sse-Mode"))
print("--- raw stream ---")
for line in resp:
print(repr(line))
// Node 18+ has a built-in EventSource via undici, browsers have window.EventSource.
const es = new EventSource("https://chaos.catastrophic.io/sse?mode=missing-data-prefix");
es.onmessage = (e) => console.log("default message:", e.data);
es.addEventListener("connected", (e) => console.log("connected:", e.data));
es.addEventListener("message", (e) => console.log("message:", e.data));
es.addEventListener("done", (e) => { console.log("done:", e.data); es.close(); });
es.onerror = (e) => console.log("error:", e);
package main
import (
"bufio"
"fmt"
"net/http"
)
func main() {
resp, _ := http.Get("https://chaos.catastrophic.io/sse?mode=missing-data-prefix")
defer resp.Body.Close()
fmt.Println("Content-Type:", resp.Header.Get("Content-Type"))
fmt.Println("X-Chaos-Sse-Mode:", resp.Header.Get("X-Chaos-Sse-Mode"))
scanner := bufio.NewScanner(resp.Body)
for scanner.Scan() {
fmt.Printf("%q\n", scanner.Text())
}
}
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking"] }
use std::io::{BufRead, BufReader};
fn main() -> Result<(), Box> {
let resp = reqwest::blocking::get("https://chaos.catastrophic.io/sse?mode=missing-data-prefix")?;
println!("Content-Type: {:?}", resp.headers().get("content-type"));
println!("X-Chaos-Sse-Mode: {:?}", resp.headers().get("x-chaos-sse-mode"));
for line in BufReader::new(resp).lines() {
println!("{:?}", line?);
}
Ok(())
}
import java.net.URI;
import java.net.http.*;
public class SseChaos {
public static void main(String[] args) throws Exception {
var client = HttpClient.newHttpClient();
var req = HttpRequest.newBuilder(URI.create("https://chaos.catastrophic.io/sse?mode=missing-data-prefix")).build();
var resp = client.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println("Content-Type: " +
resp.headers().firstValue("Content-Type").orElse(""));
System.out.println("X-Chaos-Sse-Mode: " +
resp.headers().firstValue("X-Chaos-Sse-Mode").orElse(""));
System.out.println("Body: " + resp.body());
}
}
using var client = new HttpClient();
var resp = await client.GetAsync("https://chaos.catastrophic.io/sse?mode=missing-data-prefix");
Console.WriteLine($"Content-Type: {resp.Content.Headers.ContentType}");
Console.WriteLine($"X-Chaos-Sse-Mode: " +
$"{resp.Headers.GetValues("X-Chaos-Sse-Mode").FirstOrDefault()}");
var body = await resp.Content.ReadAsStringAsync();
Console.WriteLine($"Body: {body}");
require "net/http"
uri = URI("https://chaos.catastrophic.io/sse?mode=missing-data-prefix")
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
req = Net::HTTP::Get.new(uri.request_uri)
http.request(req) do |res|
puts "Content-Type: #{res['Content-Type']}"
puts "X-Chaos-Sse-Mode: #{res['X-Chaos-Sse-Mode']}"
res.read_body { |chunk| chunk.each_line { |line| puts line.inspect } }
end
end
$r = Invoke-WebRequest -Uri 'https://chaos.catastrophic.io/sse?mode=missing-data-prefix'
"Content-Type: $($r.Headers['Content-Type'])"
"X-Chaos-Sse-Mode: $($r.Headers['X-Chaos-Sse-Mode'])"
$r.Content -split "`n" | ForEach-Object { '{0}' -f $_ }
headers
body