Bash script: использовать строковую переменную в curl. Данные JSON Post

Я хочу отправить запрос json и вставить переменную в данные сообщения. Я сделал небольшое исследование, и я придумал одинарные кавычки вокруг переменной.

    #!/bin/bash
    FILENAME="/media/file.avi"
    curl -i -X POST -H "Content-Type: application/json" —d '{"jsonrpc": "2.0", "method": "Player.Open", "params":{"item":{"file":"'$FILENAME'"}}}' http://192.167.0.13/jsonrpc

К сожалению, я получаю некоторые ошибки:

curl: (6) Couldn't resolve host '—d'
curl: (3) [globbing] nested braces not supported at pos 54
HTTP/1.1 200 OK
Content-Length: 76
Content-Type: application/json
Date: Wed, 29 Jan 2014 19:16:56 GMT

{"error":{"code":-32700,"message":"Parse error."},"id":null,"jsonrpc":"2.0"}

По-видимому, есть некоторые проблемы с фигурными скобками и состояниями ответа HTTP, что команда не может быть выполнена. Что не так с моим кодом здесь? Спасибо!

Это моя версия curl:

curl 7.30.0 (mips-unknown-linux-gnu) libcurl/7.30.0 OpenSSL/0.9.8y
Protocols: file ftp ftps http https imap imaps pop3 pop3s rtsp smtp smtps tftp 
Features: IPv6 Largefile NTLM NTLM_WB SSL 

Ответ 1

Обновление: используйте более простой

request_body=$(cat <<EOF
{
  "jsonrpc": "2.0",
  "method": "Player.Open",
  "params": {
    "item": {
      "file": "$FILENAME"
    }
  }
}
EOF
)

а не то, что я объясняю ниже. Однако, если это опция, используйте jq для создания JSON. Это гарантирует, что значение $FILENAME будет правильно процитировано.

request_body=$(jq -n --arg fname "$FILENAME" '
{
  jsonrpc: "2.0",
  method: "Player.Open",
  params: {item: {file: $fname}}
}'

Было бы проще сначала определить переменную с содержимым тела запроса:

#!/bin/bash
header="Content-Type: application/json"
FILENAME="/media/file.avi"
request_body=$(< <(cat <<EOF
{
  "jsonrpc": "2.0",
  "method": "Player.Open",
  "params": {
    "item": {
      "file": "$FILENAME"
    }
  }
}
EOF
))
curl -i -X POST -H "$header" -d "$request_body" http://192.167.0.13/jsonrpc

Это определение может потребовать объяснения, чтобы понять, но обратите внимание на два больших преимущества:

  • Вы удаляете уровень цитирования
  • Вы можете легко форматировать текст для удобства чтения.

Сначала у вас есть простая подстановка команды, которая читается из файла:

$( < ... )   # bash improvement over $( cat ... )

Вместо имени файла, однако, вы указываете подстановку процесса, в которой вывод команды используется так, как если бы она была телом файла.

Команда в подстановке процесса просто cat, которая читается из документа здесь. Это документ, который содержит ваш запрос. Забастовкa >

Ответ 2

Мое предложение:

#!/bin/bash
FILENAME="/media/file 2.avi"
curl -i -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "Player.Open", "params":{"item":{"file":"'"$FILENAME"'"}}}' http://192.167.0.13/jsonrpc

Различия - это дефис в -d (вместо тире) и двойные кавычки вокруг $FILENAME.

Ответ 3

Вот еще один способ вставить данные из файла в свойство JSON. Это решение основано на действительно классной команде jq.

Ниже приведен пример, который подготавливает данные JSON запроса, используемые для создания капли CoreOS в Digital Ocean:

# Load the cloud config to variable
user_data=$(cat config/cloud-config)

# Prepare the request data 
request_data='{
  "name": "server name",
  "region": "fra1",
  "size": "512mb",
  "image": "coreos-stable",
  "backups": false,
  "ipv6": true,
  "user_data": "---this content will be replaced---",
  "ssh_keys": [1234, 2345]
}'

# Insert data from file into the user_data property
request_data=$(echo $request_data | jq ". + {user_data: \"$user_data\"}")