escape variable in bash script curl request - linux

I am trying to curl via bash script but unable to pass the value of var1 in curl request and getting error upon execution ...
#!/bin/bash
var1="some test message"
curl 'https://link' \
-H 'Content-Type: application/json' \
-d '
{"msgtype": "text",
"text": {
"content": $var1
}
}'

Your variable $var1 doesn't get expanded by the shell because it is inside single quote '.
You need to use double quote to let bash do the parameter expansion, and escape your json data:
#!/bin/bash
var1="some test message"
curl 'https://link' \
-H 'Content-Type: application/json' \
-d "
{
\"msgtype\": \"text\",
\"text\": {
\"content\": \"$var1\"
}
}"
Or you can use inline document (without the escaping hell, but the command becomes awkward):
#!/bin/bash
var1="some test message"
curl 'https://link' \
-H 'Content-Type: application/json' \
-d "$(cat <<EOT
{
"msgtype": "text",
"text": {
"content": "$var1"
}
}
EOT
)"

In general, don't use parameter expansion to define JSON dynamically like this. There is no guarantee that your template, combined with the contents of the variable, produces well-formed JSON. (This is for the same reasons you don't use string interpolation to create dynamic SQL queries.) Use a tool like jq instead.
curl 'https://link' ... \
-d "$(jq --argjson x "$var" \
-n '{msgtype: "text", text: {content: $x}}')"

Use below script.
https://aaa.com' -H 'Content-Type: application/json' -d '{"msgtype": "text", "text": { "content": '"'$var1'"' }}'

Related

how to use loop with some conditions in shell script

I need to run a curl command several times, and check the result every time. I used a for loop to check the output from curl, and I want to exit the loop when the correct status is reached.
The very first time the curl command is run, it will show me this output :
{
"name": "organizations/org_name/operations/long_running_operation_ID",
"metadata": {
"#type": "type.googleapis.com/google.cloud.apigee.v1.OperationMetadata",
"operationType": "INSERT",
"targetResourceName": "organizations/org_name",
"state": "IN_PROGRESS"
}
}
It takes time to complete, that's why it says IN_PROGRESS. It took around 30 to 60 sec, and if we run the same curl command after 30 to 60 sec then it will show the output below :
{
"error": {
"code": 409,
"message": "org graceful-path-310004 already associated with another project",
"status": "ALREADY_EXISTS",
"details": [
{
"#type": "type.googleapis.com/google.rpc.RequestInfo",
"requestId": "11430211642328568827"
}
]
}
}
Here is the script I have so far :
test=$(curl -H "Authorization: Bearer $TOKEN" -X POST -H "content-type:application/json" \
-d '{
"name":"'"$ORG_NAME"'",
"displayName":"'"$ORG_DISPLAY_NAME"'",
"description":"'"$ORGANIZATION_DESCRIPTION"'",
"runtimeType":"'"$RUNTIMETYPE"'",
"analyticsRegion":"'"$ANALYTICS_REGION"'"
}' \
"https://apigee.googleapis.com/v1/organizations?parent=projects/$PROJECT_ID" | jq '.error.status')
echo $test
while [ $test = "ALREADY EXISTS" || $test != "IN_PROGRESS" ]
do
echo $test
echo "Organization is creating"
test=$(curl -H "Authorization: Bearer $TOKEN" -X POST -H "content-type:application/json" \
-d '{
"name":"'"$ORG_NAME"'",
"displayName":"'"$ORG_DISPLAY_NAME"'",
"description":"'"$ORGANIZATION_DESCRIPTION"'",
"runtimeType":"'"$RUNTIMETYPE"'",
"analyticsRegion":"'"$ANALYTICS_REGION"'"
}' \
"https://apigee.googleapis.com/v1/organizations?parent=projects/$PROJECT_ID" | jq '.error.status')
done
echo "exit from loop"
To reduce the duplicated code, use functions.
Also, best practice to use jq to generate json -- it will safely handle any embedded quotes in the data:
json() {
jq --arg name "$ORG_NAME" \
--arg displayName "$ORG_DISPLAY_NAME" \
--arg description "$ORGANIZATION_DESCRIPTION" \
--arg runtimeType "$RUNTIMETYPE" \
--arg analyticsRegion "$ANALYTICS_REGION" \
--null-input --compact-output \
'$ARGS.named'
}
errorStatus() {
curl -H "Authorization: Bearer $TOKEN" \
-X POST \
-H "content-type:application/json" \
-d "$(json)" \
"${URL}?parent=projects/$PROJECT_ID" \
| jq -r '.error.status'
}
while true; do
status=$(errorStatus)
[ "$status" = "ALREADY EXISTS" ] && break
done
echo "exit from loop"
The while true; do some code; condition && break; done bit is the bash version of a do-while loop

