Shell-Script

不使用 STDIN 會導致 curl 錯誤

  • February 13, 2021

我已經為 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().

引用自:https://unix.stackexchange.com/questions/633323