Reputation: 8741
I'm trying to send some headers and key value pairs of data to my server using curl. It looks like I'm getting a bash quoting problem, my key value pairs are being treated like hosts.
curl -v --header "Content-Type: application/json" \
--header "Foo: Bar 123456" \
-d \"\{ "baz": "glern", "froboz": "foo again"\}\" \
https://example.com > foo.html 2> error.txt
example.com is telling me:
HTTP 404 Not Found: URL or Document not found (dns_unresolved_hostname)
HTTP 404: Your requested host "baz" could not be resolved by DNS. The document at the specified URL does not exist.
HTTP 404 Not Found: URL or Document not found (dns_unresolved_hostname)
HTTP 404: Your requested host "glern," could not be resolved by DNS. The document at the specified URL does not exist.
and error.txt starts off like this:
* Rebuilt URL to: baz:/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 10.196.133.236...
* TCP_NODELAY set
* Connected to http.proxy.mycompanyproxy.com (10.196.133.236) port 8000 (#0)
> POST http://baz:/ HTTP/1.1
> Host: baz
> User-Agent: curl/7.54.0
> Accept: */*
> Proxy-Connection: Keep-Alive
> Content-Type: application/json
> Foo: Bar 123456
> Content-Length: 2
> } [2 bytes data]
* upload completely sent off: 2 out of 2 bytes
< HTTP/1.1 404 Not Found
...
I certainly don't mean to hit the hosts baz, glern, etc... and it certainly looks like a shell quoting problem. But after trying many different things, like adding extra \" near the existing bare " around my key value pairs, I'm a bit lost here.
Upvotes: 1
Views: 1266
Reputation: 531205
Consider what your data would look like if you simply had a file:
$ cat tmp.json
{ "baz": "glern", "froboz": "foo again" }
In that case, you'd simply use
$ curl ... -d "$(cat tmp.json)"
Now just do the command substitution "manually", so to speak (switching from double to single quotes to avoid escaping a bunch of quotes on the command line):
$ curl ... -d '{ "baz": "glern", "froboz": "foo again" }'
# with double quotes, it's
# curl ... -d "{ \"baz\": \"glern\", \"froboz\": \"foo again\" }"
# ... ew.
In general, though, it's better to let a tool like jq
generate JSON for you instead of trying to write it manually; this can simplify quoting greatly when it is needed.
$ curl ... -d "$(jq -n '{baz: "glern", froboz: "foo again"}')"
It's almost mandatory to use such a tool if your JSON isn't hard-coded, but from variables like {"baz": "$SOME_VAR"}
. Instead of jumping through hoops to make sure everything in SOME_VAR
is properly escaped, let jq
do it for you: jq -n --argjson x "$SOME_VAR" '{baz: $x}'
. Note that $x
is not a shell variable; it's a jq
variable.
Upvotes: 3
Reputation: 753970
After the -d
, only the \"\{
forms an argument to -d
. It isn't absolutely clear what you're after, but maybe:
curl -v --header "Content-Type: application/json" \
--header "Foo: Bar 123456" \
-d '{ "baz": "glern", "froboz": "foo again"}' \
https://example.com > foo.html 2> error.txt
That way, the argument to -d
is:
{ "baz": "glern", "froboz": "foo again"}
There's no call to use double quotes around a string that contains copious double quotes; that just makes life harder.
Upvotes: 3