次のようにjsonデータを読み取る必要があります。
#!/usr/bin/env python3
import os
import sys
import json
content_len = int(os.environ["CONTENT_LENGTH"])
req_body = sys.stdin.read(content_len)
my_dict = json.loads(req_body)
次のコードを使用すると、問題が発生する可能性があります。
myjson = json.load(sys.stdin)
またはあまり簡潔に書かれていません:
requ_body = sys.stdin.read()
my_dict = json.load(requ_body)
私のcgiスクリプトがサーバー上にある場合、それは私にとってはapache
うまくいきますが、私のcgiスクリプトが別のサーバー上にあるときにわかったように、一般的にはそれが機能することを期待することはできません。cgi仕様によると:
RFC 3875 CGI Version 1.1 October 2004
4.2. Request Message-Body
Request data is accessed by the script in a system-defined method;
unless defined otherwise, this will be by reading the 'standard
input' file descriptor or file handle.
Request-Data = [ request-body ] [ extension-data ]
request-body = <CONTENT_LENGTH>OCTET
extension-data = *OCTET
A request-body is supplied with the request if the CONTENT_LENGTH is
not NULL. The server MUST make at least that many bytes available
for the script to read. The server MAY signal an end-of-file
condition after CONTENT_LENGTH bytes have been read or it MAY supply
extension data. Therefore, the script MUST NOT attempt to read more
than CONTENT_LENGTH bytes, even if more data is available. However,
it is not obliged to read any of the data.
キーラインは次のとおりです。
より多くのデータが利用可能であっても、スクリプトはCONTENT_LENGTHバイトを超えて読み取ろうとしてはなりません(MUSTNOT)。
どうやら、apache
リクエスト本文をcgiスクリプトに送信した直後に、eofシグナルをcgiスクリプトに送信します。これによりsys.stdin.read()
、が返されます。しかし、cgi仕様によると、サーバーはリクエストの本文の後にeofシグナルを送信する必要はなくsys.stdin.read()
、スクリプトが別のサーバー上にあるときにcgiスクリプトがハングしていることがわかり、最終的にタイムアウトエラーが発生しました。
したがって、一般的なケースでjsonデータを読み込むには、次のようにする必要があります。
content_len = int(os.environ["CONTENT_LENGTH"])
req_body = sys.stdin.read(content_len)
my_dict = json.loads(req_body)
サーバーは、ヘッダー情報を含むcgiスクリプトの一連の環境変数を設定します。そのうちの1つはCONTENT_LENGTHです。
使用したときに失敗したcurlリクエストはmyjson = json.load(sys.stdin)
次のようになりました。
-v verbose output
-H specify one header
--data implicitly specifies a POST request
Note that curl automatically calculates a Content-Length header
for you.
~$ curl -v \
> -H 'Content-Type: application/json' \
> --data '{"a": 1, "b": 2}' \
> http://localhost:65451/cgi-bin/1.py
* Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 65451 failed: Connection refused
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 65451 (#0)
> POST /cgi-bin/1.py HTTP/1.1
> Host: localhost:65451
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 16
>
* upload completely sent off: 16 out of 16 bytes
=== hung here for about 5 seconds ====
< HTTP/1.1 504 Gateway Time-out
< Date: Thu, 08 Mar 2018 17:53:30 GMT
< Content-Type: text/html
< Server: inets/6.4.5
* no chunk, no close, no size. Assume close to signal end
<
* Closing connection 0