透過curl發送POST請求存在雙引號問題

透過curl發送POST請求存在雙引號問題

因此,為了向 gists (github) 發送 POST 請求,您可以執行類似的操作,例如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 解析器不喜歡的字元。最有可能的是,在透過curl 提交給JSON 解析器之前,變數擴充值中的某些內容需要進一步轉義或編碼。

你導出環境變數了嗎?

嘗試:

迴聲“$文件$內容”;

確保它們都按照您的預期設定。

答案2

您沒有指定正在使用的 shell,但雙引號內的任何內容都會受到 shell 檔案名稱擴充的影響。特別是,{} 對於大多數 shell 都有意義。這就是您引用的範例使用單引號來包裹整個內容的原因。

Shell 轉義是很棘手的,有時似乎不可能得到你想要的東西。老實說,在這種情況下,我會編寫一個Python腳本來呼叫curl,我知道shell不會「幫助」我。

答案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}"
'"}}}' 

您可能也可能不需要更改內部欄位分隔符,因此 shell 不會解釋變數本身中的任何空格。

微量元素: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 回車符)等。
文件內容上傳。


如果我建議使用不同的方式來建立 Gists,請curl僅使用 API 呼叫來建立單一文件,例如README包含一些樣板內容(不能為空)。
然後 grep 傳回的 json 結構git_push_url複製git 倉庫的要點。之後,您就可以直接填寫要點git commit,而不必擔心二進位資料或轉義問題。git push

答案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)

相關內容