Bash scripting, cannot substitute a command line variable - json

This is a small command line script that is used to post a json body in an http server. I am finding difficulties to pass the first command line argument $1 to the json body.
#!/bin/bash
curl -X POST -d '{ "game": 16, "id": $(($1)) }' http://localhost:10000/
The command does not fail, however the http body contains exactly
{ "game": 16, "id": $(($1)) }
I want to run the script ./script 123 and send the json body
{ "game": 16, "id": 3 }
How can I do this using bash?

You can also use single quotes so you don't have to escape double quotes like this:
#!/bin/bash
curl -X POST -d '{ "game": 16, "id": '$1' }' http://localhost:10000/

Using single quotes will print literal characters. You need to use double quotes for string interpolation. Try:
curl -X POST -d "{ \"game\": 16, \"id\": $1 }" http://localhost:10000/

Related

Having problems using curl post a json object from a variable in bash

So I'm writing a script that needs to create a json object, and post it with curl.
This is working:
curl --header "Content-Type: application/json" --request POST --data '{ "_type": "_test", "_device": "123.123.123.123", "_system": "web-services", "result": "success", "_time": "123", "error": "" }' $data_pipeline
$data_pipeline contains the URL for the post request
if $json_string contains the string including single quotes:
'{ "_type": "_test", "_device": "123.123.123.123", "_system": "web-services", "result": "success", "_time": "123", "error": "" }'
This should work but it doesn't:
curl --header "Content-Type: application/json" --request POST --data $json_string $data_pipeline
First I was creating the $json_object without the single quotes, and tried to add them on the command line for CURL. If I don't escape the single quotes, $json_string is sent as a literal, instead of expanding the variable. I escaped the single quotes, and it did not help, I even tried a double escape in case that was needed, and still it is not working. It only works if I put the entire json string by hand, but not if I put it in a variable. How can I fix this? The json is dynamically created by the script, using jq, and the json is valid as I can successfully run the post by hand, I just need it to work with a variable. It won't work without the single quotes, but the single quotes don't work when I use a variable to hold the json, it doesn't matter if I put the single quotes in the variable, or try to do it outside of the variable... How do I fix this?
The json object is built with this code:
json_string=\'$( jq -n \
--arg _type "$_type" \
--arg _device "$_device" \
--arg _system "$_system" \
--arg result "$result" \
--arg _time "$_time" \
--arg error "$error" \
'{_type: $_type, _device: $_device, _system: $_system, result: $result, _time: $_time, error: $error}' )\'
Originally I was creating the json_string without the ' but I added that in attempt to get the single quotes wrapped around the json.
Thanks!
#!/bin/bash
_type="hello"
# let's have some fun
_device="single'quote"
_system='double"quote'
error='multi
line'
encode()
{
printf "%s" "$1" | sed 's/"/%22/' | tr '\n' ' '
}
# you don't need encode() if your strings are not json-offensive
json_string="{
_type: \"$_type\"
_device: \"$_device\"
_system: \"$(encode "$_system")\"
error: \"$(encode "$error")\"
}"
set -x
curl \
-X POST \
-d "$json_string" \
-H 'content-type: application/json' \
http://httpbin.org/anything
Output:
+ curl -X POST -d '{
_type: "hello"
_device: "single'\''quote"
_system: "double%22quote"
error: "multi line"
}' -H 'content-type: application/json' http://httpbin.org/anything
{
"args": {},
"data": "{\n\t_type: \"hello\"\n\t_device: \"single'quote\"\n\t_system: \"double%22quote\"\n\terror: \"multi line\"\n}",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Content-Length": "92",
"Content-Type": "application/json",
"Host": "httpbin.org",
"User-Agent": "curl/7.58.0",
},
"json": null,
"method": "POST",
"url": "http://httpbin.org/anything"
}

How to send JSON file as part of request body in CURL POST command

I am using CURL command line to send HTTP POST to a web service. I want to include a file's contents as a PART of the body of the POST command. Is this possible? I know I can send a file as the entire body as answered here. But I only want a part of the body to be the content of the file.
For example
curl -d '{ "name": "rahul", "speed": "fast", "data": { "number": 1, "letter": "abd", "letter2": "efg"} }' 'http://...'
Here I only want data as the file's content. Not the entire body. How can I do this?
Set a variable to contain the file contents:
data=$(cat /path/to/file)
then substitute it into the JSON:
curl -d '{ "name": "rahul", "speed": "fast", "data": "'$data'" }' 'http://...'
You accepted #Barmar's answer, but for anyone reading this, #Barmar switched the double- and single-quotes, which will cause the command to not work as intended.
The following works:
data="$(cat filename)" && \
curl -d '{ "name": "rahul", "speed": "fast", "data": "'$data'" }' 'http://...'
Notice that the $data variable is surrounded by single-quotes first, then double-quotes.

