passing values with spaces in curl command using POST - shell

I am trying to pass values with spaces in curl POST method. I am directing the values through a txt file. POST command does not allow me to pass values with spaces using the for while loop, But when i pass it without while loop it accepts the value without any error.
Below are the commands
This works perfectly fine
curl -d '{"name": "equity calculation support", "email": "email#test.com"}' -H "Authorization: Basic YWRtaW46YWRtaW4=" -H "Content-Type: application/json" -H "Accept: application/json" -X POST http://localhost:3000/api/teams
{"message":"Team created","teamId":103}
when using while loop and IFS it doesn't take the values with spaces:
while IFS= read -r line ; do curl -d '{"name": "'$line'"}' -H "Authorization: Basic YWRtaW46YWRtaW4=" -H "Content-Type: application/json" -H "Accept: application/json" -X POST 'http://localhost:3000/api/teams'; done < /tmp/group.txt
group.txt file contains the values .

You aren't quoting the expansion of $line:
while IFS= read -r line ; do
curl -d '{"name": "'"$line"'"}' \
-H "Authorization: Basic YWRtaW46YWRtaW4=" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-X POST 'http://localhost:3000/api/teams'
done < /tmp/group.txt
However, it's a better idea to let a tool like jq produce the JSON, to ensure that any characters in $line that need to be escaped to produce proper JSON do, indeed, get escaped.
while IFS= read -r line; do
d=$(jq -n --argjson x "$line" '{name: $x}')
curl -d "$d" ...
done < /tmp/group.txt
It looks like the JSON you want to create would fit on a single line, so you could also process all of /tmp/group.txt with a single call to jq, and pipe its output to your loop.
jq -c -R '{name: .}' | while IFS= read -r line; do
curl -d "$line" ...
done

Related

how to put 2 elements from jq variables in one request?

