Utilizzo del curl POST con variabili definite nelle funzioni di script bash


176

Quando echo ottengo questo, che viene eseguito quando entro nel terminale

curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data '{"account":{"email":"akdgdtk@test.com","screenName":"akdgdtk","type":"NIKE","passwordSettings":{"password":"Starwars1","passwordConfirm":"Starwars1"}},"firstName":"Test","lastName":"User","middleName":"ObiWan","locale":"en_US","registrationSiteId":"520","receiveEmail":"false","dateOfBirth":"1984-12-25","mobileNumber":"9175555555","gender":"male","fuelActivationDate":"2010-10-22","postalCode":"10022","country":"US","city":"Beverton","state":"OR","bio":"This is a test user","jpFirstNameKana":"unsure","jpLastNameKana":"ofthis","height":"80","weight":"175","distanceUnit":"MILES","weightUnit":"POUNDS","heightUnit":"FT/INCHES"}' https://xxx:xxxxx@xxxx-www.xxxxx.com/xxxxx/xxxx/xxxx

Ma quando eseguito nel file di script bash, ottengo questo errore

curl: (6) Could not resolve host: application; nodename nor servname provided, or not known
curl: (6) Could not resolve host: is; nodename nor servname provided, or not known
curl: (6) Could not resolve host: a; nodename nor servname provided, or not known
curl: (6) Could not resolve host: test; nodename nor servname provided, or not known
curl: (3) [globbing] unmatched close brace/bracket at pos 158

questo è il codice nel file

curl -i \
-H '"'Accept: application/json'"' \
-H '"'Content-Type:application/json'"' \
-X POST --data "'"'{"account":{"email":"'$email'","screenName":"'$screenName'","type":"'$theType'","passwordSettings":{"password":"'$password'","passwordConfirm":"'$password'"}},"firstName":"'$firstName'","lastName":"'$lastName'","middleName":"'$middleName'","locale":"'$locale'","registrationSiteId":"'$registrationSiteId'","receiveEmail":"'$receiveEmail'","dateOfBirth":"'$dob'","mobileNumber":"'$mobileNumber'","gender":"'$gender'","fuelActivationDate":"'$fuelActivationDate'","postalCode":"'$postalCode'","country":"'$country'","city":"'$city'","state":"'$state'","bio":"'$bio'","jpFirstNameKana":"'$jpFirstNameKana'","jpLastNameKana":"'$jpLastNameKana'","height":"'$height'","weight":"'$weight'","distanceUnit":"MILES","weightUnit":"POUNDS","heightUnit":"FT/INCHES"}'"'" "https://xxx:xxxxx@xxxx-www.xxxxx.com/xxxxx/xxxx/xxxx"

Suppongo che ci sia un problema con le virgolette, ma ho giocato molto con loro e ho riscontrato errori simili. Tutte le variabili sono definite con diverse funzioni nello script reale

Risposte:


274

Non è necessario passare le virgolette che racchiudono le intestazioni personalizzate per arricciare. Inoltre, le variabili nel mezzo datadell'argomento devono essere citate.

Innanzitutto, scrivi una funzione che genera i dati di post del tuo script. Questo ti salva da ogni sorta di mal di testa riguardo alla quotazione della shell e semplifica la lettura e la manutenzione dello script piuttosto che l'alimentazione dei dati del post sulla linea di invocazione del ricciolo come nel tuo tentativo:

generate_post_data()
{
  cat <<EOF
{
  "account": {
    "email": "$email",
    "screenName": "$screenName",
    "type": "$theType",
    "passwordSettings": {
      "password": "$password",
      "passwordConfirm": "$password"
    }
  },
  "firstName": "$firstName",
  "lastName": "$lastName",
  "middleName": "$middleName",
  "locale": "$locale",
  "registrationSiteId": "$registrationSiteId",
  "receiveEmail": "$receiveEmail",
  "dateOfBirth": "$dob",
  "mobileNumber": "$mobileNumber",
  "gender": "$gender",
  "fuelActivationDate": "$fuelActivationDate",
  "postalCode": "$postalCode",
  "country": "$country",
  "city": "$city",
  "state": "$state",
  "bio": "$bio",
  "jpFirstNameKana": "$jpFirstNameKana",
  "jpLastNameKana": "$jpLastNameKana",
  "height": "$height",
  "weight": "$weight",
  "distanceUnit": "MILES",
  "weightUnit": "POUNDS",
  "heightUnit": "FT/INCHES"
}
EOF
}

