1

I'm trying to use a heredoc to pass in the ONE param I need to make a POST request via curl, this is the error I run into

./scripts/etcd.sh: line 10: warning: here-document at line 10 delimited by end-of-file (wanted `EOF{peerURLs:[http://etcd-$ordinal:2380]}EOF')
./scripts/etcd.sh: line 9: warning: here-document at line 9 delimited by end-of-file (wanted `EOF{peerURLs:[http://etcd-$ordinal:2380]}EOF')
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    42  100    42    0     0  12639      0 --:--:-- --:--:-- --:--:-- 21000
{"message":"unexpected end of JSON input"}

And the 2 lines in the script that trigger it

request_body=$(cat <<EOF{\"peerURLs\":[\"http://etcd-$ordinal:2380\"]}EOF); 
curl http://etcd-0.etcd:2379/v2/members -XPOST -H \"Content-Type: application/json\" --data \"$request_body\";

I've tried all the answers here Using curl POST with variables defined in bash script functions before asking my own question.

Edit:

From the answers and comments below I've tried

curl http://etcd-0.etcd:2379/v2/members -XPOST -H \"Content-Type: application/json\" --data @<(cat <<EOF\n{\"peerURLs\":[\"http://etcd-$ordinal:2380\"]}\nEOF)

And it works, but with giving a similar error

./scripts/etcd.sh: line 12: warning: here-document at line 10 delimited by end-of-file (wanted `EOF')
./scripts/etcd.sh: line 12: warning: here-document at line 10 delimited by end-of-file (wanted `EOF')
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
{"id":"a473da4d8f77b2b0","name":"","peerURLs":["http://etcd-3.etcd:2380"],"clientURLs":[]}
3
  • 2
    Here-docs don't work like this. The contents of it must start on a new line, and the end marker has to be on a line on its own. Your script thinks that the whole thing (EOF{\"peerURLs\":[\"http://etcd-$ordinal:2380\"]}EOF);) is your marker. Commented Mar 24, 2017 at 2:28
  • 1
    You don't want to escape the quotes, either. curl -H "Content-Type..." --data "$request_body". Commented Mar 24, 2017 at 4:09
  • 1
    Consider using a tool like jq to generate your JSON, especially when you are embedding the contents of a parameter. Commented Mar 24, 2017 at 12:16

1 Answer 1

4

Try:

request_body="{\"peerURLs\":[\"http://etcd-$ordinal:2380\"]}"

Here-docs (<<EOF\n ... \nEOF):

  • are inherently multi-line constructs (because yours isn't, you're getting the warning)

  • send their contents to stdin.

Neither aspect is required in your case, where a single-line, expandable string ("...") is sufficient.

Additionally, the way you use quoting in your curl command is broken - see bottom.


If you did want to use a here-doc with a variable, this is the most efficient idiom:

read -d '' -r request_body <<EOF
{"peerURLs":["http://etcd-$ordinal:2380"]}
EOF

Note: The closing delimiter, EOF here, must be on its own line, at the very start of the line (no leading whitespace allowed), and no other characters may follow, not even whitespace and comments.

read is used to read the here-doc's contents, via stdin (-d '' ensures that the entire here-doc is read as a whole, and -r is used to ensure that the content is read without interpretation of embedded \ chars.)

As you can see, the advantage here is that there's no need to escape embedded " chars. as \".


chepner points out that often you can use here-docs directly, without the need for an auxiliary variable; in this case, @- as the --data argument tells curl to read from stdin:

curl http://etcd-0.etcd:2379/v2/members -XPOST -H 'Content-Type: application/json' \
  --data @- <<EOF
{"peerURLs":["http://etcd-$ordinal:2380"]}
EOF

The above command also shows how to quote the -H option-argument correctly: using unescaped single-quoting to produce a string literal. By contrast, \"Content-Type: application/json\" would create 2 arguments, "Content-Type:and application/json" - with \" turning into embedded " chars.

Similarly, to use your $request_body variable instead of a here-doc, use "$request_body" rather than \"$request_body\".

Sign up to request clarification or add additional context in comments.

3 Comments

@Jonathan: It sounds like you're seeing an unrelated error. If you use the here-doc as posted in this answer with bash, it should work. Also note that, as chepner has already pointed out, your curl command is broken with respect to quoting - see my update.
My quoting use is needed, because I'm writing bash commands to a file with cat, within a kubernetes yaml file annotation where the whole block is surrounded by double quotes already, other than thatI agree with you that I'm still very very unfamiliar with heredocs :)
@Jonathan: I see - you should have mentioned that in your question to avoid confusion.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.