Escaping json strings in json config

1. Caddy version (caddy version):

v2.2.1 h1:Q62GWHMtztnvyRU+KPOpw6fNfeCD3SkwH7SfT1Tgt2c=

2. How I run Caddy:

Systemd unit provided with centos 8 copr, with the following override:

# /etc/systemd/system/caddy.service.d/override.conf
[Service]
ExecStart=
ExecReload=

ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/caddy.json
ExecReload=/usr/bin/caddy reload --config /etc/caddy/caddy.json

a. System environment:

NAME=“CentOS Linux”
VERSION=“8 (Core)”

b. Command:

systemctl start caddy

3. The problem I’m having:

How to put http headers into a json config file if escaping { is not possible?

4. Error messages and/or full log output:

validate: decoding config: invalid character '{' in string escape code

5. What I already tried:

"report-to": [ "\{test}" ]

6. Links to relevant resources:

Any character may be escaped.

I tried reporting this here: Unable to set header containing JSON in Caddy v2 b15 · Issue #3116 · caddyserver/caddy · GitHub but was directed to this forum.

Does your JSON pass validation in the first place?

It works fine until I attempt to escape {, or any escape sequence not listed here: go/scanner.go at master · golang/go · GitHub

Escaping { does not work on your linked validator, but it does work on https://jsonformatter.curiousconcept.com/.
It even works in chrome console, try this example there: {"a": "b\{c"}.

So why is go (and your link) now allowing it?

edit: i got it to work with help from irc user fizzie on freenode #go-nuts by doing this: "report-to": [ "\\\u007btest}" ]

edit2: in the end this is what my report-to header looks like in the json config:

"report-to": [ "\\\u007b \u0022group\u0022: \u0022csp\u0022, \u0022includeSubdomains\u0022: true, \u0022max_age\u0022: 86400, \u0022endpoints\u0022: [ \\\u007b \u0022url\u0022: \u0022https://example.com/csp\u0022, \u0022priority\u0022: 100, \u0022weight\u0022: 100 \\\u007d ] \\\u007d" ]

I realize i over-escaped a bit, but my syntax highlighter was giving me sass, so I just escaped everything.

I am not sure. JSON.parse() in the browser console throws an error (and thus jsonlint.com does too), but pasting that JSON into the console directly does not. The Go standard library also throws an error (hence your topic), from this function in the scanner:

I do not have an explanation though. (See below.) If you want, you could open an issue with the Go project and ask.

Edit: git blame shows that code was written 5-11 years ago, long before that RFC existed.

Edit 2: The encoding/json package is documented as an implementation of RFC 7159, not 8259. Further, the grammar is confusing, as it seems to contradict “Any character may be escaped.” The grammar seems to indicate that the reverse solidus must be followed by one of the characters in a set:

      char = unescaped /
          escape (
              %x22 /          ; "    quotation mark  U+0022
              %x5C /          ; \    reverse solidus U+005C
              %x2F /          ; /    solidus         U+002F
              %x62 /          ; b    backspace       U+0008
              %x66 /          ; f    form feed       U+000C
              %x6E /          ; n    line feed       U+000A
              %x72 /          ; r    carriage return U+000D
              %x74 /          ; t    tab             U+0009
              %x75 4HEXDIG )  ; uXXXX                U+XXXX

So I have to agree with the JSON.parse and Go implementations and the spec grammar. I think your JSON above is incorrect. I can’t explain why, but it is, apparently.

A user on Twitter has explained it thusly: https://twitter.com/SaturniusMons/status/1332112370722689026

FTR fizzie also pointed out that "the RFC goes on how to escape any character in the BMP (via an “\uXXXX” escape sequence), and mentions that “some popular characters” also have two-character escape sequences. “{” is not on the list, and the syntax for the char token makes it clear that there’s only a handful of characters can follow a backslash.

This topic was automatically closed after 30 days. New replies are no longer allowed.