curl | jq: parse error: Invalid numeric literal at line 2, column 0 - bash

I have a simple bash file as below
#!/bin/bash
net=$(curl -s -H "Content-Type: application/json" -H "X-Auth-Token: $token" -d '{"network": {"name": "net1"}}' http://10.1.10.146:18090/network/v2.0/networks 2>&1 | awk '/id/{print $1}' | jq -r .network.id)
echo $net
Running this file gives me an error as below
parse error: Invalid numeric literal at line 2, column 0
tried making the changes according to these links
https://unix.stackexchange.com/questions/354943/setting-jq-output-to-a-bash-variable
Working with Bash and cURL
but nothing helped me, unable to figure out where i am going wrong. let me know the reason for the error and possible changes.
The curl output for the command
curl -s -H "Content-Type: application/json" -H "X-Auth-Token: $token" -d '{"network": {"name": "net1"}}' http://10.1.10.146:18090/network/v2.0/networks
output:
{"network":{"status":"ACTIVE","router:external":false,"availability_zone_hints":[],"availability_zones":[],"description":"","subnets":[],"shared":false,"tenant_id":"d0e75710820c401db3291ac6278f326f","created_at":"2018-05-15T07:37:42Z","tags":[],"ipv6_address_scope":null,"mtu":1450,"updated_at":"2018-05-15T07:37:42Z","admin_state_up":true,"revision_number":2,"ipv4_address_scope":null,"is_default":false,"port_security_enabled":true,"project_id":"d0e75710820c401db3291ac6278f326f","id":"1548df56-a35b-4232-9550-54a3c2266d60","name":"net1"}}
the idea is to get only the id from the output and store into a bash variable, to get the id i used the below command
curl -s -H "Content-Type: application/json" -H "X-Auth-Token: $token" -d '{"network": {"name": "net1"}}' http://10.1.10.146:18090/network/v2.0/networks 2>&1 | awk '/id/{print $1}' | jq -r .network.id
output:
be831582-90c1-499c-875f-9c0b0d1969a6
I have also tried removing the awk and parsing the curl json response, the same error is showing up.
thanks in advance.

The "parse error" message appears because the 2>&1 redirects any STDERR message into jq, which cannot parse it. Compare the output from these commands:
> curl http://no.such.host/network/v2.0/networks 2>&1
curl: (6) Could not resolve host: no.such.host
> curl http://no.such.host/network/v2.0/networks 2>&1 | jq '.'
parse error: Invalid numeric literal at line 1, column 4
Here are some ideas:
Separate all of the piped commands into separate commands.
Try adding set -x near the top of the script to "debug" all of the
commands.
Remove the 2>&1 because it is NOT helping you!
Add error handling to the separate commands.
We could help more if you provided the curl output. (We do not have HTTP access to the 10.1.10.146 host.)

Related

Escaping multiple layers of mixed quotes for a curl command executed inside a bash script

I have the following bash script that uses its arguments to hit a RESTful web service (via curl) and prints out both the curl request made as well as the response:
#! /bin/bash
# arguments:
# $1 - username
# $2 - password
#
# outputs:
# if the script exits with a non-zero status then something went wrong
# verify that we have all 6 required arguments and fail otherwise
if [ "$#" -ne 2 ]; then
echo "Required arguments not provided"
exit 1
fi
# set the script arguments to meaningful variable names
username=$1
password=$2
# login and fetch a valid auth token
req='curl -k -i -H "Content-Type: application/json" -X POST -d ''{"username":"$username","password":"$password"}'' https://somerepo.example.com/flimflam'
resp=$(curl -k -i -H "Content-Type: application/json" -X POST -d ''{"username":"$username","password":"$password"}'' https://somerepo.example.com/flimflam)
# echo the request for troubleshooting
echo "req = $req"
if [ -z "$resp" ]; then
echo "Login failed; unable to parse response"
exit 1
fi
echo "resp = $resp"
When I run this I get:
$ sh myscript.sh myUser 12345#45678
curl: (3) Port number ended with '"'
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0curl: (6) Could not resolve host: 12345#45678"
100 1107 100 1093 100 14 2849 36 --:--:-- --:--:-- --:--:-- 2849
req = curl -k -i -H "Content-Type: application/json" -X POST -d {"username":"$username","password":"$password"} https://somerepo.example.com/flimflam
resp = HTTP/1.1 400 Bad Request...(rest omitted for brevity)
Obviously, I'm not escaping the various layers of single- and double-quotes inside the curl statement correctly, as is indicated by outputs like:
curl: (6) Could not resolve host: 12345#45678"
and:
req = curl -k -i -H "Content-Type: application/json" -X POST -d {"username":"$username","password":"$password"} https://somerepo.example.com/flimflam
where the username/password variables are not parsing.
In reality my script takes a lot more than 2 arguments, which is why I'm changing them to have meaningful variable names (such as $username instead of $1) so its more understandable and readable.
Can anyone spot where I'm going awry? Thanks in advance!
Update
I tried the suggestion which turns the req into:
curl -k -i -H 'Content-Type: application/json' -X POST -d "{'username':'myUser','password':'12345#45678'}" https://somerepo.example.com/flimflam
However this is still an illegal curl command and instead needs to be:
curl -k -i -H 'Content-Type: application/json' -X POST -d '{"username":"myUser","password":"12345#45678"}' https://somerepo.example.com/flimflam
First, as I said in a comment, storing commands in variables just doesn't work right. Variables are for data, not executable code. Second, you have two levels of quoting here: quotes that're part of the shell syntax (which are parsed, applied, and removed by the shell before the arguments are passed to `curl), and quotes that're part of the JSON syntax.
But the second problem is actually worse than that, because simply embedding an arbitrary string into some JSON may result in JSON syntax errors if the string contains characters that're part of JSON syntax. Which passwords are likely to do. To get the password (and username for that matter) embedded correctly in your JSON, use a tool that understands JSON syntax, like jq:
userinfo=$(jq -n -c --arg u "$username" --arg p "$password" '{"username":$u,"password":$p}')
Explanation: this uses --arg to set the jq variables u and p to the shell variables $username and $password respectively (and the double-quotes around the shell variables will keep the shell from doing anything silly to the values), and creates a JSON snippet with them embedded. jq will automatically add appropriate quoting/escaping/whatever is needed.
Then, to use it with curl, use something like this:
resp=$(curl -k -i -H "Content-Type: application/json" -X POST -d "$userinfo" https://somerepo.example.com/flimflam)
Again, the double-quotes around $userinfo keep the shell from doing anything silly. You should almost always put double-quotes around variables references in the shell.
Note that I never used the req variable to store the command. If you need to print the command (or its equivalent), use something like this:
printf '%q ' curl -k -i -H "Content-Type: application/json" -X POST -d "$userinfo" https://somerepo.example.com/flimflam
echo
The %q format specifier tells the shell to add appropriate quoting/escaping so that you could run the result as a shell command, and it'd work properly. (And the echo is there because printf doesn't automatically add a newline at the end of its output.)
try changing this:
req='curl -k -i -H "Content-Type: application/json" -X POST -d ''{"username":"$username","password":"$password"}'' https://somerepo.example.com/flimflam'
to this
req="curl -k -i -H 'Content-Type: application/json' -X POST -d \"{'username':'$username','password':'$password'}\" https://somerepo.example.com/flimflam"
and similarly for the resp
ah those pesky "curly" thingies...
how 'bout...
req="curl -k -i -H 'Content-Type: application/json' -X POST -d '{\"username\":\"$username\",\"password\":\"$password\"}' https://somerepo.example.com/flimflam"
This needs even more escaping:
With:
resp=$(curl -k -i -H "Content-Type: application/json" -X POST -d "{\"username\":\"$username\",\"password\":\"$password\"}" https://somerepo.example.com/flimflam)
In bash, the variables are still expanded when they're inside single quotes that are inside double quotes.
And you'll need the \" double quotes in the payload as per the JSON definition.
EDIT: I rerun the curl through a HTTP proxy and corrected the script line (see above, removed the single quotes). Results (in raw HTTP) are now:
POST /flimflam HTTP/1.1
Host: somerepo.example.com
User-Agent: curl/7.68.0
Accept: */*
Content-Type: application/json
Content-Length: 44
Connection: close
{"username":"user","password":"12345#abcde"}
(which should be fine)

Discard modification content of variable in curl command

I want to create a script to test some web service.
Here the base of my script:
XAuthToken=$(curl -i -s -X POST -H "Content-Type: application/json" -d '{"login": "apitest","password": "apitest"}' http://url:8080/rest-api-web/api/admin | grep -i '^X-Auth-Token:' | sed 's/^[Xx]-Auth-Token: //g')
curl -X GET --header 'Accept: application/json' http://url:8080/rest-api-web/api/admin/delivery_companies?token=$XAuthToken
Result of the first command is:
eyJjdHkiOiJKV1QiLCJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.KmhGpDsor4I7VVPfN1gENzcQb8Yll-wewTRorFu6qfUeaIjKNIAm5lkTkPIpuuOuSpT2U4RgXz9NhwLrYIheW45Du6LnjsyUEjjWGKB4jIW0CMO-79f_-O80pQMq0P09uwmZaqUOmARPjs8UvQYQcuCHhcHd2dB-4WMnfUl-J6USI2LdI-CeOtWDDMw5YEKHGrgnHRzxgUePNWVs-Vc-BR-tXnpkEjIfKmrYy19QUfnwxcWLEWgKisrJw5d7sz7ihfzSueyrh188GiGHTeqqiNiSIkIH8UEyZfW-5BH1Y856IkXlyUaC3abHBRYHuz-O30KwvCKhtCKkaTPVR-uqNw.89jCGtawkkWuyRtq.pQmYHaWZN-XOlbvUthjK76ewqIGd1TBF0Pt7EbA2bDnxsTsXQXyot495-u4Rsvm8-y-rscAZUZFacebMvcvZ-LhUH-jHZH6L5PALY7uvGj_SGApg_Hu8D-adNDlI1rVxNcnHjpOLuOeBdUzKAznbOytquzQNODsjP877IbLTDkWTTj0IC0OWfDu-e4rYxpf2jzZBuEbnRcC8DuvbplNB2tnbRxMjpqnKjicLY9DpYdV1T-tKUt5-sI0Bhlk6tUJ0e28g1McQReUT-sB8pO3vQreEAEsVQlysVq9rC6LiW6RNRHAZP7d6PiuhLS_D_DKVmi85junbMVimYqbvszaJ.1b7PKcZfWmVmNBbTg54nFA
But the second curl in the script, this error occurs: curl: (3) Illegal characters found in URL
And after a check, the content of "XAuthToken" is changed.
Can you help me to escape the character modification?
Thanks you for your comment.
As you can see in the following output, both declare are egal. But the oupt of the command with set -x activate, the Authtoken is changed.
Here the result :
First delare -p :
eyJjdHkiOiJKV1QiLCJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.BTri-oCE-DHYx7UZo8Kib_RoO5bx9lv7BRhEYv2yizyX2n8cwzWWhMPPA-0rDHumaESgc0LmT71NLIJEyZkwN-pXH2MgYdo2vTQhnVdFOL7rZq1rHSJvUxPvhJTbAkabnTNz-s1-Vc7WNQXmWEkngaCISdnsFQU12YfJfzhgwGZi9OOf5gmHnNtXaAxTOrDcjl84s1QI0tY5HIQ_3MEB18V4UMfcR5SSk4v_5K2yVZk-AUys3bPDw1GEZkr3rypxytNZ6wCyrOEXtGh1s8w3fFQziNnnOcgwaSkpDOdhhJWUfgN3R1Cr5tnD77vG01SZw7k844LZxiK8HXhQUj3_sQ.KAhqX5YkZPXDtVlI.d-TxeoNsuemKRfDpQe9khaYym1KACAXS9MhYfGtoIwhPomZ85hKvILeT8jXxBgIw6r4XUpgSSVNtjUzA7A-_hpu0i7ffd-Ap-YDohbCfJfCYffVO557tCuIhVvybT4qQ5EgjsX8h1V5NqIyDVIPAiDIc6hnrxWsjbwE3dmfMLxqmDLXLiYTaCUMvsxtweo-fsdIymK-REuy4DdPk8YsaITpfYj57Ee5ZphZiNfvUPixkLAXj97ycEnXbP2d6q6Aw1rYVIrE3ijGYIgW618kMs5PBvjWe"yh-76mOq9_0QnKzblZWJytHsM6DM8kbkGRHhwFhQSvjq9HUQVNmmKCI.Q4rq7-uzPW3Yewc8Wyl01A
Resut of "set -x' :
eyJjdHkiOiJKV1QiLCJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.BTri-oCE-DHYx7UZo8Kib_RoO5bx9lv7BRhEYv2yizyX2n8cwzWWhMPPA-0rDHumaESgc0LmT71NLIJEyZkwN-pXH2MgYdo2vTQhnVdFOL7rZq1rHSJvUxPvhJTbAkabnTNz-s1-Vc7WNQXmWEkngaCISdnsFQU12YfJfzhgwGZi9OOf5gmHnNtXaAxTOrDcjl84s1QI0tY5HIQ_3MEB18V4UMfcR5SSk4v_5K2yVZk-AUys3bPDw1GEZkr3rypxytNZ6wCyrOEXtGh1s8w3fFQziNnnOcgwaSkpDOdhhJWUfgN3R1Cr5tnD77vG01SZw7k844LZxiK8HXhQUj3_sQ.KAhqX5YkZPXDtVlI.d-TxeoNsuemKRfDpQe9khaYym1KACAXS9MhYfGtoIwhPomZ85hKvILeT8jXxBgIw6r4XUpgSSVNtjUzA7A-_hpu0i7ffd-Ap-YDohbCfJfCYffVO557tCuIhVvybT4qQ5EgjsX8h1V5NqIyDVIPAiDIc6hnrxWsjbwE3dmfMLxqmDLXLiYTaCUMvsxtweo-fsdIymK-REuy4DdPk8YsaITpfYj57Ee5ZphZiNfvUPixkLAXj97ycEnXbP2d6q6Aw1rYVIrE3ijGYIgW618kMs5PBvjWeTyh-76mOq9_0QnKzblZWJyt'sM6DM8kbkGRHhwFhQSvjq9HUQVNmmKCI.Q4rq7-uzPW3Yewc8Wyl01A
Second declare :
eyJjdHkiOiJKV1QiLCJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.BTri-oCE-DHYx7UZo8Kib_RoO5bx9lv7BRhEYv2yizyX2n8cwzWWhMPPA-0rDHumaESgc0LmT71NLIJEyZkwN-pXH2MgYdo2vTQhnVdFOL7rZq1rHSJvUxPvhJTbAkabnTNz-s1-Vc7WNQXmWEkngaCISdnsFQU12YfJfzhgwGZi9OOf5gmHnNtXaAxTOrDcjl84s1QI0tY5HIQ_3MEB18V4UMfcR5SSk4v_5K2yVZk-AUys3bPDw1GEZkr3rypxytNZ6wCyrOEXtGh1s8w3fFQziNnnOcgwaSkpDOdhhJWUfgN3R1Cr5tnD77vG01SZw7k844LZxiK8HXhQUj3_sQ.KAhqX5YkZPXDtVlI.d-TxeoNsuemKRfDpQe9khaYym1KACAXS9MhYfGtoIwhPomZ85hKvILeT8jXxBgIw6r4XUpgSSVNtjUzA7A-_hpu0i7ffd-Ap-YDohbCfJfCYffVO557tCuIhVvybT4qQ5EgjsX8h1V5NqIyDVIPAiDIc6hnrxWsjbwE3dmfMLxqmDLXLiYTaCUMvsxtweo-fsdIymK-REuy4DdPk8YsaITpfYj57Ee5ZphZiNfvUPixkLAXj97ycEnXbP2d6q6Aw1rYVIrE3ijGYIgW618kMs5PBvjWe"yh-76mOq9_0QnKzblZWJytHsM6DM8kbkGRHhwFhQSvjq9HUQVNmmKCI.Q4rq7-uzPW3Yewc8Wyl01A

For loop from file with multiple columns-BASH

i have following text file (output.txt)
TECH-746 TECH 10400
TECH-747 TECH 10400
i need to read all columns and pass it to 3 variables and then submit it to curl command. While read simple won't work with curl (don't know why) so i need to use for loop (it works with curl), can i use one for loop or need to nest multiple ones
for project in `cat output.txt`; do
echo $project
curl -D- -u user:pass -X POST --data "{\"fields\":{\"project\":{\"key\":\"TECH\"},\"parent\":{\"key\":\"$project\"},\"summary\":\"test",\"description\":\"test.\",\"issuetype\":{\"name\":\"Sub-task\"}}}" -H "Content-Type:application/json" --silent https://jira.company.com/rest/api/latest/issue/ >/dev/null
code above works, so i just want to "extend" to to include all other columns in file
while read can pull a line into distinct variables.
while read project col2 col3
do
curl -D- -u user:pass -X POST --data "{\"fields\":{\"project\":{\"key\":\"TECH\"},\"parent\":{\"key\":\"$project\"},\"summary\":\"test",\"description\":\"test.\",\"issuetype\":{\"name\":\"Sub-task\"}}}" -H "Content-Type:application/json" --silent https://jira.company.com/rest/api/latest/issue/ >/dev/null
done < sourcefile.txt
EDIT:
The curl command also misses escaping one quote, compare the two lines below, the first one is the original, the second one is the one I've corrected.
curl -D- -u user:pass -X POST --data "{\"fields\":{\"project\":{\"key\":\"TECH\"},\"parent\":{\"key\":\"$project\"},\"summary\":\"test",\"description\":\"test.\",\"issuetype\":{\"name\":\"Sub-task\"}}}" -H "Content-Type:application/json" --silent https://jira.company.com/rest/api/latest/issue/ >/dev/null
curl -D- -u user:pass -X POST --data "{\"fields\":{\"project\":{\"key\":\"TECH\"},\"parent\":{\"key\":\"$project\"},\"summary\":\"test\",\"description\":\"test.\",\"issuetype\":{\"name\":\"Sub-task\"}}}" -H "Content-Type:application/json" --silent https://jira.company.com/rest/api/latest/issue/ >/dev/null

How to verify a curl request in bash script?

I have a curl request like this :
curl -s -u $user:$password -X GET -H "Content-Type: application/json" $url
Which returns a json as response. So I will parse the response using jq to get some specific data. Like this :
curl -s -u $user:$password -X GET -H "Content-Type: application/json" $url | jq '<expression>'
Now if the curl request fails then obviously the parsing operation throws ugly error. I want to avoid this. How to store the response first and then later parse it if the request is successful. I don't want to display the json whole response. Also if I add -w "%{http_code}" in my request it appends the status code with the JSON response which messes up the parsing. How to solve this ? I basically want to first check if the curl request is successful or not then get the JSON response and parse it.I also want to get the status code, so that if it fails I can display the status code. But status code is now messing up with json response.
You can combine the --write and --fail options:
# separating the (verbose) curl options into an array for readability
curl_args=(
--write "%{http_code}\n"
--fail
--silent
--user "$user:$password"
--request GET
--header "Content-Type: application/json"
)
if ! output=$(curl "${curl_args[#]}" "$url"); then
echo "Failure: code=$output"
else
# remove the "http_code" line from the end of the output, and parse it
sed '$d' <<<"$output" | jq '...'
fi
Also note: quote your variables!
I found glenn jackman's answer good, but a bit confusingly written, so I rewrote it, and altered it so I can use it as a safer alternative to curl | jq.
#!/bin/bash
# call this with normal curl arguments, especially url argument, e.g.
# safecurl.sh "http://example.com:8080/something/"
# separating the (verbose) curl options into an array for readability
curl_args=(
-H 'Accept:application/json'
-H 'Content-Type:application/json'
--write '\n%{http_code}\n'
--fail
--silent
)
echo "${curl_args[#]}"
# prepend some arguments, but pass on whatever arguments this script was called with
output=$(curl "${curl_args[#]}" "$#")
return_code=$?
if [ 0 -eq $return_code ]; then
# remove the "http_code" line from the end of the output, and parse it
echo "$output" | sed '$d' | jq .
else
# echo to stderr so further piping to jq will process empty output
>&2 echo "Failure: code=$output"
fi
Note: This code does not test for services that ignore the requested content type and respond with HTML. You'd need to test for grep -l '</html>' for that.

< was unexpected at this time. from curl command line when posting input data as an xml to rest service

when i post a raw string as an input to JSON REST Service call it is executing ex:
curl -d "{\"input1\": \"as\", \"input2\": \"ad\"}" -i -X POST -H "Content-Type:application/json" http://localhost/rtygies/Service1.svc/rest/receivedata1
But when i am posting as an xml as input it is giveng error as below:
curl -d "{\"input1\": \"<xml></xml>\", \"input2\": \"<xml></xml>\"}" -i -X POST -H "Content-Type:application/json" http://localhost/rtygies/Service1.svc/rest/receivedata1
Error: < was unexpected at this time
I am using curl in windows.
can any one say how to post xml as a string input to Rest service in JSON format from curl
Actually, I don't know what is the case,
but I got an error said < is unexpected this time
when I tried the following command (on windows):
curl -u admin:password -XPOST -H 'Content-type: text/xml' -d '<namespace><prefix>newWorkspace</prefix><uri>http://geoserver.org</uri></namespace>' http://localhost:8080/geoserver/rest/namespaces
Then I changed the single quote into double quotes and it worked.
Redirection symbols can be escaped by "
Try using
curl -d "{\"input1\": \""<xml></xml>"\", \"input2\": \""<xml></xml>"\"}" -i -X POST -H "Content-Type:application/json" http://localhost/rtygies/Service1.svc/rest/receivedata1
I had no luck with double-quotes, however escaping < and > with ^ worked for me.
So your curl becomes..
curl -d "{\"input1\": \"^<xml^>^</xml^>\", \"input2\": \"^<xml^>^</xml^>\"}" -i -X POST -H "Content-Type:application/json" http://localhost/rtygies/Service1.svc/rest/receivedata1

Resources