GET /yaml
/yamlReturns a well-formed YAML 1.2 document: scalars, mapping, sequence, and a sane anchor + merge-key. No Norway-problem scalars, no cycles, no duplicate keys, no tag lies. Served as application/yaml. Counterpart to /yaml.
expect: 200 OK with Content-Type: application/yaml. Spec-compliant YAML 1.2 that parses identically under YAML 1.1 and 1.2 parsers. Build YAML config loaders against this, then flip hostname to chaos.catastrophic.io to test adversity.
curl -si 'https://not.catastrophic.io/yaml'
# pip install pyyaml ruamel.yaml
import urllib.request, yaml
resp = urllib.request.urlopen("https://not.catastrophic.io/yaml")
print("Content-Type:", resp.headers.get("Content-Type"))
print("X-Chaos-Yaml-Mode:", resp.headers.get("X-Chaos-Yaml-Mode"))
print("X-Chaos-Yaml-Note:", resp.headers.get("X-Chaos-Yaml-Note"))
text = resp.read().decode()
try:
# safe_load uses YAML 1.1 in older PyYAML; the Norway problem surfaces here.
parsed = yaml.safe_load(text)
print("parsed:", parsed)
except yaml.YAMLError as e:
print("parser rejected:", e)
// npm: js-yaml (YAML 1.2)
import yaml from "js-yaml";
const res = await fetch("https://not.catastrophic.io/yaml");
console.log("Content-Type:", res.headers.get("content-type"));
console.log("X-Chaos-Yaml-Mode:", res.headers.get("x-chaos-yaml-mode"));
console.log("X-Chaos-Yaml-Note:", res.headers.get("x-chaos-yaml-note"));
const text = await res.text();
try {
console.log("parsed:", yaml.load(text));
} catch (e) {
console.log("parser rejected:", e.message);
}
package main
// go get gopkg.in/yaml.v2 (YAML 1.1 — sees Norway problem)
// go get gopkg.in/yaml.v3 (YAML 1.2)
import (
"fmt"
"io"
"net/http"
"gopkg.in/yaml.v3"
)
func main() {
resp, _ := http.Get("https://not.catastrophic.io/yaml")
defer resp.Body.Close()
raw, _ := io.ReadAll(resp.Body)
fmt.Println("Content-Type:", resp.Header.Get("Content-Type"))
fmt.Println("X-Chaos-Yaml-Mode:", resp.Header.Get("X-Chaos-Yaml-Mode"))
var out map[string]any
if err := yaml.Unmarshal(raw, &out); err != nil {
fmt.Println("unmarshal rejected:", err)
} else {
fmt.Println("decoded keys:", out)
}
}
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking"] }
// serde_yaml = "0.9" (YAML 1.2)
fn main() -> Result<(), Box> {
let resp = reqwest::blocking::get("https://not.catastrophic.io/yaml")?;
println!("Content-Type: {:?}", resp.headers().get("content-type"));
println!("X-Chaos-Yaml-Mode: {:?}", resp.headers().get("x-chaos-yaml-mode"));
let text = resp.text()?;
match serde_yaml::from_str::(&text) {
Ok(v) => println!("parsed: {:?}", v),
Err(e) => println!("parser rejected: {}", e),
}
Ok(())
}
// SnakeYAML on the classpath (YAML 1.1 by default).
import java.net.URI;
import java.net.http.*;
import org.yaml.snakeyaml.Yaml;
public class YamlChaos {
public static void main(String[] args) throws Exception {
var client = HttpClient.newHttpClient();
var req = HttpRequest.newBuilder(URI.create("https://not.catastrophic.io/yaml")).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-Yaml-Mode: " +
resp.headers().firstValue("X-Chaos-Yaml-Mode").orElse(""));
try {
Object parsed = new Yaml().load(resp.body());
System.out.println("parsed: " + parsed);
} catch (Exception e) {
System.out.println("parser rejected: " + e.getMessage());
}
}
}
// NuGet: YamlDotNet (YAML 1.2)
using YamlDotNet.Serialization;
using var client = new HttpClient();
var resp = await client.GetAsync("https://not.catastrophic.io/yaml");
Console.WriteLine($"Content-Type: {resp.Content.Headers.ContentType}");
Console.WriteLine($"X-Chaos-Yaml-Mode: " +
$"{resp.Headers.GetValues("X-Chaos-Yaml-Mode").FirstOrDefault()}");
var text = await resp.Content.ReadAsStringAsync();
try {
var parsed = new Deserializer().Deserialize# YAML.safe_load uses Psych (YAML 1.1)
require "net/http"
require "yaml"
uri = URI("https://not.catastrophic.io/yaml")
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
res = http.get(uri.request_uri)
puts "Content-Type: #{res['Content-Type']}"
puts "X-Chaos-Yaml-Mode: #{res['X-Chaos-Yaml-Mode']}"
puts "X-Chaos-Yaml-Note: #{res['X-Chaos-Yaml-Note']}"
begin
parsed = YAML.unsafe_load(res.body)
puts "parsed: #{parsed.inspect}"
rescue => e
puts "parser rejected: #{e.message}"
end
end
# PowerShell-Yaml (Install-Module powershell-yaml)
$r = Invoke-WebRequest -Uri 'https://not.catastrophic.io/yaml'
"Content-Type: $($r.Headers['Content-Type'])"
"X-Chaos-Yaml-Mode: $($r.Headers['X-Chaos-Yaml-Mode'])"
"X-Chaos-Yaml-Note: $($r.Headers['X-Chaos-Yaml-Note'])"
try {
$parsed = ConvertFrom-Yaml $r.Content
"parsed keys: $($parsed.Keys -join ', ')"
} catch {
"parser rejected: $_"
}
headers
body