È quindi facile usare quella funzione nell'invocazione del ricciolo:

curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data "$(generate_post_data)" "https://xxx:xxxxx@xxxx-www.xxxxx.com/xxxxx/xxxx/xxxx"

Detto questo, ecco alcuni chiarimenti sulle regole di quotazione della shell:

Le doppie virgolette negli -Hargomenti (come in -H "foo bar") dicono a bash di mantenere ciò che è dentro come un singolo argomento (anche se contiene spazi).

Le virgolette singole --datanell'argomento (come in --data 'foo bar') fanno lo stesso, tranne per il fatto che passano tutto il testo alla lettera (inclusi i caratteri di virgolette doppie e il simbolo del dollaro).

Per inserire una variabile nel bel mezzo di un unico testo citato, è necessario porre fine alla sola offerta, quindi concatenare con la variabile doppio citato, e ri-aprire la singola citazione di continuare il testo: 'foo bar'"$variable"'more foo'.


9
"'" $ <nome variabile> "'" ha risolto il mio problema in cui avevo bisogno di virgolette da non omettere. Grazie.
Usman,

1
Questa soluzione funziona ma penso che tu possa emettere le doppie virgolette extra che circondano la variabile. Quindi invece di questo: --data '{"account": {"email": "'" $ email "'"}}' puoi farlo: --data '{"account": {"email": " '$ email' "}} '
twistedstream

3
Non ha funzionato quando c'era uno spazio dopo il secondo EOF: EOF . Dopo averlo rimosso tutto va bene.
Klaas,

2
@dbreaux Dipende da dove si esegue il comando curl. Se il comando si trova in uno script, è sufficiente definire la funzione ovunque sopra di esso nello stesso script. Se si esegue il ricciolo direttamente dalla riga di comando, sono disponibili diverse opzioni, una delle quali è digitare la funzione in un nuovo file e quindi eseguire la riga di comando source my_new_fileper definire la funzione nell'ambiente corrente. Successivamente è possibile eseguire il comando arricciatura come indicato.
Sir Athos,

2
@slashdottir Questa è una funzione bash chiamata Here Documents. Puoi leggerlo più dettagliatamente a questo link - in particolare, controlla Esempio 19-5. C'è anche una domanda completa al riguardo qui su SO.
Sir Athos,

103

Soluzione testata con https://httpbin.org/ e script bash inline
1. Per variabili senza spazi in essa, ad es . 1:
aggiungere semplicemente 'prima e dopo $variablequando si sostituisce la stringa desiderata

for i in {1..3}; do \
  curl -X POST -H "Content-Type: application/json" -d \
    '{"number":"'$i'"}' "https://httpbin.org/post"; \
done

2. Per input con spazi:
avvolgere la variabile con ulteriori "ie "el a":

declare -a arr=("el a" "el b" "el c"); for i in "${arr[@]}"; do \
  curl -X POST -H "Content-Type: application/json" -d \
    '{"elem":"'"$i"'"}' "https://httpbin.org/post"; \
done

Wow funziona :)


