Menggunakan curl POST dengan variabel yang didefinisikan dalam fungsi skrip bash

176

Ketika saya echo saya mendapatkan ini, yang berjalan ketika saya memasukkannya ke terminal

curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data '{"account":{"email":"[email protected]","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

Tetapi ketika dijalankan dalam file skrip bash, saya mendapatkan kesalahan ini

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

ini kode dalam 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:[email protected]/xxxxx/xxxx/xxxx"

Saya berasumsi ada masalah dengan tanda kutip saya, tapi saya sering bermain dengan mereka dan saya mendapatkan kesalahan yang sama. Semua variabel didefinisikan dengan berbagai fungsi dalam skrip aktual

AGleasonTU
sumber

Jawaban:

274

Anda tidak perlu meneruskan tanda kutip yang melampirkan tajuk khusus. Juga, variabel Anda di tengah dataargumen harus dikutip.

Pertama, tulis fungsi yang menghasilkan data tulisan skrip Anda. Ini menyelamatkan Anda dari semua jenis sakit kepala berkenaan dengan mengutip shell dan membuatnya lebih mudah untuk membaca skrip pemeliharaan daripada memberi makan data posting pada baris doa curl seperti dalam upaya Anda:

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
}

Maka mudah untuk menggunakan fungsi itu dalam doa curl:

curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data "$(generate_post_data)" "https://xxx:[email protected]/xxxxx/xxxx/xxxx"

Ini mengatakan, berikut adalah beberapa klarifikasi tentang aturan penawaran shell:

Kutipan ganda dalam -Hargumen (seperti dalam -H "foo bar") memberitahu bash untuk menjaga apa yang ada di dalamnya sebagai argumen tunggal (bahkan jika itu berisi spasi).

Kutipan tunggal dalam --dataargumen (seperti dalam --data 'foo bar') melakukan hal yang sama, kecuali mereka melewati semua teks kata demi kata (termasuk karakter kutipan ganda dan tanda dolar).

Untuk menyisipkan variabel di tengah-tengah teks yang dikutip tunggal, Anda harus mengakhiri kutip tunggal, kemudian menyatukan dengan variabel dikutip ganda, dan re-membuka kutip tunggal untuk melanjutkan teks: 'foo bar'"$variable"'more foo'.

Pak Athos
sumber
9
"'" $ <variabel nama> "'" menyelesaikan masalah saya di mana saya perlu kutipan agar tidak dihapus. Terima kasih.
Usman
1
Solusi ini berfungsi tetapi saya pikir Anda dapat memancarkan tanda kutip ganda tambahan di sekitar variabel. Jadi alih-alih ini: --data '{"akun": {"email": "'" $ email "'"}}' Anda dapat melakukan ini: --data '{"akun": {"email": " '$ email' "}} '
twistedstream
3
Tidak bekerja ketika ada ruang setelah EOF kedua: EOF . Setelah menghapus semuanya baik-baik saja.
Klaas
2
@dauxaux Itu tergantung di mana Anda menjalankan perintah curl. Jika perintah dalam skrip, Anda cukup mendefinisikan fungsi di mana saja di atasnya dalam skrip yang sama. Jika Anda menjalankan curl langsung dari baris perintah, Anda memiliki beberapa opsi, salah satunya adalah mengetikkan fungsi dalam file baru dan kemudian pada baris perintah jalankan source my_new_fileuntuk menentukan fungsi di lingkungan Anda saat ini. Setelah itu Anda dapat menjalankan perintah curl seperti yang ditunjukkan.
Sir Athos
2
@ slashdottir Itu fitur bash yang disebut Here Documents. Anda dapat membacanya lebih detail di tautan ini - khususnya, lihat Contoh 19-5. Sudah ada juga pertanyaan lengkap tentang ini di sini di SO.
Sir Athos
103

Solusi diuji dengan https://httpbin.org/ dan skrip inline bash
1. Untuk variabel tanpa spasi di dalamnya yaitu 1:
Cukup tambahkan 'sebelum dan sesudah $variableketika mengganti string yang diinginkan

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

2. Untuk input dengan spasi:
Bungkus variabel dengan tambahan "yaitu "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 berhasil :)

pbaranski
sumber
1
Tidak berfungsi saat $iberisi spasi. :(
Vasyl Boroviak
Bisakah Anda memposting contoh?
pbaranski
1
Tentu. i="a b"bukannya for-loop
Vasyl Boroviak
5
Saya menemukan bahwa jawaban yang diterima dan yang kedua tidak berfungsi /bin/sh. Namun, jawaban ini berhasil. Dan itu jauh lebih sederhana daripada jawaban lainnya. Terima kasih banyak! Saya telah mengedit jawaban Anda dengan beberapa format pembungkus baris yang lebih bagus. Kalau tidak, sulit untuk menemukan kecemerlangannya. Cheers mate
Vasyl Boroviak
1
Terima kasih banyak @ pbaranski Anda menghemat banyak waktu saya
sudhir tataraju
32

Curl dapat memposting data biner dari file jadi saya telah menggunakan proses substitusi dan memanfaatkan deskriptor file setiap kali saya perlu memposting sesuatu yang buruk dengan curl dan masih ingin akses ke vars di shell saat ini. Sesuatu seperti:

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

Ini akhirnya tampak seperti --data @/dev/fd/<some number>yang baru saja diproses seperti file normal. Pokoknya jika Anda ingin melihatnya berfungsi secara lokal jalankan saja nc -l 8080terlebih dahulu dan dalam shell yang berbeda dari perintah di atas. Anda akan melihat sesuatu seperti:

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  }

Seperti yang Anda lihat, Anda dapat memanggil subshell dan yang lainnya serta vars referensi di heredoc. Selamat hacking, harap ini membantu '"'"'""""'''""''.

Che Ruisi-Besares
sumber
2
Jawaban lain tidak berhasil untuk saya karena saya mencoba memintanya dalam peringatan dari Zabbix. Yang ini menyelesaikannya dengan sempurna dan lebih bersih.
0rkan
Tetapi bagaimana jika Anda meletakkan kode dalam fungsi bash: myFunction () {....}?
Hanynowsky
1
perlu dicatat bahwa resep ini hanya berfungsi jika skrip disalin kata demi kata (yaitu tidak memformat ulang EOF, kawat gigi, dll.)
Vader B
9

Beberapa tahun terlambat tetapi ini mungkin membantu seseorang jika Anda menggunakan pengganti eval atau backtick:

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

Menggunakan tanda kutip untuk mengutip dari awal dan akhir respons

$(curl --silent -H "Content-Type: application/json" https://${target_host}/runs/get-work -d ${postDataJson} | sed -e 's/^"//' -e 's/"$//')
mesin terbang
sumber
4
  • info dari Sir Athos bekerja dengan sempurna !!

Inilah cara saya harus menggunakannya dalam skrip ikal saya untuk couchDB. Ini sangat membantu. Terima kasih!

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

Inilah yang sebenarnya bekerja untuk saya, setelah bimbingan dari jawaban di sini:

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'
xgMz
sumber
2

Jawaban yang ada menunjukkan bahwa curl dapat memposting data dari file, dan menggunakan heredocs untuk menghindari kutipan berlebihan yang keluar dan dengan jelas memecah JSON ke baris baru. Namun tidak perlu mendefinisikan fungsi atau menangkap output dari cat, karena curl dapat memposting data dari input standar. Saya menemukan formulir ini sangat mudah dibaca:

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
abyrd
sumber