There is a part of the script where each request receives a response and is written to a variable. How to do it in one request with writing to variables?
boolStatus=$(curl -X 'GET' \
"https://tsit-app1/api/v2/workItems/$case?versionNumber=0" \
-H 'accept: application/json' \
-H "Authorization: $apiKey" | jq '.isAutomated')
echo $boolStatus
name=$(curl -X 'GET' \
"https://tsit-app1/api/v2/workItems/$case?versionNumber=0" \
-H 'accept: application/json' \
-H "Authorization: $apiKey" | jq '.name')
echo $name
I tried
curl -X 'GET' \
"https://tsit-app1/api/v2/workItems/$case?versionNumber=0" \
-H 'accept: application/json' \
-H "Authorization: $apiKey" | jq '"boolStatus=\(.isAutomated)", "name=\(.name)"'
but in echo i get
"boolStatus=true",
"name=bla bla"
need to
echo $boolStatus
true
echo $name
bla bla
One way would be to use the #sh string interpolation and then use your shell's eval.
Using the string interpolation would output something like:
boolStatus=true
name='abc'
which can then be fed to eval:
vars="$(curl ... | jq -r '#sh "boolStatus=\(.isAutomated)", #sh "name=\(.name)"')"
eval "$vars"
or explicitly output the line break:
jq -r '#sh "boolStatus=\(.isAutomated)\nname=\(.name)"'
Disclaimer: Note that this will evaluate any shell code and might open your system to malicious code (#sh escapes the values, but it's always a good idea to be aware of this).
Use process substitution to allow two uses of read to read from the output of jq.
{ read boolStatus; read name; } < <(curl ... | jq -r '.isAutomated, .name')
(assuming the name does not contain any newlines).
At the very least, you can save the output to process with jq twice.
response=$(curl ...)
name=$(echo "$response" | jq -r .name)
boolStatus=$(echo "$response" | jq -r .isAutomated)

PUT call on parameter-defined JSON

I have a script that goes like this where "get_customers" is my pre-defined function and I have to pass each of the following four values as parameter to PUT call for all the customers. However, I am getting the error HTTP 400 Bad Request)","error":"ERROR_BAD_REQUEST" when running this. Anyone knows how I can pass JSON body using this for-loop in PUT call? Is my script wrong?
name=($(get_customers | jq --raw-output '.values[].name'))
tenantId=($(get_customers | jq --raw-output '.values[].tenantId'))
nodeId=($(get_customers | jq --raw-output '.values[].nodeId'))
d=($(get_customers | jq --raw-output '.values[].id'))
for (( i=0; i<${#name[#]}; i++ )); do
curl -X PUT --header "Content-Type: application/json" --header "Accept: application/json" --header "Authorization: Bearer ${API_TOKEN}" -d '{"id":"${d[i]}","name":"${name[i]}","tenantId":"${tenantId[i]}","nodeId":"${nodeId[i]}"}' -k "${URL}/api/file/files/${d[i]}"
done
You are using single quotes, where variables are not expanded. Try this:
for (( i=0; i<${#name[#]}; i++ )); do
curl -X PUT --header "Content-Type: application/json"\
--header "Accept: application/json"\
--header "Authorization: Bearer ${API_TOKEN}"\
-d "$(cat << EOF
{"id":"${d[i]}","name":"${name[i]}","tenantId":"${tenantId[i]}","nodeId":"${nodeId[i]}"}
EOF
)" -k "${URL}/api/file/files/${d[i]}"
done

How to make a valid curl request in shell script? [duplicate]

Goal:
I'm using a bash CURL script to connect to the Cloudflare APIv4. The goal is to update an A-record. My script:
# Get current public IP
current_ip=curl --silent ipecho.net/plain; echo
# Update A record
curl -X PUT "https://api.cloudflare.com/client/v4/zones/ZONEIDHERE/dns_records/DNSRECORDHERE" \
-H "X-Auth-Email: EMAILHERE" \
-H "X-Auth-Key: AUTHKEYHERE" \
-H "Content-Type: application/json" \
--data '{"id":"ZONEIDHERE","type":"A","name":"example.com","content":"'"${current_ip}"'","zone_name":"example.com"}'
Problem:
The current_ip variable is not printed when I call it in my script. The output will be "content" : "" and not "content" : "1.2.3.4".
I used other stackoverflow posts and I'm trying to follow their examples but I think I'm still doing something wrong, just can't figure out what. :(
Using jq for this, as Charles Duffy's answer suggests, is a very good idea. However, if you can't or do not want to install jq here is what you can do with plain POSIX shell.
#!/bin/sh
set -e
current_ip="$(curl --silent --show-error --fail ipecho.net/plain)"
echo "IP: $current_ip"
# Update A record
curl -X PUT "https://api.cloudflare.com/client/v4/zones/ZONEIDHERE/dns_records/DNSRECORDHERE" \
-H "X-Auth-Email: EMAILHERE" \
-H "X-Auth-Key: AUTHKEYHERE" \
-H "Content-Type: application/json" \
--data #- <<END;
{
"id": "ZONEIDHERE",
"type": "A",
"name": "example.com",
"content": "$current_ip",
"zone_name": "example.com"
}
END
The reliable way to edit JSON from shell scripts is to use jq:
# set shell variables with your contents
email="yourEmail"
authKey="yourAuthKey"
zoneid="yourZoneId"
dnsrecord="yourDnsRecord"
# make sure we show errors; --silent without --show-error can mask problems.
current_ip=$(curl --fail -sS ipecho.net/plain) || exit
# optional: template w/ JSON content that won't change
json_template='{"type": "A", "name": "example.com"}'
# build JSON with content that *can* change with jq
json_data=$(jq --arg zoneid "$zoneid" \
--arg current_ip "$current_ip" \
'.id=$zoneid | .content=$current_ip' \
<<<"$json_template")
# ...and submit
curl -X PUT "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records/$dnsrecord" \
-H "X-Auth-Email: $email" \
-H "X-Auth-Key: $authKey" \
-H "Content-Type: application/json" \
--data "$json_data"

cURL using bash script with while read text file

Hi there anyone there having the same trouble like mine?
whenever I cURL the $list from the list.txt it just displaying {} which is a blank response from the API does my code should be really working properly or it is just a bug?
I know the $list is working because I can update the database status
Please this is a bit urgennnnttt :(
#! /bin/bash
filename=/var/lib/postgresql/Script/list.txt
database='dbname'
refLink='URL'
authorization='Authorization: Basic zxc'
expireDate=$(date -d "+3 days")
body="Message."
while IFS=' ' read -r list
do
wow=$(curl --location --request POST $refLink \
--header 'Authorization: Basic $authorization' \
--header 'Content-Type: application/json' \
--data-raw '{
"title":"Expiration Notice",
"body":"$body",
"min" :[{"mobileNumber" : "$list"}],
"type" : "Notification",
"action_type" : "NotificationActivity"}')
echo "result: '$result'"
RESP=$(echo "$result" | grep -oP "^[^a-zA-Z0-9]")
echo "RESP:'$RESP'"
echo $body
#echo $wow >> logs.txt
psql -d $database -c "UPDATE tblname SET status='hehe' WHERE mobile='$list'"
done < $filename
Your "$list" JSON entry is not populated with the content of the $list variable because it is within single quotes of the --data-raw curl parameter.
What you need is compose your JSON data for the query before-hand, preferably with the help of jq or some other JSON processor, before sending it as argument to the curl's POST request.
Multiple faults in your scripts (not exhaustive):
Shebang is wrong with a space #! /bin/bash
expireDate=$(date -d "+3 days") return date in locale format and this may not be what you need for your request.
The request and the response data are not processed with JSON grammar aware tools. grep is not appropriate for JSON data.
Some clues but cannot fix your script more without knowing more about the API answers and functions you use.
Anyway here is how you can at least compose a proper JSON request:
#!/usr/bin/env bash
filename='/var/lib/postgresql/Script/list.txt'
database='dbname'
refLink='URL'
authorization='zxc'
expireDate=$(date -R -d "+3 days")
body="Message."
while IFS=' ' read -r list; do
raw_json="$(
jq -n --arg bdy "$body" --arg mobN "$list" \
'.action_type="NotificationActivity"|.title="Expiration Notice"|.type="Notification"|.body=$bdy|.min[0].mobileNumber=$mobN|.'
)"
json_reply="$(curl --location --request POST "$refLink" \
--header "Authorization: Basic $authorization" \
--header 'Content-Type: application/json' \
--data-raw "$raw_json")"
echo "json_reply: '$json_reply'"
echo "$body"
# psql -d "$database" -c "UPDATE tblname SET status='hehe' WHERE mobile='$list'"
done <"$filename"

How to use a variable in a CURL request with bash?

Goal:
I'm using a bash CURL script to connect to the Cloudflare APIv4. The goal is to update an A-record. My script:
# Get current public IP
current_ip=curl --silent ipecho.net/plain; echo
# Update A record
curl -X PUT "https://api.cloudflare.com/client/v4/zones/ZONEIDHERE/dns_records/DNSRECORDHERE" \
-H "X-Auth-Email: EMAILHERE" \
-H "X-Auth-Key: AUTHKEYHERE" \
-H "Content-Type: application/json" \
--data '{"id":"ZONEIDHERE","type":"A","name":"example.com","content":"'"${current_ip}"'","zone_name":"example.com"}'
Problem:
The current_ip variable is not printed when I call it in my script. The output will be "content" : "" and not "content" : "1.2.3.4".
I used other stackoverflow posts and I'm trying to follow their examples but I think I'm still doing something wrong, just can't figure out what. :(
Using jq for this, as Charles Duffy's answer suggests, is a very good idea. However, if you can't or do not want to install jq here is what you can do with plain POSIX shell.
#!/bin/sh
set -e
current_ip="$(curl --silent --show-error --fail ipecho.net/plain)"
echo "IP: $current_ip"
# Update A record
curl -X PUT "https://api.cloudflare.com/client/v4/zones/ZONEIDHERE/dns_records/DNSRECORDHERE" \
-H "X-Auth-Email: EMAILHERE" \
-H "X-Auth-Key: AUTHKEYHERE" \
-H "Content-Type: application/json" \
--data #- <<END;
{
"id": "ZONEIDHERE",
"type": "A",
"name": "example.com",
"content": "$current_ip",
"zone_name": "example.com"
}
END
The reliable way to edit JSON from shell scripts is to use jq:
# set shell variables with your contents
email="yourEmail"
authKey="yourAuthKey"
zoneid="yourZoneId"
dnsrecord="yourDnsRecord"
# make sure we show errors; --silent without --show-error can mask problems.
current_ip=$(curl --fail -sS ipecho.net/plain) || exit
# optional: template w/ JSON content that won't change
json_template='{"type": "A", "name": "example.com"}'
# build JSON with content that *can* change with jq
json_data=$(jq --arg zoneid "$zoneid" \
--arg current_ip "$current_ip" \
'.id=$zoneid | .content=$current_ip' \
<<<"$json_template")
# ...and submit
curl -X PUT "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records/$dnsrecord" \
-H "X-Auth-Email: $email" \
-H "X-Auth-Key: $authKey" \
-H "Content-Type: application/json" \
--data "$json_data"

Resources