How to curl a post request with a bash array? - bash

So I am trying to create a script that will send data to a slack hook app. This is my current code:
DATA="[app_code: app_code | error invalid _id: alsdjasdlkj];[app_code: app_code | error invalid _type: 1a1]"
IFS=';' ;read -ra errors <<< "$DATA"
unset IFS
cmd=$(curl -X POST -H 'Content-type: application/json' --data '{"text": "'"${errors[#]}"'" }' hook_url)
echo $cmd
The issue I am having is that I want to send an array list of errors as I will never know how many there could be at any given time. when I run this bash command this is the error I get:
curl: (3) bad range in URL position 2:
[app_code: app_code | error invalid _type: 1a1]" }
So how can I fix the code to send an array as a curl command for the data field? And if that's not possible is there a workaround for this? I need the text to show up on the slack channel as follows:
Total errors: 2
[app_code: app_code | error invalid _id: alsdjasdlkj]
[app_code: app_code | error invalid _type: 1a1]
Any help is appreciated. Thanks!

Related

Supply binary content inside a JSON string via curl

I'm trying to use the Yandex.Cloud function API from bash and cURL.
In order to do that, I'm composing a JSON like this:
#Make header
IAM_TOKEN="myToken"
HEADER="Authorization: Bearer ${IAM_TOKEN}"
#Make data JSON
DATA=""
for ELEMENT in \
"'"\
'{"runtime":"dotnetcore31", "entrypoint": "Function.Handler",'\
'"resources":{"memory":"134217728"}, "content": "PLACEHOLDERFORCONTENT",'\
'"ServiceAccountId":"accId", '\
'"function_id": "funcId"}'\
"'"; do
DATA+="${ELEMENT}"
done
Then, I need to supply content of the deployment package inside JSON, as API suggests:
In my case, it is a zip archive with function code. So, I read the file as bytes and inject the result into the JSON string. And send the request.
#Read file content
FILE_LOC="/Users/Constantine/Downloads/archiveName.zip"
FILE_BYTES=`(xxd -b ${FILE_LOC}) | base64`
#Inject content into JSON
DATA=${DATA/PLACEHOLDERFORCONTENT/$FILE_BYTES}
#Send the request
eval "$(echo curl -H \"$HEADER\" --data-binary $DATA https://serverless-functions.api.cloud.yandex.net/functions/v1/versions)"
Here, I'm getting the -bash: /usr/bin/curl: Argument list too long error. I suspect this happens because cURL interprets the binary content as the filename to read, but I'm not sure how to resolve this.
How can I supply binary content from a file into a JSON string?
You are sending the request using a cURL call under bash. And the shell have a maximum line length that you are largely surpassing.
Your easiest workaround is to save your JSON data to a file and supply cURL with a pointer to this file, so that the line length remains contained:
#Make data JSON
data_file="data.json"
> "${data_file}"
for ELEMENT in \
"'"\
'{"runtime":"dotnetcore31", "entrypoint": "Function.Handler",'\
'"resources":{"memory":"134217728"}, "content": "PLACEHOLDERFORCONTENT",'\
'"ServiceAccountId":"accId", '\
'"function_id": "funcId"}'\
"'"; do
echo "${ELEMENT}"
done >> "${data_file}"
#Read file content
FILE_LOC="/Users/Constantine/Downloads/archiveName.zip"
FILE_BYTES=$(xxd -b "${FILE_LOC}" | base64)
#Inject content into JSON
sed -i "s/PLACEHOLDERFORCONTENT/${FILE_BYTES}/" "${data_file}"
#Send the request
eval "$(echo curl -H \"$HEADER\" --data-binary "#${data_file}" https://serverless-functions.api.cloud.yandex.net/functions/v1/versions)"
Besides that, your code seems quite complex for the duty. You could simplify it a little. Avoid loops, create the file in one go and avoid eval:
#Make data JSON
data_file="data.json"
FILE_LOC="/Users/Constantine/Downloads/archiveName.zip"
cat <<-EOF > "${data_file}"
{
"runtime": "dotnetcore31",
"entrypoint": "Function.Handler",
"resources": {
"memory": "134217728"
},
"content": "$(xxd -b "${FILE_LOC}" | base64)",
"ServiceAccountId": "accId",
"function_id": "funcId"
}
EOF
#Send the request
curl -H "$HEADER" --data-binary "#${data_file}" https://serverless-functions.api.cloud.yandex.net/functions/v1/versions

Why does curl see several parameters? [duplicate]