How to store only one response of curl command [duplicate]

This question already has answers here:
Difference between single and double quotes in Bash
(7 answers)
Closed 1 year ago.
i want to store the output of curl command in a variable but not whole response only one value of that response
i have this curl command
curl -H "Authorization: Bearer $TOKEN" -X POST -H "content-type:application/json" \
-d '{
"name":"'"$ORG_NAME"'",
"displayName":"'"$ORG_DISPLAY_NAME"'",
"description":"'"$ORGANIZATION_DESCRIPTION"'",
"runtimeType":"'"$RUNTIMETYPE"'",
"analyticsRegion":"'"$ANALYTICS_REGION"'"
}' \
"https://apigee.googleapis.com/v1/organizations?parent=projects/$PROJECT_ID"
when i hit this command then it will show the response look like this
{
"name": "organizations/heloo/operations/keijfiejwfefekd",
"metadata": {
"#type": "type.googleapis.com/google.cloud.apigee.v1.OperationMetadata",
"operationType": "INSERT",
"targetResourceName": "organizations/heloo",
"state": "IN_PROGRESS"
}
}
so in the response i want to store this state value in a variable
test=$(curl -H "Authorization: Bearer $TOKEN" -X POST -H "content-type:application/json" \
-d '{
"name":"'"$ORG_NAME"'",
"displayName":"'"$ORG_DISPLAY_NAME"'",
"description":"'"$ORGANIZATION_DESCRIPTION"'",
"runtimeType":"'"$RUNTIMETYPE"'",
"analyticsRegion":"'"$ANALYTICS_REGION"'"
}' \
"https://apigee.googleapis.com/v1/organizations?parent=projects/$PROJECT_ID" | jq '.metadata.state')
it will work

parse JSON out from curl response using Sed or awk and assign to variable for later use

I am writing a bash script to be run on a linux appliance so I do not have access to install jq, I need to be able to use native Linux tools
curl --location --request POST "https://api-mp.meraki.com/api/v1/networks/12345/switch/stacks/12345/routing/interfaces" \
--header "X-Cisco-Meraki-API-Key: 123key" \
--header "Content-Type: application/json" \
--data '{
"name": "L3 int",
"subnet": "192.168.249.0/24",
"interfaceIp": "192.168.249.2",
"multicastRouting": "disabled",
"vlanId": 140,
"ospfSettings": {
"area": "0",
"cost": 1,
"isPassiveEnabled": true
}
}' | sed -n 's|.*"interfaceID":"\([^"]*\)".*|\1|p' > $newVar
the response from the server returns this:
{
"interfaceId": "12345",
"name": "PA L3 DR Int",
"subnet": "192.168.249.0/24",
"interfaceIp": "192.168.249.2",
"multicastRouting": "disabled",
"vlanId": 140,
"ospfSettings": {
"area": "0",
"cost": 1,
"isPassiveEnabled": true
}
}
I then need to be able to access the interfaceID new variable in a query string paramter
You just got the case wrong (ID vs Id in interfaceId) and forgot about the space after :, but you were close:
$ sed -n 's|.*"interfaceId": *"\([^"]*\)".*|\1|p' file
12345
Using cat file in place of your curl command to show how to save that to a variable in case you don't know:
$ var=$(cat file | sed -n 's|.*"interfaceId": *"\([^"]*\)".*|\1|p')
$ echo "$var"
12345
Could you please try following. Tested successfully in link
https://ideone.com/EsdCQp
your_command |
awk '
/"interfaceId": "/{
gsub(/[^0-9]+|"\,/,"")
print
}
'

