不使用 STDIN 會導致 curl 錯誤
我已經為 Github 設置了一個接收後掛鉤。它將向 Apache cgi 腳本發出 POST 請求,然後該腳本應該將對儲存庫的更改下載到本地複製的裸儲存庫中。當我添加 a 時腳本執行良好
VARIABLE=$(cat -)
,但是當我嘗試發出 post 請求並刪除包含的行時出現 curl 錯誤VARIABLE=
curl: (18) transfer closed with outstanding read data remaining
我的 POST 請求是由 curl 生成的(post-data 僅用於測試,它不會在實際腳本中使用):
curl -D - -H "Connection: close" -H "Content-Type: application/json" -d '{ "repository": { "name": "webhook-test", "git_url": "git://github.com/bng44270/webhook-test.git", "ssh_url": "git@github.com:bng44270/webhook-test.git", "clone_url": "https://github.com/bng44270/webhook-test.git" }}' http://10.0.0.2/cgi-bin/clone.cgi --verbose
我的虛擬主機配置文件:
ScriptAlias "/cgi-bin" "/opt/hooks/cgi-bin" DocumentRoot /opt/hooks/html <Directory /opt/hooks> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> </VirtualHost>
我的腳本正在執行:
#!/bin/bash /sbin/runuser -l gogsjail -c '/usr/bin/git --git-dir /home/gogsjail/gogs-repositories/admin/upstream.git fetch --prune >/dev/null 2>&1' >/dev/null 2>&1 # VARIABLE=$(cat -) echo "Content-type: text/json" echo "" echo '{"result":"success"}'
最後是 curl 的輸出:
* Expire in 0 ms for 6 (transfer 0x563f98984f90) * Trying 10.0.0.2... * TCP_NODELAY set * Expire in 200 ms for 4 (transfer 0x563f98984f90) * Connected to 10.0.0.2 (10.0.0.2) port 80 (#0) > POST /cgi-bin/clone.cgi HTTP/1.1 > Host: 10.0.0.2 > User-Agent: curl/7.64.0 > Accept: */* > Connection: close > Content-Type: application/json > Content-Length: 230 > * upload completely sent off: 230 out of 230 bytes < HTTP/1.1 200 OK HTTP/1.1 200 OK < Date: Mon, 08 Feb 2021 12:55:42 GMT Date: Mon, 08 Feb 2021 12:55:42 GMT < Server: Apache/2.4.38 (Debian) Server: Apache/2.4.38 (Debian) < Connection: close Connection: close < Transfer-Encoding: chunked Transfer-Encoding: chunked < Content-Type: text/json Content-Type: text/json < {"result":"success"} * transfer closed with outstanding read data remaining * Closing connection 0 curl: (18) transfer closed with outstanding read data remaining
如果我
VARIABLE=$(cat -)
在迴聲呼叫之前執行,我會得到* Expire in 0 ms for 6 (transfer 0x55ea56355f90) * Trying 10.0.0.2... * TCP_NODELAY set * Expire in 200 ms for 4 (transfer 0x55ea56355f90) * Connected to 10.0.0.2 (10.0.0.2) port 80 (#0) > POST /cgi-bin/clone.cgi HTTP/1.1 > Host: 10.0.0.2 > User-Agent: curl/7.64.0 > Accept: */* > Connection: close > Content-Type: application/json > Content-Length: 244 > * upload completely sent off: 244 out of 244 bytes < HTTP/1.1 200 OK < Date: Mon, 08 Feb 2021 13:35:28 GMT < Server: Apache/2.4.38 (Debian) < Connection: close < Transfer-Encoding: chunked < Content-Type: text/json < {"result":"success"} * Closing connection 0
有人可以將我推向正確的方向嗎?
我想apache正在做相當於:讀取來自客戶端的所有請求,包括POST數據,並通過管道(比如)將其寫入cgi程序。它還從 cgi 讀取回复並將其發送給客戶端。它執行一個循環,
select()
同時繼續這些讀取和寫入。當 cgi 退出並關閉管道時,apache 的 select() 會在讀取時看到異常,由於 eof,並且在寫入時出現異常。如果 cgi 沒有從 apache 讀取 POST 數據,則 apache 會看到掛起的寫入出現 ioerror,因此可能會認為 cgi 表現不佳,而只是關閉客戶端連接而無需進一步清理。
由於 cgi 沒有放出 content-length 標頭,因此 apache 無法確定回复的長度,因此放出了
Transfer-Encoding: chunked
標頭。該協議通過一個包含後續寫入長度的小標題圍繞回復中的每個寫入。需要通過發送寫入長度 0 (0\r\n
) 來徹底終止協議。據推測,協議的最後一部分是缺少的,並且是 curl 抱怨的原因。分塊協議不會由 curl 公開,但您可能會使用
--raw
或使用strace()
.