Githubの受信後フックを設定しました。 Apache cgiスクリプトにPOSTリクエストを実行し、リポジトリへの変更をローカルに複製されたベアリポジトリにダウンロードします。追加するとスクリプトは正常に実行されますが、VARIABLE=$(cat -)
発行要求を実行して次の行を削除しようとするとカールエラーが発生します。VARIABLE=
curl: (18) transfer closed with outstanding read data remaining
私のPOSTリクエストはカールによって生成されます(公開データはテスト用にのみ使用され、実際のスクリプトでは使用されません)。
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": "[email protected]: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"}'
最後に、カールの出力は次のようになります。
* 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
誰かが私を正しい方向に押してもらえますか?
答え1
私はApacheがPOSTデータを含むクライアントからすべての要求を読み込み、それをパイプを介してcgiプロセスに書き込むのと同等のことを想像しています。また、cgiの応答を読み、それをクライアントに送信します。select()
これらの読み取りと書き込みを継続しながらループを実行します。
cgiがパイプを終了して閉じると、apacheのselect()は読み込み時に例外をスローし、eofによって書き込まれると例外をスローします。 cgiがapacheからPOSTデータを読み取らない場合、apacheは保留中の書き込みでioerrorを表示します。したがって、cgiが誤動作していると考え、追加のクリーンアップなしで単にクライアント接続を閉じることができます。
cgiはコンテンツ長ヘッダーを出力しないため、Apacheは応答長を決定できないため、ヘッダーを出力しますTransfer-Encoding: chunked
。このプロトコルは、後続の書き込み長で構成されるミニヘッダーで、応答の各書き込みを囲みます。プロトコルは、0\r\n
長さ0()の書き込みを送信してきちんと終了する必要があります。おそらく、プロトコルの最後の部分が欠落してカールが文句を言う理由です。
チャンキングプロトコルはカールを介して公開されませんが、または--raw
を使用して表示できますstrace()
。