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

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)

Related

Doing PUT using bash script

I am writing a bash script that does this :
Get a list of customers
For each customer, query an API (get files) This returns id and name
For each file, do a PUT.
My question is, I want to both "id" and "name" in my PUT body, so how can I get this in a single loop on "files" API. I have written this:
URL="https://some-url.com"
API_TOKEN="some-token"
get_customers() {
curl --insecure \
--fail \
--header "Accept: application/json" \
--header "Authorization: Bearer ${API_TOKEN}" \
-k ${URL}/api/org/customers
}
get_files() {
curl --insecure \
--fail \
--header "Accept: application/json" \
--header "Authorization: Bearer ${API_TOKEN}" \
-k ${URL}/api/files/files
}
put_capability() {
echo ""
curl --insecure \
--fail \
--silent \
--header "Content-Type: application/json" \
--header "Authorization: Bearer ${API_TOKEN}" \
--data #- \
${URL}/api/files/files/{id}
echo ""
}
customers=($(get_customers | jq --raw-output '.values[].id'))
for customer_id in "${customers[#]}"; do
fileshares=($(get_files ${customer_id} | jq --raw-output '.values[].id'))
fileshares-names=($(get_files ${customer_id} | jq --raw-output '.values[].name'))
for fileshare_id in "${fileshares[#]}"; do
#call function put_capability and do subsequent PUT.
#PUT needs two parameters, fileshares and fileshares-names
done
done
Basically, I don't want to call "get_files" twice as I am doing now. I need both the "fileshares" and "fileshares-names" in my subsequent PUT API. Can this be done in one for loop on file shares?
You can parse get_files output once by storing it in a temp file like that :
customers=($(get_customers | jq --raw-output '.values[].id'))
for customer_id in "${customers[#]}"; do
get_files ${customer_id} > /tmp/cust.txt
fileshares=($(cat /tmp/cust.txt | jq --raw-output '.values[].id'))
fileshares-names=($(cat /tmp/cust.txt | jq --raw-output '.values[].name'))
for fileshare_id in "${fileshares[#]}"; do
#call function put_capability and do subsequent PUT.
#PUT needs two parameters, fileshares and fileshares-names
done
done

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

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"

Curl command in shell script returning error {"Error":"bpapigw-300 Cannot authorize access to resource"

I am trying to execute curl using this shell script:
#!/bin/bash
curl -k -H "Content-Type:application/json" -d '{"username":"admin","password":"adminpw", "tenant":"master"}' https://localhost/tron/api/v1/tokens > /tmp/token.data
grep -Po '{\"token\":\"\K[^ ]...................' /tmp/token.data > /tmp/token
tokendetails=`cat /tmp/token`
for token in $tokendetails
do
TOKEN=`echo $token`
done
userdetails=`cat /tmp/curloutput.txt | sed 's/{"clientInactivityTime"/\n{"clientInactivityTime"/g' | sed 's/\(.*\).\("firstName":[^,]*\)\(.*\)\("lastName":[^,]*\)\(.*\)\("email":[^,]*\)\(.*\)\("username":[^,]*\)\(.*\)/\2,\4,\6,\8/g' | grep username`
for user in $userdetails
do
firstName=`echo $user | sed 's/,/\n/g' | grep firstName | sed 's/.*:"\([^"]*\).*/\1/g'`
lastName=`echo $user | sed 's/,/\n/g' | grep lastName | sed 's/.*:"\([^"]*\).*/\1/g'`
email=`echo $user | sed 's/,/\n/g' | grep email | sed 's/.*:"\([^"]*\).*/\1/g'`
username=`echo $user | sed 's/,/\n/g' | grep username | sed 's/.*:"\([^"]*\).*/\1/g'`
curl -k -X POST "https://haxsne09/tron/api/v1/users" -H "accept: application/json" -H "Authorization: Bearer =${TOKEN}" -H "Content-Type: application/x-www-form-urlencoded" -d "first_name=${firstName}\&last_name=${lastName}\&email=${email}\&password=Tata123^\&username=${username}\&is_active=true"
echo $RESPONSE
done
I am getting ths error:
{"Error":"bpapigw-300 Cannot authorize access to resource: Could not authorize path for user identifier: Failed to get Roles for identifier: REST operation failed 0 times: '[GET /api/v1/current-user][401] currentUserListUnauthorized \u0026{Detail:Invalid token}'. This user is unauthenticated?"}
Do I need to add any syntax before executing curl -k -X POST?
What I see is that -H "Authorization: Bearer =${TOKEN}" contains an = sign which shouldn't be there...
It should be: -H "Authorization: Bearer ${TOKEN}"
More, in a command you use /tmp/curloutput.txt file, which is never created by your script...
The Authorization header you are using is not working. Maybe the syntax is not Bearer =aAbBcCdDeEfF0123456 but something else for the server running on haxsne09, maybe without the = like #MarcoS suggests.
Alternatively, your grep command may be returning one too many characters (a rogue quote maybe).
I rewrote your code below to be more readable. You will notice that I:
Changed your matching groups in sed to capture only the needed parts and put them in variables using read. I also used the -E flag to avoid having to use \( and \)
Removed the useless for loops
Quoted all variable expansions properly
Added some line breaks for readability
Removed some temporary files and associated useless uses of cat
Here is the updated script:
#!/bin/bash
curl -k -H 'Content-Type:application/json' -d \
'{"username":"admin","password":"adminpw", "tenant":"master"}' \
https://localhost/tron/api/v1/tokens > /tmp/token.data
token=$(grep -Po '{"token":"\K[^ ]...................' /tmp/token.data)
IFS=, read -r firstName lastName email username < <(
</tmp/curloutput.txt sed 's/{"clientInactivityTime"/\n&/' |
sed -nE 's/.*."firstName":"([^"]*)".*"lastName":"([^"]*)").*"email":"([^"]*).*"username":"([^"]*)".*/\1,\2,\3,\4/p'
)
curl -k -X POST 'https://haxsne09/tron/api/v1/users' -H 'accept: application/json' \
-H "Authorization: Bearer $token" -H "Content-Type: application/x-www-form-urlencoded" -d \
"first_name=$firstName&last_name=$lastName&email=$email&password=Tata123^&username=$username&is_active=true"
echo

passing values with spaces in curl command using POST

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

Resources