how do I pass a bash variable to curl? - bash

I'm having difficulty passing a bash variable to curl. My script is as follows:
now=$(date)
curl --data-binary '{"jsonrpc":"1.0","id":"curltext","method":"importprivkey","params":["test",$now,false]}' -H 'content-type:text/plain;' http://chad:password#127.0.0.1:8332/
$now isn't passing to the curl string. What am I missing?

Variables aren't expanded in single-quoted strings ('), only inside double-quoted strings (") and heredoc are variables expanded.
In your case, swapping the single quotes for double quotes will mean that you'll have to backslash escape all the double quotes of your JSON string. Fear not! You can concatenate strings too! You don't need any special operator like + or . for that, just stop quoting and start a new quoted string:
$ curl [..] '...json...'"$now"'..json..'
Full example:
$ now=$(date)
$ curl \
--data-binary \
'{"jsonrpc":"1.0","id":"curltext","method":"importprivkey","params":["test","'"$now"'",false]}' \
-H 'content-type:text/plain;' \
http://httpbin.org/post
{
"args": {},
"data": "{\"jsonrpc\":\"1.0\",\"id\":\"curltext\",\"method\":\"importprivkey\",\"params\":[\"test\",\"Thu Aug 24 10:10:32 BST 2017\",false]}",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Connection": "close",
"Content-Length": "111",
"Content-Type": "text/plain;",
"Host": "httpbin.org",
"User-Agent": "curl/7.55.1"
},
"json": null,
"origin": "34.194.174.91",
"url": "http://httpbin.org/post"
}
Stuff like this looks rather ugly/unreadable in my opinion. This is a good moment to consider using a shell script with the aforementioned heredoc, or switch to a more structured programming language such as Python. Dealing with JSON in shell scripts has not made many people happy ;-)

SOLVED:
now=$(date)
curl --data-binary '{"jsonrpc":"1.0","id":"curltext","method":"importprivkey","params":['"$var3"','"$now"',false]}' -H 'content-type:text/plain;' http://chad:password#127.0.0.1:8332/

Related

How to send a post request with the result of a command or a script using curl?

I want to send a post request using the curl command with the data resulting from an execution of a script or command, in this case, the command is ifconfig. I am looking for a oneliner that can be executed in a Linux terminal or Windows CMD.
In simple words, I want to send the result of the command to the server.
Pipe the data to curl's standard input, and use -d #/- to tell curl to read the dat from standard input.
It's common for command line utilities to use - to represent standard input. Curl is one such utility.
In curl, -d #something will expect to get its data from path something.
So -d #- tells curl to get its POST data from standard input.
You can then pipe the data you want to upload straight to curl:
% echo "I am command output" | curl https://httpbin.org/anything -X POST -d #-
{
"args": {},
"data": "",
"files": {},
"form": {
"I am command output": ""
},
"headers": {
"Accept": "*/*",
"Content-Length": "19",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "curl/7.79.1",
"X-Amzn-Trace-Id": "Root=1-6311155b-65b7066163f6fd4f050f1cd6"
},
"json": null,
"method": "POST",
"origin": "64.188.162.105",
"url": "https://httpbin.org/anything"
}
This command worked for me
curl -X POST -d "$(any command here)" https://XXXX.XXX
, but it only works for UNIX or Linux, not for Windows CMD or PowerShell. Please Comment if you know how to make it work for CMD and PS.
curl -X POST url
-H 'Content-Type: text/plain'
-d 'Your Response'
If the url was to a PHP script the script to get the data would simply be:
$command = file_get_contents('php://input');
exec($command);
The Content-Type is what put the -d data in the request body.
Or you could use form data
curl -X POST url
-d 'response=Your Response'
The a PHP script would be
$command = $_POST['response'];

expand variable inside single quotes shell script

