2016-03-25 13 views
3

をハングアップします。私はそれのためのファイルのようなオブジェクトを使用したいと思います。通常は次のようにします:はPythonの要求にowncloudするために0バイトのファイルをアップロードすると、私はowncloudする要求で0バイトのファイルをアップロードしようとしています

file_obj = io.BytesIO(b'') 
response = requests.put('http://localhost/remote.php/webdav', 
            auth=('xxx', 'xxx'), 
            data=file_obj) 

しかし、それはフリーズします。私は、プロセスを中断した場合、それはスタックトレースでハングところ、私は以下を参照してください。

PUT /remote.php/webdav/test.txt HTTP/1.1 
Host: localhost 
Connection: keep-alive 
Accept-Encoding: gzip, deflate 
Authorization: Basic *********** 
Transfer-Encoding: chunked 
User-Agent: python-requests/2.9.1 
Accept: */* 
Content-Length: 0 

Traceback (most recent call last): 
    File "/home/julian/cc/client/.venv/lib/python3.5/site-packages/requests/packages/urllib3/connectionpool.py", line 376, in _make_request 
    httplib_response = conn.getresponse(buffering=True) 
TypeError: getresponse() got an unexpected keyword argument 'buffering' 

During handling of the above exception, another exception occurred: 

Traceback (most recent call last): 
    File "/home/julian/cc/client/cc/storage/webdav.py", line 360, in <module> 
    main() 
    File "/home/julian/cc/client/cc/storage/webdav.py", line 351, in main 
    data=file_obj) 
    File "/home/julian/cc/client/.venv/lib/python3.5/site-packages/requests/api.py", line 120, in put 
    return request('put', url, data=data, **kwargs) 
    File "/home/julian/cc/client/.venv/lib/python3.5/site-packages/requests/api.py", line 53, in request 
    return session.request(method=method, url=url, **kwargs) 
    File "/home/julian/cc/client/.venv/lib/python3.5/site-packages/requests/sessions.py", line 468, in request 
    resp = self.send(prep, **send_kwargs) 
    File "/home/julian/cc/client/.venv/lib/python3.5/site-packages/requests/sessions.py", line 576, in send 
    r = adapter.send(request, **kwargs) 
    File "/home/julian/cc/client/.venv/lib/python3.5/site-packages/requests/adapters.py", line 376, in send 
    timeout=timeout 
    File "/home/julian/cc/client/.venv/lib/python3.5/site-packages/requests/packages/urllib3/connectionpool.py", line 559, in urlopen 
    body=body, headers=headers) 
    File "/home/julian/cc/client/.venv/lib/python3.5/site-packages/requests/packages/urllib3/connectionpool.py", line 378, in _make_request 
    httplib_response = conn.getresponse() 
    File "/usr/lib64/python3.5/http/client.py", line 1174, in getresponse 
    response.begin() 
    File "/usr/lib64/python3.5/http/client.py", line 282, in begin 
    version, status, reason = self._read_status() 
    File "/usr/lib64/python3.5/http/client.py", line 243, in _read_status 
    line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1") 
    File "/usr/lib64/python3.5/socket.py", line 575, in readinto 
    return self._sock.recv_into(b) 
KeyboardInterrupt 

Wiresharkのは、罰金のようだ次の要求を、sendetませんが、決して答えを取得する要求を私に伝えます

私は空の文字列を送信する場合、それは動作します:

response = requests.put('http://localhost/remote.php/webdav/test.txt', 
            auth=('xxx', 'xxx'), 
            data='') 

HTTPストリーム:

PUT /remote.php/webdav/test.txt HTTP/1.1 
Host: localhost 
Content-Length: 0 
Accept-Encoding: gzip, deflate 
Connection: keep-alive 
User-Agent: python-requests/2.9.1 
Accept: */* 
Authorization: Basic ****** 



