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()
.