Send data with curl in Bash script: positional argument not working

Total noob in BASH. Trying to learn.
I have the following bash script to make an API request:
#!/bin/bash
if [ $1 = "new_event" ]; then
a='https://www.googleapis.com/calendar/v3/calendars/'
b=$2
c='/events?access_token='
d=$3
path=$a$b$c$d
echo $4
OUTPUT="$(curl -s -H "Content-Type: application/json" $path -d $4 )"
echo "${OUTPUT}"
fi
Positional arguments are 'new_event', calendarId, access token and json string.
If I run the script I get:
first echo is the json string I pass as parameter in the call:
' {"guestsCanSeeOtherGuests": false, "location": "", "description": "TEST", "reminders": {"useDefault": false}, "start": {"dateTime": "2017-07-06T14:00:00", "timeZone": "America/Sao_Paulo"}, "end": {"dateTime": "2017-07-06T15:00:00", "timeZone": "America/Sao_Paulo"}, "guestsCanInviteOthers": false, "summary": "TEST", "status": "tentative", "attendees": []} '
second echo gives me parsing error.
BUT, if I copy the echoed json string and replace $4 for it, everything works.
OUTPUT="$(curl -s -H "Content-Type: application/json" $path -d ' {"guestsCanSeeOtherGuests": false, "location": "", "description": "TEST", "reminders": {"useDefault": false}, "start": {"dateTime": "2017-07-06T14:00:00", "timeZone": "America/Sao_Paulo"}, "end": {"dateTime": "2017-07-06T15:00:00", "timeZone": "America/Sao_Paulo"}, "guestsCanInviteOthers": false, "summary": "TEST", "status": "tentative", "attendees": []} ' )"
Any hint why is it not working with the positional argument while it works if I paste it's content?
Thanks!
When you pass the JSON string as a parameter, it assigns the content contained inside the single quote as a whole string but when you pass it to curl it was subjected to word splitting.
To show what it looks like here's a sample script to demonstrate it.
This script will receive the string and pass it to the second script.
#!/bin/bash
./params $1
This second script simulates what curl sees. It will print the number of parameters it receives.
#!/bin/bash
echo $#
Guess what the output is:
27
To fix your issue and make it simpler, drop the outermost quote and quote everything inside the $().
OUTPUT=$(curl -s -H "Content-Type: application/json" "$path" -d "$4" )

Windows: curl with json data on the command line

I am running the following command in Windows prompt:
curl -XPUT http://127.0.0.1:9200/test-index/test-type/_mapping?pretty=true -d '{"test-type": {"properties": {"name": {"index": "analyzed", "term_vector": "with_positions_offsets", "boost": 1.0, "store": "yes", "type": "string"}}}}'
I get the following error:
{
"error" : "ElasticsearchParseException[Failed to parse content to map]; nested: JsonParseException[Unexpected character (''' (code 39)): expected a
valid value (number, String, array, object, 'true', 'false' or 'null')\n at [Source: org.elasticsearch.common.compress.lzf.LZFCompressedStreamInput#45
4ed1d2; line: 1, column: 2]]; ",
"status" : 400
}
I searched for solutions and found alternatives such as put json data in files, but I cannot use it for some reasons.
Thanks!
Windows's cmd doesn't support strings with single quotes. Use " and escape the inner ones with \".
"I searched for solutions and found alternatives such as put json data in files, but I cannot use it for some reasons"
This should work, with hello.json in temp. The # is requried.
c:\temp>curl -v -X PUT \
--data "#hello.json" \
-H "Content-Type:application/json" \
http://localhost:8080/api/myresource

Why does this JSON POST post an empty file?

I am trying to post the following JSON to a URL using cURL in Terminal:
[
{
"token": "ABCDEF",
"templateId": "{1234-5678-9}",
"senders": "null",
"viewers": "null",
"peoples": "null",
"fields": {
"Matter Name": "My test matter name",
"Matter Number": "ABC123"
}
}
]
This is how I POST it in Terminal:
curl -v -k -X POST -H "Content-Type: application/json" -d docfile=#test.json https://myWebsite.com/extension/extension/extension
The Terminal output clearly says that something was posted but the part that confuses me is this excerpt from the output: upload completely sent off: 18 out of 18 bytes
Only 18 bytes were sent? My file is 218 bytes...Why is this file not being POSTed? What is being POSTed?
The problem is with your -d switch. From the documentation:
-d
Sends the specified data in a POST request to the HTTP server... If you start the data with the letter #, the rest should be a file name to read the data from.
What you are passing to the -d switch does not begin with "#", so it is being interpreted as actual data. You'll notice docfile=#test.json IS actually 18 bytes.
You need to change it from -d docfile=#test.json to -d #test.json.