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.
Related
I have written a bash script using Curl command. I'm using an SQL query that gives a count of value 5. I want to assign that count value to T_4. Not sure how to do that in bash script using Curl command.
#!/bin/sh
result=$(
curl --netrc-file ~/.netrc -d '[
{
"T_1": "Test1",
"T_2": "Test2",
"T_3": "Test3",
"T_4": "1"
}
]' -X POST -H "Content-Type: application/json" https://www.testurl.com -d "SELECT count(5) FROM DUAL")
echo "Response from server"
echo $result
exit
Also, when I run the above script in putty, I'm getting an error that says -
"errorCode":"SIP-10322","errorMessage":"SIP-10322: rows updated is not 1:0"
Need your input on this.
The output of the SQL query which is a metric value, I have to use it in Rest call(Post API). Can anyone guide me on this?
Use command substitution to execute the query and assign the output to a shell variable. For instance, if the DB is MySQL, you would use:
t_4=$(mysql -e "SELECT 5 FROM DUAL")
Then use the variable inside the JSON parameter.
json='[
{
"T_1": "Test1",
"T_2": "Test2",
"T_3": "Test3",
"T_4": "'$t_4'"
}
]'
result=$(curl --netrc-file ~/.netrc -d "$json" -X POST -H "Content-Type: application/json" https://www.testurl.com)
I am hitting a wall trying to build a script to save myself quite a good bit of time. I am working in a system in which I need to run a curl POST against a list of values. The list is about 400 lines long, so I am hoping to find a way of scripting this in Bash instead of running that call manually for each entry. Below are some details to help understand what I'm trying to accomplish:
If I were to be doing this task manually, each call would be formatted like the below:
curl -X POST --header "Content-Type: application/json" -v 'http://www.website.com:8081/cc/membership' -d #json_payload.json
This points to my JSON in the listed file which shows as the below:
{
"groupId": "12345678987654321",
"type": "serial",
"memberInfo": "apple"
}
If I run the above, the call works, and the expected operation occurs. The issue is that I need to run this against roughly 400 values for that "memberInfo" field in the JSON payload. I'm trying to identify a way to run a single bash script, which will run this curl command over and over, and update the JSON payload to use each row in a file as the below:
memberList.txt
apple
banana
peach
pear
orange
.
.
And then maybe insert a pointer in my JSON for the "memberInfo" field over to this file.
Any and all help/suggestions are greatly appreciated!
.
This will do as you intend. Its a little convoluted but you might polish it a bit.
#!/bin/bash
function getString(){
echo $1 | python3 -c '
import json
import sys
payload="""
{
"groupId": "12345678987654321",
"type": "serial",
"memberInfo": ""
}
"""
obj = json.loads(payload)
obj["memberInfo"] = sys.stdin.read().strip()
print(json.dumps(obj, indent = " "))
'
}
while read member
do
getString "$member" > json_payload.json
curl -X POST --header "Content-Type: application/json" -v 'http://www.website.com:8081/cc/membership' -d #json_payload.json
done <<< "$( cat fruits.txt )"
Hope it helps!
while read member; do
curl -X POST --header "Content-Type: application/json" -v 'http://www.website.com:8081/cc/membership' -d '{"groupId": "12345678987654321","type": "serial","memberInfo": "$member"}'
done <members.txt
This will work if you only care about the memberInfo field, another method could be writing your json line by line to payloads.txt file.
payloads.txt
{"groupId": "12345678987455432","type": "stereo","memberInfo": "apple"}
{"groupId": "34532453453453465","type": "serial","memberInfo": "banana"}
...
then use this as the script
while read payload; do
curl -X POST --header "Content-Type: application/json" -v 'http://www.website.com:8081/cc/membership' -d '$payload'
done <payloads.txt
here is a collection of bash scripting common uses I've had to use
https://github.com/felts94/advanced-bash/blob/master/bash_learn.sh
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
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\"}")
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/