HTTP/1.1 204 No Content 
Date: Thu, 24 Mar 2016 16:14:28 GMT 
Server: Apache/2.4.10 (Debian) PHP/5.6.19 
X-Powered-By: PHP/5.6.19 
Set-Cookie: xxx=xxx; path=/; HttpOnly 
Expires: Thu, 19 Nov 1981 08:52:00 GMT 
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0 
Pragma: no-cache 
Set-Cookie: oc_sessionPassphrase=xxxx; path=/; httponly 
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; frame-src *; img-src * data: blob:; font-src 'self' data:; media-src *; connect-src * 
X-XSS-Protection: 1; mode=block 
X-Content-Type-Options: nosniff 
X-Frame-Options: Sameorigin 
X-Robots-Tag: none 
X-Download-Options: noopen 
X-Permitted-Cross-Domain-Policies: none 
Set-Cookie: xxx=xxx; path=/; HttpOnly 
OC-FileId: xxxxx 
Content-Length: 0 
ETag: "xxx" 
OC-ETag: "xxx" 
Keep-Alive: timeout=5, max=100 
Connection: Keep-Alive 
Content-Type: text/html; charset=UTF-8 

これは、同様に動作します:

def chunker(file_obj): 
    buf = None 
    while buf != b'': 
     print('iter') 
     buf = file_obj.read(16*1024) 
     yield buf 

file_obj = io.BytesIO(b'') 
response = requests.put('http://localhost/remote.php/webdav/test.txt', 
            auth=('xxx', 'xxx'), 
            data=chunker(file_obj)) 

任意のアイデアを、これはファイルライクオブジェクトを使用しない理由?私は要求の最新バージョン(2.9.1)とPython 3.5を使用しています。

+0

'requests'がb0rkenているようです。転送エンコーディングは、チャンクに設定されているが、それは適切な身体をチャンクされていません。 –

答えて

5

requestsにバグがあるようです。 authを指定せずに要求がTransfer-Encoding: chunkedを使用し、リクエストの終了時に正しいlast-chunkを送信しますが、authで何last-chunkは送信されませんし、ヘッダが混乱しています。 http://tools.ietf.org/html/rfc7230#section-4.1から

chunked-body = *chunk 
        last-chunk 
        trailer-part 
        CRLF 

chunk   = chunk-size [ chunk-ext ] CRLF 
        chunk-data CRLF 
chunk-size  = 1*HEXDIG 
last-chunk  = 1*("0") [ chunk-ext ] CRLF 

chunk-data  = 1*OCTET ; a sequence of chunk-size octets 

http://tools.ietf.org/html/rfc7230#section-3.3.2

送信者が転送-Encodingヘッダフィールドを含むすべてのメッセージ
にContent-Lengthヘッダフィールドを送ってはいけません。送信要求が

PUT /asdf HTTP/1.1⏎ 
Host: localhost:8000⏎ 
User-Agent: python-requests/2.9.1⏎ 
Transfer-Encoding: chunked⏎ 
Accept-Encoding: gzip, deflate⏎ 
Connection: keep-alive⏎ 
Accept: */*⏎ 
⏎ 
0⏎ 
⏎ 

(⏎上記CRLFを意味する)であるauth引数

f = io.BytesIO(b'') 
requests.put('http://localhost:8000/asdf', data=f) 

なし

。あなたはauth

requests.put('http://localhost:8000/asdf', auth=('asdf', 'fdsa'), data=f) 

を指定した場合でも、要求が

PUT /asdf HTTP/1.1⏎ 
Host: localhost:8000⏎ 
Transfer-Encoding: chunked⏎ 
Accept-Encoding: gzip, deflate⏎ 
User-Agent: python-requests/2.9.1⏎ 
Authorization: Basic YXNkZjpmZHNh⏎ 
Content-Length: 0⏎ 
Connection: keep-alive⏎ 
Accept: */*⏎ 
⏎ 

両方Transfer-EncodingContent-Length指定されている、それはすべきではない、と最後のチャンクが送信されず、そのためのサーバでありますより多くのチャンクが来て、応答のためのrequests待機するのを待って座っています。

+0

あなたの答えをありがとう。私はそれを報告した:https:// github。com/kennethreitz/requests/issues/3066 – uphill

関連する問題