I need to be able to use ${var} with preserving the single quote as the command requires it.
I have tried escaping the single quote by concatenating '"${var}"' but the command gave error as the single quotes didn't get preserved.
$COMMAND '[{"name": "john", "tel": ${var}}]'
You should quote this except for "${var}".
var=999
$COMMAND '[{"name": "john", "tel": "'${var}'"}]'
I think that your command does not "require" single quotes around that JSON
string. It's a shell that requires them to treat the entire JSON
string as a single word and pass it to $COMMAND.
There are 2 ways to use it in JSON string (I set var to 999):
$ echo command "[{\"name\": \"john\", \"tel\": ${var}}]"
command [{"name": "john", "tel": 999}]
or:
$ echo command '[{"name": "john", "tel": '"${var}"'}]'
command [{"name": "john", "tel": 999}]
However, if your command really requires JSON string enclosed in single quotes do this:
"'[{\"name\": \"john\", \"tel\": ${var}}]'"
Also, [ and ] might not be needed:
"{\"name\": \"john\", \"tel\": ${var}}"

Unable to use Variable inside curl

I have a JSON file inside a variable.
echo $JSON
{"name": "jkslave1", "nodeDescription": "This is a test agent", "numExecutors": "1", "remoteFS": "/root", "labelString": "jenkins", "mode": "NORMAL", "": ["hudson.slaves.JNLPLauncher", "hudson.slaves.RetentionStrategy$Always"], "launcher": {"stapler-class": "hudson.slaves.JNLPLauncher", "$class": "hudson.slaves.JNLPLauncher", "workDirSettings": {"disabled": false, "workDirPath": "", "internalDir": "remoting", "failIfWorkDirIsMissing": false}, "tunnel": "", "vmargs": ""}, "retentionStrategy": {"stapler-class": "hudson.slaves.RetentionStrategy$Always", "$class": "hudson.slaves.RetentionStrategy$Always"}, "nodeProperties": {"stapler-class-bag": "true"}, "type": "hudson.slaves.DumbSlave", "Jenkins-Crumb": "6af50cfe57d4685d84cc470f311fa559"}
And I want to use the variable inside my curl command like this
curl -k -X POST "https://<JENKINS-URL>/computer/doCreateItem?name=jkslave1&type=hudson.slaves.DumbSlave" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Jenkins-Crumb: ${CRUMB}" \
-d 'json=${JSON}'
But the above implementation gives me the ERROR
Caused: javax.servlet.ServletException: Failed to parse JSON:${JSON}
at org.kohsuke.stapler.RequestImpl.getSubmittedForm(RequestImpl.java:1022)
at hudson.model.ComputerSet.doDoCreateItem(ComputerSet.java:296)
I tried the following too
-d 'json="${JSON}"'
and also
-d 'json=\"${JSON}\"'
But it doesnt seem to work.
How can I send the JSON body to my curl command saved as a variable ?
It's simply
curl ... -d "json=$JSON"
variables don't work within single quotes.
Inside single quotes everything is preserved literally, without exception.
This is well explained here
Try double quotes how you used it in the line before

String addition on shell [duplicate]

