supress cat output in following cmd in shell script - linux

curl=`-c cat <<EOS
curl -s https://api.openai.com/v1/completions
-H 'Content-Type: application/json'
-H "Authorization: Bearer foo"
-d '{
"model": "text-davinci-003",
"prompt": "$1",
"max_tokens": 4000,
"temperature": $2
}'
--insecure | jq '.choices[]'
EOS`
eval ${curl} | tee $newFileName

There is no need for command substitution and eval. They only make the things more complicated than they need to be.
I suspect that you used command substitution to get the expanded the values of $1 and $2 in the JSON but this is not the right way to do it. If $1 contains " the generated JSON becomes invalid. The same if $2 is not a number.
The code is even vulnerable to data injection. If $1 contains the value blah", "model": "foo and the value of $2 is 0, the argument passed to -d becomes:
{ "model": "text-davinci-003", "prompt": "blah", "model": "foo", "max_tokens": 4000, "temperature": 0 }
It is not valid JSON (it contains the key model twice) but most JSON parsers accept it and they usually use the last value assigned to the key (probably because they do not check for key uniqueness).
This makes the API handle this input object:
{ prompt": "blah", "model": "foo", "max_tokens": 4000, "temperature": 0 }
It is not easy to remove the vulnerability using what the shell script offers. You can attempt to replace " with \" but this leads to more problems (and there must be escaped many characters, anyway).
The easiest solution for this is to use jq or other JSON manipulating tool.
Using jq, the code would be like this:
# Generate the data object using `jq`...
# ...and store it into a separate variable for readability
DATA=$(jq -n -c --arg prompt "$1" --arg temp "$2" '{
model: "text-davinci-003",
prompt: $prompt,
max_tokens: 4000,
temperature: $temp
}')
curl -s \
https://api.openai.com/v1/completions \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer foo" \
-d "$DATA" \
--insecure |
jq '.choices[]' |
tee "$newFileName"

Related

bash script variable in curl

bash get-token.sh | grep x-subject-token | awk '{print $2}' >> token.txt
token=`cat token.txt`
echo $token this is true
data=`curl -s -H "X-Auth-Token: ${token}" -X GET "https://url"`
echo $token = correct token but $data is invalid.
When I write the token in curl and run it manually I get the correct data.
How can I use this token in my script?

Bash shell script to find Robots meta tag value

I've found this bash script to check status of URLs from text file and print the destination URL when having redirections :
#!/bin/bash
while read url
do
dt=$(date '+%H:%M:%S');
urlstatus=$(curl -kH 'Cache-Control: no-cache' -o /dev/null --silent --head --write-out '%{http_code} %{redirect_url}' "$url" )
echo "$url $urlstatus $dt" >> urlstatus.txt
done < $1
I'm not that good in bash : I'd like to add - for each url - the value of its Robots meta tag (if is exists)
Actually I'd really suggest a DOM parser (e.g. Nokogiri, hxselect, etc.),
but you can do this for instance (Handles lines starting with <meta and "extracts" the value of the robots' attribute content):
curl -s "$url" | sed -n '/\<meta/s/\<meta[[:space:]][[:space:]]*name="*robots"*[[:space:]][[:space:]]*content="*\([^"]*\)"*\>/\1/p'
This will print the value of the attribute or the empty string if not available.
Do you need a pure Bash solution? Or do you have sed?
You can add a line to extract the meta header for robots from the source code of the page and modify the line with echo to show its value:
#!/bin/bash
while read url
do
dt=$(date '+%H:%M:%S');
urlstatus=$(curl -kH 'Cache-Control: no-cache' -o /dev/null --silent --head --write-out '%{http_code} %{redirect_url}' "$url" )
metarobotsheader=$(curl -kH 'Cache-Control: no-cache' --silent "$url" | grep -P -i "<meta.+robots" )
echo "$url $urlstatus $dt $metarobotsheader" >> urlstatus.txt
done < $1
This example records the original line with the meta header for robots.
If you want to put a mark "-" when the page has no meta header for robots, you can change the metarobotsheader line, and put this one:
metarobotsheader=$(curl -kH 'Cache-Control: no-cache' --silent "$url" | grep -P -i "<meta.+robots" || echo "-")
If you want to extract the exact value of the attribute, you can change that line:
metarobotsheader="$(curl -kH 'Cache-Control: no-cache' --silent "$url" | grep -P -i "<meta.+robots" | perl -e '$line = <STDIN>; if ( $line =~ m#content=[\x27"]?(\w+)[\x27"]?#i) { print "$1"; } else {print "no_meta_robots";}')"
When the URL doesn't contain any meta header for robots, it will show no_meta_robots.

How to save the response body from cURL in a file when executing the command in a loop in a bash script?

I've created a cURL bash script in which I want to save the response body into a file called output.log, but when I open the file output.log it looks like this:
Here is my bash script:
#!/bin/bash
SECRET_KEY='helloWorld'
FILE_NAME='sma.txt'
function save_log()
{
printf '%s\n' \
"Header Code : $1" \
"Executed at : $(date)" \
"Response Body : $2" \
'==========================================================\n' > output.log
}
while IFS= read -r line;
do
HTTP_RESPONSE=$(curl -I -L -s -w "HTTPSTATUS:%{http_code}\\n" -H "X-Gitlab-Event: Push Hook" -H 'X-Gitlab-Token: '$SECRET_KEY --insecure $line 2>&1)
HTTP_STATUS=$(echo $HTTP_RESPONSE | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
save_log $HTTP_STATUS $HTTP_RESPONSE
done < $FILE_NAME
Can anyone help me get my desired output in my output.log?
From the Curl documentation:
-I, --head Show document info only
Removing the -I or replace it with -i should solve your problem

How can I use an argument in a string in a bash function

I try:
ctests() {
curl -X POST \
http://route.to.host/cucumber/execute-tests \
-H 'Authorization: Basic xxxxxxxxxxxxxxxxxxxxx' \
-H 'Content-Type: application/json' \
-H 'cache-control: no-cache' \
-d '{ "text": "cucumber! alltests products=$1" }'
}
And want to call this like
> ctests someproduct
But $1 wont resolve. I tried ${1}, but its the same.
Is there a nice solution for this?
the $1 doesn't resolve because you are using single-ticks ' which prohibit variable resolution.
use double-ticks (") instead (you'll have to escape the double-quotes inside the double-quotes; or use single-quotes within the double-quotes; depending on your context)
ctests() {
curl -X POST \
http://route.to.host/cucumber/execute-tests \
-H 'Authorization: Basic xxxxxxxxxxxxxxxxxxxxx' \
-H 'Content-Type: application/json' \
-H 'cache-control: no-cache' \
-d "{ \"text\": \"cucumber! alltests products=$1\" }"
}
quoting bash(1):
QUOTING
[...]
Enclosing characters in single quotes preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.
Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $ [...]

Bash cUrl response converted to string - won't match 'identical' string in string comparison

while [[ "$(curl -X GET -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" "https://api.digitalocean.com/v2/droplets/$NEW_ID" | jq '.droplet.status')" != "active" ]]; do
echo "$(curl -X GET -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" "https://api.digitalocean.com/v2/droplets/$NEW_ID" | jq '.droplet.status')"
echo "try again"
sleep 30s
done
The echo command outputs "active" appropriately (once the Droplet is active), but the while statement always fails.
After looking at other questions on SO about bash string comparisons I've tried quotation marks/no quotation marks around each side of the comparison operator and using * to match for possible newlines but the problem persists.
In an attempt to get exactly what is getting echo'd I piped the output to od.
This is what I got:
0000000 " a c t i v e " \n 0000011
I can see the newline after the string but "active"*, "active*", active*, and " a c t i v e "*(I was getting desperate here) did not successfully match when they should have. What am I missing?
jq without -r will be returning not active but "active", since its output is escaped as JSON data. However, in your comparison, the quotes on the right-hand side are syntactic -- parsed as shell syntax, not data -- so the shell is comparing the output of your pipeline to active, a string which doesn't contain any quotes.
Two approaches come immediately to mind:
Include literal rather than syntactic quotes on the right-hand side of the comparison:
[[ $(curl ... | jq ...) = '"active"' ]] # option 1: outer single quotes
[[ $(curl ... | jq ...) = \"active\" ]] # option 2: escape the double quotes
Use the -r argument to jq to emit raw strings, thereby suppressing quotes in its output:
[[ $(curl ... | jq -r ...) = active ]]

Resources