This question already has answers here:
When to wrap quotes around a shell variable?
(5 answers)
Closed last year.
I want to send a message to a slack app in a script:
...
declare -a models=("TR10"
"TR100"
"TR1000")
for i in "${models[#]}"
do
#Send Message
if [ $use_slack_app ]
then
message="Starting model $i ($c of $lenght)!"
data=''\''{"text":"'"$message"'"}'''\'
echo $data
curl -X POST -H 'Content-type: application/json' --data $data $slack_app_url
echo "curl -X POST -H 'Content-type: application/json' --data $data $slack_app_url"
fi
#Counter
((c=c+1))
done
...
return of echo $data:
'{"text":"Starting model TR10 (1 of 3)!"}'
curl message:
curl: (3) unmatched close brace/bracket in URL position 5:
3)!"}'
^
curl: (6) Could not resolve host: model
curl: (6) Could not resolve host: TR10
curl: (6) Could not resolve host: (1
curl: (6) Could not resolve host: of
invalid_payload
It looks like it sees the string as several parameters, but I don't understand why. If I echo the line out, and run it in the terminal it works. I don't have much experience with bash scripting, so I don't understand what the problem here is.
Quote the variable expansions to ensure values with spaces are sent as one word: "$var" vs. $var.
Get rid of the single quotes (''\') surrounding $data.
data='{"text":"'"$message"'"}'
curl -X POST -H 'Content-Type: application/json' --data "$data" "$slack_app_url"

Running Curl POST w/ JSON Payload Sequentially Against File

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

curl: argument list too long

I want to send an email with attached pdf file through the Sparkpost API with curl post.
To insert the pdf I use (my test.pdf is ~ 200KB)
"data":"'$(cat test.pdf} | base64 --wrap=0)'"
But somehow this doesn't work out showing the following error:
/usr/bin/curl: Die Argumentliste ist zu lang (original)
/usr/bin/curl: Argument list is too long
EDIT:
curl command
curl -X POST https://api.eu.sparkpost.com/api/v1/transmissions -H 'Authorization: <APIKEY>' -H 'Content-Type: application/json' -d '{
"options":{
"open_tracking":false,
"click_tracking":false,
"inline_css":false
},
"recipients":[
{
"address":{
"email":"user#domain.tld",
"name":"user"
}
}
],
"content":{
"from":{
"name":"sender",
"email":"sender#domain.tld"
},
"reply_to":"replyto#domain.tld",
"subject":"subject",
"text":"textbody",
"attachments":[
{
"name":"attachmentname.pdf",
"type":"application/pdf",
"data":"'$(cat test.pdf | base64 --wrap=0)'"
}
]
}
}'
This is coming up because you are trying to pass the entirety of the base64'd content on the command line. curl has the ability to load in data to POST from a file, which I'd recommend doing. More information can be found in the man page, but the basic format is this:
curl -X POST -d #filename.txt https://website.com/path
According to the curl manual, the -F option allows you to encode a file for base64, but limits the output to 76 characters.
Ex:
-F '=#localfile;encoder=base64'

How to use jq to fetch attribute from json

I have written a bash file to fetch an attribute value from a json. But it says data not shown. Not sure how to make jq work in my linux box. Can some one please help.
curl -v -H "Content-Type: application/json" -X GET 'URL' > myFile.json
cat myFile.json | jq '.offerVerticalMap["GROCERIES.offerPublishStatus"]'
in myFile.json the json is getting created but am unable to pull the attribute value.
please can someone look into this at the earliest?
Thanks
Your json still shows as invalid. Anyhow, I'm attaching a sample json and how to extract it through jq. Please see below:
~$ cat n1.json
[
{
"name":"sandboxserver.tar.gz.part-aa",
"hash":"010d126f8ccf199f3cd5f468a90d5ae1",
"bytes":4294967296,
"last_modified":"2018-10-10T01:32:00.069000",
"content_type":"binary/octet-stream"
},
{
"name":"sandboxserver.tar.gz.part-ab",
"hash":"49a6f22068228f51488559c096aa06ce",
"bytes":397973601,
"last_modified":"2018-10-10T01:32:22.395000",
"content_type":"binary/octet-stream"
},
{
"name":"sandboxserver.tar.gz.part-ac",
"hash":"2c5e845f46357e203214592332774f4c",
"bytes":5179281858,
"last_modified":"2018-10-11T08:20:11.566000",
"content_type":"binary/octet-stream"
}
]
And then used jq to find the names:
~$ jq -r '.[].name' n1.json
sandboxserver.tar.gz.part-aa
sandboxserver.tar.gz.part-ab
sandboxserver.tar.gz.part-ac
Let me know if this helps.

Resources