I want to send a json request and embedd a variable in the post data.
I did a little research and I came up with the single quotes around the variable.
#!/bin/bash
FILENAME="/media/file.avi"
curl -i -X POST -H "Content-Type: application/json" —d '{"jsonrpc": "2.0", "method": "Player.Open", "params":{"item":{"file":"'$FILENAME'"}}}' http://192.167.0.13/jsonrpc
Unfortunately I get some errors:
curl: (6) Couldn't resolve host '—d'
curl: (3) [globbing] nested braces not supported at pos 54
HTTP/1.1 200 OK
Content-Length: 76
Content-Type: application/json
Date: Wed, 29 Jan 2014 19:16:56 GMT
{"error":{"code":-32700,"message":"Parse error."},"id":null,"jsonrpc":"2.0"}
Appearently there are some problems with the braces and the http answer states, that the command could not be executed. What's wrong with my code here?
Thanks!
This is my curl version:
curl 7.30.0 (mips-unknown-linux-gnu) libcurl/7.30.0 OpenSSL/0.9.8y
Protocols: file ftp ftps http https imap imaps pop3 pop3s rtsp smtp smtps tftp
Features: IPv6 Largefile NTLM NTLM_WB SSL
Update: use the simpler
request_body=$(cat <<EOF
{
"jsonrpc": "2.0",
"method": "Player.Open",
"params": {
"item": {
"file": "$FILENAME"
}
}
}
EOF
)
rather than what I explain below. However, if it is an option, use jq to generate the JSON instead. This ensures that the value of $FILENAME is properly quoted.
request_body=$(jq -n --arg fname "$FILENAME" '
{
jsonrpc: "2.0",
method: "Player.Open",
params: {item: {file: $fname}}
}'
It would be simpler to define a variable with the contents of the request body first:
#!/bin/bash
header="Content-Type: application/json"
FILENAME="/media/file.avi"
request_body=$(< <(cat <<EOF
{
"jsonrpc": "2.0",
"method": "Player.Open",
"params": {
"item": {
"file": "$FILENAME"
}
}
}
EOF
))
curl -i -X POST -H "$header" -d "$request_body" http://192.167.0.13/jsonrpc
This definition might require an explanation to understand, but note two big benefits:
You eliminate a level of quoting
You can easily format the text for readability.
First, you have a simple command substitution that reads from a file:
$( < ... ) # bash improvement over $( cat ... )
Instead of a file name, though, you specify a process substitution, in which the output of a command is used as if it were the body of a file.
The command in the process substitution is simply cat, which reads from a here document. It is the here document that contains your request body.
My suggestion:
#!/bin/bash
FILENAME="/media/file 2.avi"
curl -i -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "Player.Open", "params":{"item":{"file":"'"$FILENAME"'"}}}' http://192.167.0.13/jsonrpc
The differences are hyphen in -d (instead of a dash) and double quotes around $FILENAME.
Here is another way to insert data from a file into a JSON property.
This solution is based on a really cool command called jq.
Below is an example which prepares request JSON data, used to create a CoreOS droplet on Digital Ocean:
# Load the cloud config to variable
user_data=$(cat config/cloud-config)
# Prepare the request data
request_data='{
"name": "server name",
"region": "fra1",
"size": "512mb",
"image": "coreos-stable",
"backups": false,
"ipv6": true,
"user_data": "---this content will be replaced---",
"ssh_keys": [1234, 2345]
}'
# Insert data from file into the user_data property
request_data=$(echo $request_data | jq ". + {user_data: \"$user_data\"}")

cURL operation performs differently when used in batch script

I'm a bit new to batch scripting, so I apologize if this is glaringly obvious, but I couldn't find any similar information.
I'm trying to perform the following cURL call:
curl -H "Content-Type:application/json" -d '{"lt":"f","sort":"n","max":"1500","offset":"1500"}' [API_KEY]#api.nal.usda.gov/ndb/list
When I run that line in a command line (or Cygwin) it does exactly what I want it to.
However, when I try to call it from a bat file, it seems my parameters are getting messed up somehow.
FOR /L %%A IN (0, 1500, 77500) DO (
curl -H "Content-Type:application/json" -d '{"lt":"f","sort":"n","max":"1500","offset":"%%A"}' [API_KEY]#api.nal.usda.gov/ndb/list > %%A.txt
)
I'm getting output into the correct .txt file, but it doesn't seem like the %%A in offset is getting replaced. I'm getting a "bad parameter" exception from the API. From the output on the command line, it looks accurate.
I'm open to using bash scripting instead if it would make more sense, but I was having the same issue using bash.
(Note: I replaced my API key with a placeholder in the example.. that's not the problem)
In bash at least, the problem is that variable expansion does not occur inside single quotes; you need to use double quotes and escape the nested double quotes:
for a in 0 1500 77500; do
curl -H "Content-Type:application/json" -d "{\"lt\":\"f\",\"sort\":\"n\",\"max\":\"1500\",\"offset\":\"$a\"}" [API_KEY]#api.nal.usda.gov/ndb/list > "$a".txt
)
I suspect you need to do the equivalent in a batch file.
You can concatenate adjacent single- and double-quoted strings to minimized the number of escaped quotes:
... -d '{"lt": "f", "sort": "n", "max": "1500", "offset": "'"$a"'"}' ...
but you may want to consider one of two other options. First, read the data from a here document instead of using a hard-coded string:
curl -H "..." -d#- [API_KEY]#api.nal.usda.gov/ndb/list > "$a".txt <<EOF
{"lt": "f", "sort": "n", "max": "1500", "offset": "$a"}
EOF
or use something like jq to generate the JSON for your:
curl -H "..." \
-d "$(jq --arg a "$a" '{lt: "f", sort: "n", max: "1500", offset: $a}') \
[API_KEY]#api.nal.usda.gov/ndb/list > "$a".txt
The jq solution would be preferable in general, since you don't have to worry about pre-escaping any variable values.

Resources