Caddy version:
v2.4.1
The problem I’m having:
I would like to create a respond with a multi line body. According to the documentation this is possible: respond (Caddyfile directive) — Caddy Documentation
body is an alternate way to provide a body; convenient if it is multiple lines.
Sadly it is not documented how I have to enter the multi line body.
What I already tried:
I have already try this:
respond /robots.txt {
body "User-agent: *
Disallow: /"
}
But how I expected this is not a valid Caddyfile:
run: adapting config using caddyfile: parsing caddyfile tokens for 'respond': /etc/caddy/Caddyfile:3 - Error during parsing: Wrong argument count or unexpected line ending after 'respond'
How can I enter the newline?
The one line version does work:
respond /robots.txt "User-agent: * Disallow: /"
Mohammed90
(Mohammed Al Sahaf)
June 9, 2021, 7:54pm
2
You can use backticks ` for multi-line strings. It’s explained in the Tokens and Quotes section:
matt
(Matt Holt)
June 9, 2021, 8:45pm
3
Double quotes should work too. I don’t think the multi-line body is the problem. There might be a discrepancy between the docs and the parsing logic. (Not sure if bug in docs or parser, though.)
Actually, the problem is you missed the required status code argument:
:80
respond /robots.txt 200 {
body "User-agent: *
Disallow: /"
}
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":80"
],
"routes": [
{
"match": [
{
"path": [
"/robots.txt"
]
}
],
"handle": [
{
"body": "User-agent: * \n Disallow: /",
"handler": "static_response",
"status_code": 200
}
]
}
]
}
}
}
}
}
Unfortunately, there’s no way to avoid the leading spaces on the subsequent lines without aligning it to the left gutter, like this:
:80
respond /robots.txt 200 {
body "User-agent: *
Disallow: /"
}
I proposed a solution by implementing heredoc support in the Caddyfile, but it was rejected for having a weird implementation
caddyserver:master
← francislavoie:caddyfile-heredoc
opened 07:21AM - 16 Oct 20 UTC
Adds support for heredoc syntax to the Caddyfile, inspired by HCL (HashiCorp Con… fig Language), and PHP 7.3's flexible syntax (trimming the front of every line based on the indentation of the ending marker: https://wiki.php.net/rfc/flexible_heredoc_nowdoc_syntaxes)
Here's an example:
```
example.com {
respond <<EOF
<html>
<head><title>Foo</title>
<body>Foo</body>
</html>
EOF 200
}
```
Adapted JSON:
```json
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":443"
],
"routes": [
{
"match": [
{
"host": [
"example.com"
]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"body": "\u003chtml\u003e\n \u003chead\u003e\u003ctitle\u003eFoo\u003c/title\u003e\n \u003cbody\u003eFoo\u003c/body\u003e\n\u003c/html\u003e\n",
"handler": "static_response",
"status_code": 200
}
]
}
]
}
],
"terminal": true
}
]
}
}
}
}
}
```
Notice that the response body has the leading whitespace on each line stripped away.
---
The implementation was a bit funky here, I don't like that I added a new field on the Token struct, but I couldn't think of a better way to handle it, frankly.
Basically, heredocs don't include the newline that counts as the starting point as part of the token contents. This is ideal, because then you don't have an extra newline at the start of every token, so it reads more like a file.
The problem is this: the logic for splitting the tokens into segments involves counting the amount of newlines inside of the token text, and checking whether it matches the line numbers on the tokens. Since we drop one newline from the heredoc, this doesn't match that expectation.
So basically my "hack" was to just add a "+1" marker on the token, with a field called "Heredoc" for the purposes of counting line breaks, while keeping the line numbers intact (because they're useful for debugging etc). Can you think of a better way?
I also went ahead and commented the shit out of the lexer, because I think it deserves it, since it's getting pretty involved. The heredoc stuff is admittedly quite chunky, and probably non-optimally written cause I'm by no means a Go expert... but I think the logic is sound.
I should add some more tests for this to `lexer_test.go` but I'm too tired right now :smile: I'll come back to it soon.
2 Likes
matt
(Matt Holt)
June 9, 2021, 8:48pm
5
Ah yep, that’s what I was wondering. I have to admit I had to read the docs twice but I think both the docs and the parser are in harmony.
Thanks for the help. I did misunderstand the documentation and had though that the status code is optimal.
simple "
with status codes does work:
respond /robots.txt 200 {
body "User-agent: *
Disallow: /"
}
But the same with additional ` does not work.
respond /robots.txt 200 {
body `"User-agent: *
Disallow: /"`
If I use this, the "
are included in the responds:
"User-agent: *
Disallow: /"
1 Like
Backticks are a replacement for double quotes, mainly for when you actually do want double quotes in the output. Most typical example is when you need to emit JSON. For example:
respond `{"foo": "bar"}`
instead of:
respond "{\"foo\": \"bar\"}"
Both work, but clearly the first is better because it avoids the mess of escaping.
1 Like
system
(system)
Closed
July 9, 2021, 5:15pm
8
This topic was automatically closed after 30 days. New replies are no longer allowed.