Отправка POST-запроса через curl имеет проблемы с двойными кавычками

Отправка POST-запроса через curl имеет проблемы с двойными кавычками

Итак, чтобы отправить POST-запрос в gists (github), вы можете сделать что-то вроде этого, как показано вhttps://gist.github.com/caspyi...

curl --user "user" -X POST --data '{"description":"Created via API","public":"true","files":{"file1.txt":{"content":"Demo"}}' https://api.github.com/gists

Однако в приведенном выше примере имя файла и его содержимое жестко закодированы, что является частью file1.txt":{"content":"Demo"}...

Я заменяю указанную выше часть своей переменной, $file":{"content":"$content"}но инициализирую переменную, json-запрос должен быть заключен в двойные кавычки, что я и сделал, как

curl --user "user" -X POST --data "{\"description\":\"Created via API\",\"public\":\"true\",\"files\":{\"$file\":{\"content\":\"$content\"}}' https://api.github.com/gists

Но это не работает, я получаю ошибку json.

{
  "message": "Problems parsing JSON",
  "documentation_url": "https://developer.github.com/v3/gists/#create-a-gist"
}

Даже если бы я заменил все экранированные двойные кавычки на \'одинарные.

Кто-нибудь знает, как включить переменную в этот запрос JSON? Кстати: я использовал все заголовки, такие как

 -H "Content-Type: application/json; charset=UTF-8" 

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

ОБНОВЛЯТЬ.

Вот как выглядит весь контент.

function gist_controller(){
    content=$(cat $1)
    DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
    read -p "enter your password - " pass 
    public="false"
    gist_content=$(cat $1)
    curl --user "samserayo"  -H "Content-Type: application/json; charset=UTF-8" -X POST -d  "{ 'description': 'Created via API', 'public': 'true', 'files':{ ' '$1 ':{ 'content': '$gist_content'}}" https://api.github.com/gists
}
ОБНОВЛЕНИЕ 2

Файл, который приводит к сбою скрипта (файл, который я пытаюсь загрузить)

<?php echo 'hello world' ?>

решение1

Вы не показываете, какое значение вы установили для $file или $content. Во что они оба расширяются? Вероятно, один из них, другой или оба содержат символы, которые не нравятся парсеру JSON. Скорее всего, что-то внутри значения расширения переменной необходимо дополнительно экранировать или закодировать перед отправкой парсеру JSON через curl.

Вы ЭКСПОРТировали переменные среды?

Пытаться:

echo "$файл $контент";

чтобы убедиться, что они оба настроены так, как вы ожидаете.

решение2

Вы не указали, какую оболочку вы используете, но все, что заключено в двойные кавычки, подлежит расширению имени файла оболочки. В частности, {} имеет значение для большинства оболочек. Вот почему в приведенном вами примере для всего были использованы одинарные кавычки.

Выходы из оболочки сложны, и иногда кажется невозможным получить то, что вы хотите. Честно говоря, в таких случаях я бы написал скрипт Python для вызова curl, где я знаю, что оболочка мне не «помогает».

решение3

Поскольку этот вопрос был отложен для рассмотрения, вот еще один ответ.

Экранируйте части по отдельности (закройте первый экран, затем экранируйте свою переменную):

curl --user "user" -X POST --data '{"description":"Created via API","public":"true","files":{"'"${file}"'":{"content":"'"${content}"'"}}}' https://api.github.com/gists

или разделить для удобства чтения:

'{"description":"Created via API","public":"true","files":{"'
"${file}"
'":{"content":"'
"${content}"
'"}}}' 

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

МВЭ:cat /tmp/myfile | ./thisscript.sh "myfilename.txt"

#!/bin/sh

FILENAME="${1}"
#CONTENT="$(cat)"
CONTENT="$(sed -e 's/"/\\"/g')" # escape stuff

OFS="${IFS}"
IFS=''

PERSONAL_ACCESS_TOKEN="e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e"

curl --user "username:${PERSONAL_ACCESS_TOKEN}" -X POST --data '{"description":"Created via API","public":"true","files":{"'"${FILENAME}"'":{"content":"'"${CONTENT}"'"}}}' https://api.github.com/gists
IFS="${OFS}"

Чтобы это работало правильно, вам, конечно, все равно придется экранировать все символы, которые нарушат JSON., в содержимом вашего файла, например, "и управляющие символы (возврат каретки DOS) и т. д.
К сожалению, они решили использовать структуры данных JSON длясодержимое файлазагрузки.


Если я могу предложить другой способ создания Gists, используйте curlвызов API только для создания одного файла, скажем, READMEс некоторым шаблонным содержимым (не может быть пустым).
Затем выполните grep возвращенной структуры json дляgit_push_urlиклонgist git repo. После этого вы можете просто git commit, git pushнабивать gist, не беспокоясь о бинарных данных или проблемах экранирования.

решение4

Вот решение, но оно предполагает две вещи.

Что fileэто имя файла, предоставленное скрипту в качестве первого аргумента. А contentэто содержимое файла как text.

Также обратите внимание на то, что POST URL отличается от Вашего (см. пояснения ниже).

#!/bin/bash

file=$1
content=$(cat $1)

curl -H "Content-Type: application/json; charset=UTF-8" -X POST -d  "{ 'description': 'Created via API', 'public': 'true', 'files':{ ' '${file}':{ 'content': '${content}'}}" https://postman-echo.com/post

Файл content.txt содержит:

This is content of the content file.

Пример запуска:

./curl.sh content.txt

Пример вывода:

{
  "args": {},
  "data": "{ 'description': 'Created via API', 'public': 'true', 'files':{ ' 'content.txt ':{ 'content': 'This is content of the content file.'}}",
  "files": {},
  "form": {},
  "headers": {
    "x-forwarded-proto": "https",
    "host": "postman-echo.com",
    "content-length": "134",
    "accept": "*/*",
    "content-type": "application/json; charset=UTF-8",
    "user-agent": "curl/7.65.3",
    "x-forwarded-port": "443"
  },
  "json": null,
  "url": "https://postman-echo.com/post"
}

ПРИМЕЧАНИЯ:

Я использую здесь https://postman-echo.com/postвеб-сайт, который отображает все, что Вы на нем публикуете, в формате JSON.

Если содержимое файла content.txt более сложное, это решение может сломаться, так как его все равно придется правильно экранировать. Содержимое помещается в поле "content", поэтому здесь применяются все правила экранирования для json.

Чтобы увидеть красиво отображенный ответ (как в json выше), добавьте в конец curl | jq .(возможно, вам сначала придется его установить):

https://postman-echo.com/post | jq . 

Можно использовать jqдля автоматического цитирования всего содержимого файла (при необходимости для более продвинутого использования):

$ jq -Rs '.' content.txt
"This is just a text.\n"

$ jq -Rs '.' content.cpp
"#include <iostream>\nusing namespace std;\nint main() \n{\n    cout << \"Hello, World!\";\n    return 0;\n}\n"

Вам придется немного изменить скрипт, curl.shчтобы он заработал:

content=$(jq -Rs '.' $1)

Связанный контент