STDIN을 사용하지 않으면 컬 오류가 발생할 수 있습니다.

STDIN을 사용하지 않으면 컬 오류가 발생할 수 있습니다.

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

나는 아파치가 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().

관련 정보