1
Non funziona per quando $icontiene spazi. :(
Vasyl Boroviak,

Puoi pubblicare un esempio?
pbaranski,

1
Sicuro. i="a b"anziché for-loop
Vasyl Boroviak

5
Ho scoperto che la risposta accettata e la seconda votata non funzionano /bin/sh. Tuttavia, questa risposta ha funzionato. Ed è molto più semplice delle altre risposte. Grazie mille! Ho modificato la tua risposta con una migliore formattazione del ritorno a capo. Altrimenti, è difficile individuare lo splendore. Saluti compagno
Vasyl Boroviak

1
Grazie mille @pbaranski mi hai risparmiato un sacco di tempo
sudhir tataraju,

32

Curl può pubblicare dati binari da un file, quindi ho usato la sostituzione di processo e sfruttando i descrittori di file ogni volta che ho bisogno di pubblicare qualcosa di brutto con curl e voglio ancora accedere ai var nella shell corrente. Qualcosa di simile a:

curl "http://localhost:8080" \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
--data @<(cat <<EOF
{
  "me": "$USER",
  "something": $(date +%s)
  }
EOF
)

Questo finisce per sembrare --data @/dev/fd/<some number>che viene appena elaborato come un normale file. Comunque, se vuoi vederlo funzionare localmente, esegui nc -l 8080prima e in una shell diversa spegni il comando sopra. Vedrai qualcosa come:

POST / HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.43.0
Accept: application/json
Content-Type:application/json
Content-Length: 43

{  "me": "username",  "something": 1465057519  }

Come puoi vedere, puoi chiamare sottotitoli e quant'altro, nonché vars di riferimento nell'eredità. Happy hacking spero che questo aiuti con '"'"'""""'''""''.


2
L'altra risposta non ha funzionato per me mentre cercavo di invocarla in un avviso di Zabbix. Questo lo risolve perfettamente ed è più pulito.
0rkan,

Ma cosa succede se si inserisce il codice in una funzione bash: myFunction () {....}?
Hanynowsky,

1
vale la pena notare che questa ricetta funziona solo se lo script è copiato alla lettera (cioè non è necessario riformattare EOF, parentesi graffe ecc.)
Vader B,

9

Qualche anno in ritardo, ma questo potrebbe aiutare qualcuno se stai usando la sostituzione di eval o backtick:

postDataJson="{\"guid\":\"$guid\",\"auth_token\":\"$token\"}"

Utilizzo di sed per eliminare le virgolette dall'inizio e dalla fine della risposta

$(curl --silent -H "Content-Type: application/json" https://${target_host}/runs/get-work -d ${postDataJson} | sed -e 's/^"//' -e 's/"$//')

4
  • le informazioni di Sir Athos hanno funzionato perfettamente !!

Ecco come ho dovuto usarlo nel mio script curl per couchDB. Mi ha davvero aiutato molto. Grazie!

bin/curl -X PUT "db_domain_name_:5984/_config/vhosts/$1.couchdb" -d '"/'"$1"'/"' --user "admin:*****"

4

Ecco cosa ha funzionato per me, dopo la guida delle risposte qui:

export BASH_VARIABLE="[1,2,3]"
curl http://localhost:8080/path -d "$(cat <<EOF
{
  "name": $BASH_VARIABLE,
  "something": [
    "value1",
    "value2",
    "value3"
  ]
}
EOF
)" -H 'Content-Type: application/json'

2

Le risposte esistenti sottolineano che l'arricciatura può pubblicare dati da un file e impiegare heredocs per evitare la fuga eccessiva di citazioni e chiaramente suddividere il JSON su nuove righe. Tuttavia, non è necessario definire una funzione o acquisire l'output da cat, poiché l'arricciatura può inviare dati dall'input standard. Trovo questo modulo molto leggibile:

curl -X POST -H 'Content-Type:application/json' --data '$@-' ${API_URL} << EOF
{
  "account": {
    "email": "$email",
    "screenName": "$screenName",
    "type": "$theType",
    "passwordSettings": {
      "password": "$password",
      "passwordConfirm": "$password"
    }
  },
  "firstName": "$firstName",
  "lastName": "$lastName",
  "middleName": "$middleName",
  "locale": "$locale",
  "registrationSiteId": "$registrationSiteId",
  "receiveEmail": "$receiveEmail",
  "dateOfBirth": "$dob",
  "mobileNumber": "$mobileNumber",
  "gender": "$gender",
  "fuelActivationDate": "$fuelActivationDate",
  "postalCode": "$postalCode",
  "country": "$country",
  "city": "$city",
  "state": "$state",
  "bio": "$bio",
  "jpFirstNameKana": "$jpFirstNameKana",
  "jpLastNameKana": "$jpLastNameKana",
  "height": "$height",
  "weight": "$weight",
  "distanceUnit": "MILES",
  "weightUnit": "POUNDS",
  "heightUnit": "FT/INCHES"
}
EOF
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.