Using Curl with Json (Node.js)

I am having trouble getting curl and Json (Node.js) to work when I in curl omit the "[ and ]" part of the JSON-RPC request params. I am using named parameters (i.e. an object, not an array).
This works:
curl -v -i POST -H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "method":"registerPerson", "params": ["{\"username\":\"morten10\",\"password\":\"mypass\"}"], "id":1 }' \
http://localhost:3000
However, when I omit the [" and ]" from the params it doesn't work:
curl -v -i POST -H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "method":"registerPerson", "params": {\"username\":\"morten10\",\"password\":\"mypass\"}, "id":1 }' \
http://localhost:3000
and Jayson gives this error message:
TypeError: First argument must be a string or Buffer
However, according to the JSON-RPC 2.0 specification and its examples, I should be able to exclude the "[ and ]" part from params when I use named parameters, as in this example:
--> {"jsonrpc": "2.0", "method": "subtract", "params": {"minuend": 42, "subtrahend": 23}, "id": 4}
<-- {"jsonrpc": "2.0", "result": 19, "id": 4}
What am I not getting?
Thanks!
I think your object needs to be a string as suggested by the error.
Try:
curl -v -i POST -H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "method":"registerPerson", "params": "{\"username\":\"morten10\",\"password\":\"mypass\"}", "id":1 }' \
http://localhost:3000

How to read headers from file using cURL?

I found this.
And I wrote this variant:
#!/bin/bash
while read line ; do
headers="$headers -H '$line'"
done < public/headers.txt
echo $headers
curl -X PUT \
$headers \
-d #'public/example.json' \
echo.httpkit.com
In headers.txt I have:
X-PAYPAL-SECURITY-USERID:123
X-PAYPAL-SECURITY-PASSWORD:123
But when I run ./public/curl.sh I am not getting the headers I am sending.
I isolated the issue with an env var:
$ x='-H some:asd'
$ curl $x echo.httpkit.com
=> header was NOT present
$ curl -H 'some:asd' echo.httpkit.com
=> header was present
$ curl -H some:asd echo.httpkit.com
=> header was present
How can I correctly insert a variable in the header section?
Let's ask shellcheck:
In yourscript line 3:
headers="$headers -H '$line'"
^-- SC2089: Quotes/backslashes will be treated literally.
Use an array.
Ok, then let's do that:
#!/bin/bash
while read line ; do
headers=("${headers[#]}" -H "$line")
done < public/headers.txt
echo "${headers[#]}"
curl -X PUT \
"${headers[#]}" \
-d #'public/example.json' \
echo.httpkit.com
Result:
{
"method": "PUT",
"uri": "/",
"path": {
"name": "/",
"query": "",
"params": {}
},
"headers": {
"host": "echo.httpkit.com",
"user-agent": "curl/7.35.0",
"accept": "*/*",
"x-paypal-security-userid": "123", // <----- Yay!!
"x-paypal-security-password": "123",
"content-length": "32",
"content-type": "application/x-www-form-urlencoded"
},
"body": "\"This is text from example.json\"",
"ip": "127.0.0.1",
"powered-by": "http://httpkit.com",
"docs": "http://httpkit.com/echo"
}
If you don't want to put the HTTP headers on a command line (perhaps for security reasons), you can still have curl read them directly from a file.
curl -H #headerfile.txt https://www.google.com/ # requires curl >=7.55.0
If your curl is older than 7.55.0:
Use the option -K/--config <config file>, and put several -H/--header <header> lines in the text file.
For more details, please see my answer in the original article:
https://stackoverflow.com/a/48762561/5201675

Resources