Beim Senden einer POST-Anfrage über curl treten Probleme mit doppelten Anführungszeichen auf

Beim Senden einer POST-Anfrage über curl treten Probleme mit doppelten Anführungszeichen auf

Um also eine POST-Anfrage an Gists (GitHub) zu senden, können Sie so etwas tun wie inhttps://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

Aber im obigen Beispiel sind der Dateiname und der Inhalt der Datei fest codiert, und das ist der Teil .. file1.txt":{"content":"Demo"}..

Ich ersetze den obigen Teil durch meine Variable, $file":{"content":"$content"}initialisiere aber die Variable, die JSON-Anforderung muss in doppelte Anführungszeichen eingeschlossen werden, was ich getan habe als

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

Aber das funktioniert nicht, ich bekomme einen JSON-Fehler.

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

Selbst wenn ich alle maskierten Anführungszeichen durch \'einfache Anführungszeichen ersetzt hätte.

Weiß jemand, wie man eine Variable in diese JSON-Anfrage einfügt? Übrigens: Ich habe alle Header verwendet, wie

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

und viele Kombinationen, um die Anfrage zu validieren, aber ohne Erfolg

AKTUALISIEREN.

So sieht der gesamte Inhalt aus.

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
}
AKTUALISIERUNG 2

Die Datei, die den Abbruch des Skripts verursacht (die Datei, die ich hochzuladen versuche, ist)

<?php echo 'hello world' ?>

Antwort1

Sie zeigen nicht, welchen Wert Sie für $file oder $content festgelegt haben. Wozu werden diese beiden erweitert? Wahrscheinlich enthält einer oder der andere oder beide Zeichen, die dem JSON-Parser nicht gefallen. Höchstwahrscheinlich muss etwas innerhalb des Variablenerweiterungswerts weiter maskiert oder codiert werden, bevor es über curl an den JSON-Parser übermittelt wird.

Haben Sie die Umgebungsvariablen EXPORTIERT?

Versuchen:

echo "$Datei $Inhalt";

um sicherzustellen, dass beide wie erwartet eingestellt sind.

Antwort2

Sie haben nicht angegeben, welche Shell Sie verwenden, aber alles in Anführungszeichen unterliegt der Shell-Dateinamenerweiterung. Insbesondere {} hat für die meisten Shells eine Bedeutung. Aus diesem Grund wurden in dem von Ihnen zitierten Beispiel einfache Anführungszeichen verwendet, um das Ganze einzuschließen.

Shell-Escapes sind knifflig und manchmal scheint es unmöglich, das gewünschte Ergebnis zu erzielen. Ehrlich gesagt würde ich in solchen Fällen ein Python-Skript schreiben, um curl aufzurufen, wenn ich weiß, dass mir die Shell nicht „hilft“.

Antwort3

Da dies zur Überprüfung zurückgestellt wurde, hier eine weitere Antwort.

Escapen Sie die Teile separat (schließen Sie das erste Escape und escapen Sie dann Ihre Variable):

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

oder zur besseren Lesbarkeit aufgeteilt:

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

Möglicherweise müssen Sie auch den internen Feldtrenner ändern, damit die Shell keine Leerzeichen in Ihren Variablen selbst interpretiert.

MWE: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}"

Damit dies richtig funktioniert, müssen Sie natürlich weiterhin alle Zeichen maskieren, die JSON beschädigen würden., in Ihren Dateiinhalten, wie z. B. "und Steuerzeichen (DOS-Wagenrückläufe) usw.
Es ist ... bedauerlich, dass sie sich entschieden haben, JSON-Datenstrukturen fürDateiinhaltUploads.


Wenn ich eine andere Möglichkeit zum Erstellen von Gists vorschlagen darf, verwenden Sie den curlAPI-Aufruf nur, um eine einzelne Datei zu erstellen, beispielsweise READMEmit einem Boilerplate-Inhalt (darf nicht leer sein).
Dann durchsuchen Sie die zurückgegebene JSON-Struktur nachgit_push_urlUndKlondas Gist-Git-Repo. Danach können Sie einfach das Gist-Repo füllen git commit, git pushohne sich um Binärdaten oder Escape-Probleme kümmern zu müssen.

Antwort4

Hier ist eine Lösung, die jedoch zwei Dinge voraussetzt.

Das fileist ein Dateiname, der dem Skript als erstes Argument übergeben wird. Und das contentist der Dateiinhalt als text.

Beachten Sie auch, dass es sich um eine andere POST-URL als Ihre eigene handelt (Erklärung siehe unten).

#!/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

Die Datei content.txt enthält:

This is content of the content file.

Beispiellauf:

./curl.sh content.txt

Beispielausgabe:

{
  "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"
}

ANMERKUNGEN:

Ich verwende hier die https://postman-echo.com/postWebsite, die alles, was Sie dort posten, als JSON wiedergibt.

Wenn der Inhalt der Datei content.txt komplizierter ist, kann diese Lösung scheitern, da er noch immer ordnungsgemäß maskiert werden muss. Der Inhalt wird in das Feld „content“ eingefügt, daher gelten hier alle Maskierungsregeln für JSON.

Um die Antwort schön angezeigt zu bekommen (wie oben im JSON), fügen Sie am Ende des Curls hinzu | jq .(Sie müssen es möglicherweise zuerst installieren):

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

Es ist möglich, jqdie gesamte Inhaltsdatei automatisch zu zitieren (falls dies für eine erweiterte Nutzung erforderlich ist):

$ 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.shDamit es funktioniert, müssen Sie das Skript leicht modifizieren :

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

verwandte Informationen