author | Jun Wu <quark@fb.com> |
Fri, 02 Jun 2017 19:32:27 -0700 | |
changeset 32688 | 2c1400d43fd2 |
parent 31411 | a53f2d4c734f |
permissions | -rw-r--r-- |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
1 |
# Copyright 2010, Google Inc. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
2 |
# All rights reserved. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
3 |
# |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
4 |
# Redistribution and use in source and binary forms, with or without |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
5 |
# modification, are permitted provided that the following conditions are |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
6 |
# met: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
7 |
# |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
8 |
# * Redistributions of source code must retain the above copyright |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
9 |
# notice, this list of conditions and the following disclaimer. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
10 |
# * Redistributions in binary form must reproduce the above |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
11 |
# copyright notice, this list of conditions and the following disclaimer |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
12 |
# in the documentation and/or other materials provided with the |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
13 |
# distribution. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
14 |
# * Neither the name of Google Inc. nor the names of its |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
15 |
# contributors may be used to endorse or promote products derived from |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
16 |
# this software without specific prior written permission. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
17 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
18 |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
19 |
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
20 |
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
21 |
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
22 |
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
23 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
24 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
25 |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
26 |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
27 |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
28 |
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
29 |
"""Improved HTTP/1.1 client library |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
30 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
31 |
This library contains an HTTPConnection which is similar to the one in |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
32 |
httplib, but has several additional features: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
33 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
34 |
* supports keepalives natively |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
35 |
* uses select() to block for incoming data |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
36 |
* notices when the server responds early to a request |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
37 |
* implements ssl inline instead of in a different class |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
38 |
""" |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
39 |
from __future__ import absolute_import |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
40 |
|
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
41 |
# Many functions in this file have too many arguments. |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
42 |
# pylint: disable=R0913 |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
43 |
import email |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
44 |
import email.message |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
45 |
import errno |
29131
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
46 |
import inspect |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
47 |
import logging |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
48 |
import select |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
49 |
import socket |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
50 |
import ssl |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
51 |
import sys |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
52 |
|
29131
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
53 |
try: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
54 |
import cStringIO as io |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
55 |
io.StringIO |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
56 |
except ImportError: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
57 |
import io |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
58 |
|
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
59 |
try: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
60 |
import httplib |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
61 |
httplib.HTTPException |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
62 |
except ImportError: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
63 |
import http.client as httplib |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
64 |
|
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
65 |
from . import ( |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
66 |
_readers, |
29131
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
67 |
) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
68 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
69 |
logger = logging.getLogger(__name__) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
70 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
71 |
__all__ = ['HTTPConnection', 'HTTPResponse'] |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
72 |
|
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
73 |
HTTP_VER_1_0 = b'HTTP/1.0' |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
74 |
HTTP_VER_1_1 = b'HTTP/1.1' |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
75 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
76 |
OUTGOING_BUFFER_SIZE = 1 << 15 |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
77 |
INCOMING_BUFFER_SIZE = 1 << 20 |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
78 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
79 |
HDR_ACCEPT_ENCODING = 'accept-encoding' |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
80 |
HDR_CONNECTION_CTRL = 'connection' |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
81 |
HDR_CONTENT_LENGTH = 'content-length' |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
82 |
HDR_XFER_ENCODING = 'transfer-encoding' |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
83 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
84 |
XFER_ENCODING_CHUNKED = 'chunked' |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
85 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
86 |
CONNECTION_CLOSE = 'close' |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
87 |
|
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
88 |
EOL = b'\r\n' |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
89 |
_END_HEADERS = EOL * 2 |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
90 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
91 |
# Based on some searching around, 1 second seems like a reasonable |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
92 |
# default here. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
93 |
TIMEOUT_ASSUME_CONTINUE = 1 |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
94 |
TIMEOUT_DEFAULT = None |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
95 |
|
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
96 |
if sys.version_info > (3, 0): |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
97 |
_unicode = str |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
98 |
else: |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
99 |
_unicode = unicode |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
100 |
|
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
101 |
def _ensurebytes(data): |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
102 |
if not isinstance(data, (_unicode, bytes)): |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
103 |
data = str(data) |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
104 |
if not isinstance(data, bytes): |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
105 |
try: |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
106 |
return data.encode('latin-1') |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
107 |
except UnicodeEncodeError as err: |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
108 |
raise UnicodeEncodeError( |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
109 |
err.encoding, |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
110 |
err.object, |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
111 |
err.start, |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
112 |
err.end, |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
113 |
'%r is not valid Latin-1 Use .encode("utf-8") ' |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
114 |
'if sending as utf-8 is desired.' % ( |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
115 |
data[err.start:err.end],)) |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
116 |
return data |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
117 |
|
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
118 |
class _CompatMessage(email.message.Message): |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
119 |
"""Workaround for rfc822.Message and email.message.Message API diffs.""" |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
120 |
|
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
121 |
@classmethod |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
122 |
def from_string(cls, s): |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
123 |
if sys.version_info > (3, 0): |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
124 |
# Python 3 can't decode headers from bytes, so we have to |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
125 |
# trust RFC 2616 and decode the headers as iso-8859-1 |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
126 |
# bytes. |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
127 |
s = s.decode('iso-8859-1') |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
128 |
headers = email.message_from_string(s, _class=_CompatMessage) |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
129 |
# Fix multi-line headers to match httplib's behavior from |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
130 |
# Python 2.x, since email.message.Message handles them in |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
131 |
# slightly different ways. |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
132 |
if sys.version_info < (3, 0): |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
133 |
new = [] |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
134 |
for h, v in headers._headers: |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
135 |
if '\r\n' in v: |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
136 |
v = '\n'.join([' ' + x.lstrip() for x in v.split('\r\n')])[1:] |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
137 |
new.append((h, v)) |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
138 |
headers._headers = new |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
139 |
return headers |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
140 |
|
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
141 |
def getheaders(self, key): |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
142 |
return self.get_all(key) |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
143 |
|
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
144 |
def getheader(self, key, default=None): |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
145 |
return self.get(key, failobj=default) |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
146 |
|
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
147 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
148 |
class HTTPResponse(object): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
149 |
"""Response from an HTTP server. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
150 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
151 |
The response will continue to load as available. If you need the |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
152 |
complete response before continuing, check the .complete() method. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
153 |
""" |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
154 |
def __init__(self, sock, timeout, method): |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
155 |
self.sock = sock |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
156 |
self.method = method |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
157 |
self.raw_response = b'' |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
158 |
self._headers_len = 0 |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
159 |
self.headers = None |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
160 |
self.will_close = False |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
161 |
self.status_line = b'' |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
162 |
self.status = None |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
163 |
self.continued = False |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
164 |
self.http_version = None |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
165 |
self.reason = None |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
166 |
self._reader = None |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
167 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
168 |
self._read_location = 0 |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
169 |
self._eol = EOL |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
170 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
171 |
self._timeout = timeout |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
172 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
173 |
@property |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
174 |
def _end_headers(self): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
175 |
return self._eol * 2 |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
176 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
177 |
def complete(self): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
178 |
"""Returns true if this response is completely loaded. |
14376
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
179 |
|
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
180 |
Note that if this is a connection where complete means the |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
181 |
socket is closed, this will nearly always return False, even |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
182 |
in cases where all the data has actually been loaded. |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
183 |
""" |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
184 |
if self._reader: |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
185 |
return self._reader.done() |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
186 |
|
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
187 |
def _close(self): |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
188 |
if self._reader is not None: |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
189 |
# We're a friend of the reader class here. |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
190 |
# pylint: disable=W0212 |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
191 |
self._reader._close() |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
192 |
|
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
193 |
def getheader(self, header, default=None): |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
194 |
return self.headers.getheader(header, default=default) |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
195 |
|
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
196 |
def getheaders(self): |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
197 |
if sys.version_info < (3, 0): |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
198 |
return [(k.lower(), v) for k, v in self.headers.items()] |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
199 |
# Starting in Python 3, headers aren't lowercased before being |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
200 |
# returned here. |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
201 |
return self.headers.items() |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
202 |
|
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
203 |
def readline(self): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
204 |
"""Read a single line from the response body. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
205 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
206 |
This may block until either a line ending is found or the |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
207 |
response is complete. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
208 |
""" |
19038 | 209 |
blocks = [] |
210 |
while True: |
|
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
211 |
self._reader.readto(b'\n', blocks) |
19038 | 212 |
|
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
213 |
if blocks and blocks[-1][-1:] == b'\n' or self.complete(): |
19038 | 214 |
break |
215 |
||
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
216 |
self._select() |
19038 | 217 |
|
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
218 |
return b''.join(blocks) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
219 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
220 |
def read(self, length=None): |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
221 |
"""Read data from the response body.""" |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
222 |
# if length is None, unbounded read |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
223 |
while (not self.complete() # never select on a finished read |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
224 |
and (not length # unbounded, so we wait for complete() |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
225 |
or length > self._reader.available_data)): |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
226 |
self._select() |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
227 |
if not length: |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
228 |
length = self._reader.available_data |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
229 |
r = self._reader.read(length) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
230 |
if self.complete() and self.will_close: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
231 |
self.sock.close() |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
232 |
return r |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
233 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
234 |
def _select(self): |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
235 |
r, unused_write, unused_err = select.select( |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
236 |
[self.sock], [], [], self._timeout) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
237 |
if not r: |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
238 |
# socket was not readable. If the response is not |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
239 |
# complete, raise a timeout. |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
240 |
if not self.complete(): |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
241 |
logger.info('timed out with timeout of %s', self._timeout) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
242 |
raise HTTPTimeoutException('timeout reading data') |
14341
5c3de67e7402
httpclient: import revision b8c3511a8cae from py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14293
diff
changeset
|
243 |
try: |
5c3de67e7402
httpclient: import revision b8c3511a8cae from py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14293
diff
changeset
|
244 |
data = self.sock.recv(INCOMING_BUFFER_SIZE) |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
245 |
except ssl.SSLError as e: |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
246 |
if e.args[0] != ssl.SSL_ERROR_WANT_READ: |
14341
5c3de67e7402
httpclient: import revision b8c3511a8cae from py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14293
diff
changeset
|
247 |
raise |
17428
72803c8edaa4
avoid using abbreviations that look like spelling errors
Mads Kiilerich <mads@kiilerich.com>
parents:
17424
diff
changeset
|
248 |
logger.debug('SSL_ERROR_WANT_READ in _select, should retry later') |
14341
5c3de67e7402
httpclient: import revision b8c3511a8cae from py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14293
diff
changeset
|
249 |
return True |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
250 |
logger.debug('response read %d data during _select', len(data)) |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
251 |
# If the socket was readable and no data was read, that means |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
252 |
# the socket was closed. Inform the reader (if any) so it can |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
253 |
# raise an exception if this is an invalid situation. |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
254 |
if not data: |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
255 |
if self._reader: |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
256 |
# We're a friend of the reader class here. |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
257 |
# pylint: disable=W0212 |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
258 |
self._reader._close() |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
259 |
return False |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
260 |
else: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
261 |
self._load_response(data) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
262 |
return True |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
263 |
|
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
264 |
# This method gets replaced by _load later, which confuses pylint. |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
265 |
def _load_response(self, data): # pylint: disable=E0202 |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
266 |
# Being here implies we're not at the end of the headers yet, |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
267 |
# since at the end of this method if headers were completely |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
268 |
# loaded we replace this method with the load() method of the |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
269 |
# reader we created. |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
270 |
self.raw_response += data |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
271 |
# This is a bogus server with bad line endings |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
272 |
if self._eol not in self.raw_response: |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
273 |
for bad_eol in (b'\n', b'\r'): |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
274 |
if (bad_eol in self.raw_response |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
275 |
# verify that bad_eol is not the end of the incoming data |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
276 |
# as this could be a response line that just got |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
277 |
# split between \r and \n. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
278 |
and (self.raw_response.index(bad_eol) < |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
279 |
(len(self.raw_response) - 1))): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
280 |
logger.info('bogus line endings detected, ' |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
281 |
'using %r for EOL', bad_eol) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
282 |
self._eol = bad_eol |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
283 |
break |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
284 |
# exit early if not at end of headers |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
285 |
if self._end_headers not in self.raw_response or self.headers: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
286 |
return |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
287 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
288 |
# handle 100-continue response |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
289 |
hdrs, body = self.raw_response.split(self._end_headers, 1) |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
290 |
unused_http_ver, status = hdrs.split(b' ', 1) |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
291 |
if status.startswith(b'100'): |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
292 |
self.raw_response = body |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
293 |
self.continued = True |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
294 |
logger.debug('continue seen, setting body to %r', body) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
295 |
return |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
296 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
297 |
# arriving here means we should parse response headers |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
298 |
# as all headers have arrived completely |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
299 |
hdrs, body = self.raw_response.split(self._end_headers, 1) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
300 |
del self.raw_response |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
301 |
if self._eol in hdrs: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
302 |
self.status_line, hdrs = hdrs.split(self._eol, 1) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
303 |
else: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
304 |
self.status_line = hdrs |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
305 |
hdrs = b'' |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
306 |
# TODO HTTP < 1.0 support |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
307 |
(self.http_version, self.status, |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
308 |
self.reason) = self.status_line.split(b' ', 2) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
309 |
self.status = int(self.status) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
310 |
if self._eol != EOL: |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
311 |
hdrs = hdrs.replace(self._eol, b'\r\n') |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
312 |
headers = _CompatMessage.from_string(hdrs) |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
313 |
content_len = None |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
314 |
if HDR_CONTENT_LENGTH in headers: |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
315 |
content_len = int(headers[HDR_CONTENT_LENGTH]) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
316 |
if self.http_version == HTTP_VER_1_0: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
317 |
self.will_close = True |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
318 |
elif HDR_CONNECTION_CTRL in headers: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
319 |
self.will_close = ( |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
320 |
headers[HDR_CONNECTION_CTRL].lower() == CONNECTION_CLOSE) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
321 |
if (HDR_XFER_ENCODING in headers |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
322 |
and headers[HDR_XFER_ENCODING].lower() == XFER_ENCODING_CHUNKED): |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
323 |
self._reader = _readers.ChunkedReader(self._eol) |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
324 |
logger.debug('using a chunked reader') |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
325 |
else: |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
326 |
# HEAD responses are forbidden from returning a body, and |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
327 |
# it's implausible for a CONNECT response to use |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
328 |
# close-is-end logic for an OK response. |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
329 |
if (self.method == b'HEAD' or |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
330 |
(self.method == b'CONNECT' and content_len is None)): |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
331 |
content_len = 0 |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
332 |
if content_len is not None: |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
333 |
logger.debug('using a content-length reader with length %d', |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
334 |
content_len) |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
335 |
self._reader = _readers.ContentLengthReader(content_len) |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
336 |
else: |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
337 |
# Response body had no length specified and is not |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
338 |
# chunked, so the end of the body will only be |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
339 |
# identifiable by the termination of the socket by the |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
340 |
# server. My interpretation of the spec means that we |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
341 |
# are correct in hitting this case if |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
342 |
# transfer-encoding, content-length, and |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
343 |
# connection-control were left unspecified. |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
344 |
self._reader = _readers.CloseIsEndReader() |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
345 |
logger.debug('using a close-is-end reader') |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
346 |
self.will_close = True |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
347 |
|
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
348 |
if body: |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
349 |
# We're a friend of the reader class here. |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
350 |
# pylint: disable=W0212 |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
351 |
self._reader._load(body) |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
352 |
logger.debug('headers complete') |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
353 |
self.headers = headers |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
354 |
# We're a friend of the reader class here. |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
355 |
# pylint: disable=W0212 |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
356 |
self._load_response = self._reader._load |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
357 |
|
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
358 |
def _foldheaders(headers): |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
359 |
"""Given some headers, rework them so we can safely overwrite values. |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
360 |
|
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
361 |
>>> _foldheaders({'Accept-Encoding': 'wat'}) |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
362 |
{'accept-encoding': ('Accept-Encoding', 'wat')} |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
363 |
""" |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
364 |
return dict((k.lower(), (k, v)) for k, v in headers.items()) |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
365 |
|
29131
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
366 |
try: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
367 |
inspect.signature |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
368 |
def _handlesarg(func, arg): |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
369 |
""" Try to determine if func accepts arg |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
370 |
|
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
371 |
If it takes arg, return True |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
372 |
If it happens to take **args, then it could do anything: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
373 |
* It could throw a different TypeError, just for fun |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
374 |
* It could throw an ArgumentError or anything else |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
375 |
* It could choose not to throw an Exception at all |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
376 |
... return 'unknown' |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
377 |
|
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
378 |
Otherwise, return False |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
379 |
""" |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
380 |
params = inspect.signature(func).parameters |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
381 |
if arg in params: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
382 |
return True |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
383 |
for p in params: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
384 |
if params[p].kind == inspect._ParameterKind.VAR_KEYWORD: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
385 |
return 'unknown' |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
386 |
return False |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
387 |
except AttributeError: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
388 |
def _handlesarg(func, arg): |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
389 |
""" Try to determine if func accepts arg |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
390 |
|
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
391 |
If it takes arg, return True |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
392 |
If it happens to take **args, then it could do anything: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
393 |
* It could throw a different TypeError, just for fun |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
394 |
* It could throw an ArgumentError or anything else |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
395 |
* It could choose not to throw an Exception at all |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
396 |
... return 'unknown' |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
397 |
|
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
398 |
Otherwise, return False |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
399 |
""" |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
400 |
spec = inspect.getargspec(func) |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
401 |
if arg in spec.args: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
402 |
return True |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
403 |
if spec.keywords: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
404 |
return 'unknown' |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
405 |
return False |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
406 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
407 |
class HTTPConnection(object): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
408 |
"""Connection to a single http server. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
409 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
410 |
Supports 100-continue and keepalives natively. Uses select() for |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
411 |
non-blocking socket operations. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
412 |
""" |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
413 |
http_version = HTTP_VER_1_1 |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
414 |
response_class = HTTPResponse |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
415 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
416 |
def __init__(self, host, port=None, use_ssl=None, ssl_validator=None, |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
417 |
timeout=TIMEOUT_DEFAULT, |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
418 |
continue_timeout=TIMEOUT_ASSUME_CONTINUE, |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
419 |
proxy_hostport=None, proxy_headers=None, |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
420 |
ssl_wrap_socket=None, **ssl_opts): |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
421 |
"""Create a new HTTPConnection. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
422 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
423 |
Args: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
424 |
host: The host to which we'll connect. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
425 |
port: Optional. The port over which we'll connect. Default 80 for |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
426 |
non-ssl, 443 for ssl. |
17424
e7cfe3587ea4
fix trivial spelling errors
Mads Kiilerich <mads@kiilerich.com>
parents:
16774
diff
changeset
|
427 |
use_ssl: Optional. Whether to use ssl. Defaults to False if port is |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
428 |
not 443, true if port is 443. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
429 |
ssl_validator: a function(socket) to validate the ssl cert |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
430 |
timeout: Optional. Connection timeout, default is TIMEOUT_DEFAULT. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
431 |
continue_timeout: Optional. Timeout for waiting on an expected |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
432 |
"100 Continue" response. Default is TIMEOUT_ASSUME_CONTINUE. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
433 |
proxy_hostport: Optional. Tuple of (host, port) to use as an http |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
434 |
proxy for the connection. Default is to not use a proxy. |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
435 |
proxy_headers: Optional dict of header keys and values to send to |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
436 |
a proxy when using CONNECT. For compatibility with |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
437 |
httplib, the Proxy-Authorization header may be |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
438 |
specified in headers for request(), which will clobber |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
439 |
any such header specified here if specified. Providing |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
440 |
this option and not proxy_hostport will raise an |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
441 |
ValueError. |
19807
c48df403caae
httpclient: import 4bb625347d4a to provide SSL wrapper injection
Augie Fackler <raf@durin42.com>
parents:
19620
diff
changeset
|
442 |
ssl_wrap_socket: Optional function to use for wrapping |
c48df403caae
httpclient: import 4bb625347d4a to provide SSL wrapper injection
Augie Fackler <raf@durin42.com>
parents:
19620
diff
changeset
|
443 |
sockets. If unspecified, the one from the ssl module will |
c48df403caae
httpclient: import 4bb625347d4a to provide SSL wrapper injection
Augie Fackler <raf@durin42.com>
parents:
19620
diff
changeset
|
444 |
be used if available, or something that's compatible with |
c48df403caae
httpclient: import 4bb625347d4a to provide SSL wrapper injection
Augie Fackler <raf@durin42.com>
parents:
19620
diff
changeset
|
445 |
it if on a Python older than 2.6. |
c48df403caae
httpclient: import 4bb625347d4a to provide SSL wrapper injection
Augie Fackler <raf@durin42.com>
parents:
19620
diff
changeset
|
446 |
|
c48df403caae
httpclient: import 4bb625347d4a to provide SSL wrapper injection
Augie Fackler <raf@durin42.com>
parents:
19620
diff
changeset
|
447 |
Any extra keyword arguments to this function will be provided |
c48df403caae
httpclient: import 4bb625347d4a to provide SSL wrapper injection
Augie Fackler <raf@durin42.com>
parents:
19620
diff
changeset
|
448 |
to the ssl_wrap_socket method. If no ssl |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
449 |
""" |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
450 |
host = _ensurebytes(host) |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
451 |
if port is None and host.count(b':') == 1 or b']:' in host: |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
452 |
host, port = host.rsplit(b':', 1) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
453 |
port = int(port) |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
454 |
if b'[' in host: |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
455 |
host = host[1:-1] |
19807
c48df403caae
httpclient: import 4bb625347d4a to provide SSL wrapper injection
Augie Fackler <raf@durin42.com>
parents:
19620
diff
changeset
|
456 |
if ssl_wrap_socket is not None: |
29131
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
457 |
_wrap_socket = ssl_wrap_socket |
19807
c48df403caae
httpclient: import 4bb625347d4a to provide SSL wrapper injection
Augie Fackler <raf@durin42.com>
parents:
19620
diff
changeset
|
458 |
else: |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
459 |
_wrap_socket = ssl.wrap_socket |
29131
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
460 |
call_wrap_socket = None |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
461 |
handlesubar = _handlesarg(_wrap_socket, 'server_hostname') |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
462 |
if handlesubar is True: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
463 |
# supports server_hostname |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
464 |
call_wrap_socket = _wrap_socket |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
465 |
handlesnobar = _handlesarg(_wrap_socket, 'serverhostname') |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
466 |
if handlesnobar is True and handlesubar is not True: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
467 |
# supports serverhostname |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
468 |
def call_wrap_socket(sock, server_hostname=None, **ssl_opts): |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
469 |
return _wrap_socket(sock, serverhostname=server_hostname, |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
470 |
**ssl_opts) |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
471 |
if handlesubar is False and handlesnobar is False: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
472 |
# does not support either |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
473 |
def call_wrap_socket(sock, server_hostname=None, **ssl_opts): |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
474 |
return _wrap_socket(sock, **ssl_opts) |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
475 |
if call_wrap_socket is None: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
476 |
# we assume it takes **args |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
477 |
def call_wrap_socket(sock, **ssl_opts): |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
478 |
if 'server_hostname' in ssl_opts: |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
479 |
ssl_opts['serverhostname'] = ssl_opts['server_hostname'] |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
480 |
return _wrap_socket(sock, **ssl_opts) |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
481 |
self._ssl_wrap_socket = call_wrap_socket |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
482 |
if use_ssl is None and port is None: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
483 |
use_ssl = False |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
484 |
port = 80 |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
485 |
elif use_ssl is None: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
486 |
use_ssl = (port == 443) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
487 |
elif port is None: |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
488 |
port = (use_ssl and 443 or 80) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
489 |
self.port = port |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
490 |
self.ssl = use_ssl |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
491 |
self.ssl_opts = ssl_opts |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
492 |
self._ssl_validator = ssl_validator |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
493 |
self.host = host |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
494 |
self.sock = None |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
495 |
self._current_response = None |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
496 |
self._current_response_taken = False |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
497 |
if proxy_hostport is None: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
498 |
self._proxy_host = self._proxy_port = None |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
499 |
if proxy_headers: |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
500 |
raise ValueError( |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
501 |
'proxy_headers may not be specified unless ' |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
502 |
'proxy_hostport is also specified.') |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
503 |
else: |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
504 |
self._proxy_headers = {} |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
505 |
else: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
506 |
self._proxy_host, self._proxy_port = proxy_hostport |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
507 |
self._proxy_headers = _foldheaders(proxy_headers or {}) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
508 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
509 |
self.timeout = timeout |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
510 |
self.continue_timeout = continue_timeout |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
511 |
|
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
512 |
def _connect(self, proxy_headers): |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
513 |
"""Connect to the host and port specified in __init__.""" |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
514 |
if self.sock: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
515 |
return |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
516 |
if self._proxy_host is not None: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
517 |
logger.info('Connecting to http proxy %s:%s', |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
518 |
self._proxy_host, self._proxy_port) |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
519 |
sock = socket.create_connection((self._proxy_host, |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
520 |
self._proxy_port)) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
521 |
if self.ssl: |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
522 |
data = self._buildheaders(b'CONNECT', b'%s:%d' % (self.host, |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
523 |
self.port), |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
524 |
proxy_headers, HTTP_VER_1_0) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
525 |
sock.send(data) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
526 |
sock.setblocking(0) |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
527 |
r = self.response_class(sock, self.timeout, b'CONNECT') |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
528 |
timeout_exc = HTTPTimeoutException( |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
529 |
'Timed out waiting for CONNECT response from proxy') |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
530 |
while not r.complete(): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
531 |
try: |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
532 |
# We're a friend of the response class, so let |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
533 |
# us use the private attribute. |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
534 |
# pylint: disable=W0212 |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
535 |
if not r._select(): |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
536 |
if not r.complete(): |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
537 |
raise timeout_exc |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
538 |
except HTTPTimeoutException: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
539 |
# This raise/except pattern looks goofy, but |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
540 |
# _select can raise the timeout as well as the |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
541 |
# loop body. I wish it wasn't this convoluted, |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
542 |
# but I don't have a better solution |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
543 |
# immediately handy. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
544 |
raise timeout_exc |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
545 |
if r.status != 200: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
546 |
raise HTTPProxyConnectFailedException( |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
547 |
'Proxy connection failed: %d %s' % (r.status, |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
548 |
r.read())) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
549 |
logger.info('CONNECT (for SSL) to %s:%s via proxy succeeded.', |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
550 |
self.host, self.port) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
551 |
else: |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
552 |
sock = socket.create_connection((self.host, self.port)) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
553 |
if self.ssl: |
16774
69af967b6d6f
httpclient: update to c5abd358e543 of httpplus
Augie Fackler <raf@durin42.com>
parents:
16643
diff
changeset
|
554 |
# This is the default, but in the case of proxied SSL |
69af967b6d6f
httpclient: update to c5abd358e543 of httpplus
Augie Fackler <raf@durin42.com>
parents:
16643
diff
changeset
|
555 |
# requests the proxy logic above will have cleared |
17424
e7cfe3587ea4
fix trivial spelling errors
Mads Kiilerich <mads@kiilerich.com>
parents:
16774
diff
changeset
|
556 |
# blocking mode, so re-enable it just to be safe. |
16774
69af967b6d6f
httpclient: update to c5abd358e543 of httpplus
Augie Fackler <raf@durin42.com>
parents:
16643
diff
changeset
|
557 |
sock.setblocking(1) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
558 |
logger.debug('wrapping socket for ssl with options %r', |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
559 |
self.ssl_opts) |
29131
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
560 |
sock = self._ssl_wrap_socket(sock, server_hostname=self.host, |
8a66eda46c98
httpclient: update to upstream revision 2995635573d2
Augie Fackler <augie@google.com>
parents:
28997
diff
changeset
|
561 |
**self.ssl_opts) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
562 |
if self._ssl_validator: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
563 |
self._ssl_validator(sock) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
564 |
sock.setblocking(0) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
565 |
self.sock = sock |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
566 |
|
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
567 |
def _buildheaders(self, method, path, headers, http_ver): |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
568 |
if self.ssl and self.port == 443 or self.port == 80: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
569 |
# default port for protocol, so leave it out |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
570 |
hdrhost = self.host |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
571 |
else: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
572 |
# include nonstandard port in header |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
573 |
if b':' in self.host: # must be IPv6 |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
574 |
hdrhost = b'[%s]:%d' % (self.host, self.port) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
575 |
else: |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
576 |
hdrhost = b'%s:%d' % (self.host, self.port) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
577 |
if self._proxy_host and not self.ssl: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
578 |
# When talking to a regular http proxy we must send the |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
579 |
# full URI, but in all other cases we must not (although |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
580 |
# technically RFC 2616 says servers must accept our |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
581 |
# request if we screw up, experimentally few do that |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
582 |
# correctly.) |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
583 |
assert path[0:1] == b'/', 'path must start with a /' |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
584 |
path = b'http://%s%s' % (hdrhost, path) |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
585 |
outgoing = [b'%s %s %s%s' % (method, path, http_ver, EOL)] |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
586 |
headers[b'host'] = (b'Host', hdrhost) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
587 |
headers[HDR_ACCEPT_ENCODING] = (HDR_ACCEPT_ENCODING, 'identity') |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
588 |
for hdr, val in sorted((_ensurebytes(h), _ensurebytes(v)) |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
589 |
for h, v in headers.values()): |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
590 |
outgoing.append(b'%s: %s%s' % (hdr, val, EOL)) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
591 |
outgoing.append(EOL) |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
592 |
return b''.join(outgoing) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
593 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
594 |
def close(self): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
595 |
"""Close the connection to the server. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
596 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
597 |
This is a no-op if the connection is already closed. The |
17536 | 598 |
connection may automatically close if requested by the server |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
599 |
or required by the nature of a response. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
600 |
""" |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
601 |
if self.sock is None: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
602 |
return |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
603 |
self.sock.close() |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
604 |
self.sock = None |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
605 |
logger.info('closed connection to %s on %s', self.host, self.port) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
606 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
607 |
def busy(self): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
608 |
"""Returns True if this connection object is currently in use. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
609 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
610 |
If a response is still pending, this will return True, even if |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
611 |
the request has finished sending. In the future, |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
612 |
HTTPConnection may transparently juggle multiple connections |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
613 |
to the server, in which case this will be useful to detect if |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
614 |
any of those connections is ready for use. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
615 |
""" |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
616 |
cr = self._current_response |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
617 |
if cr is not None: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
618 |
if self._current_response_taken: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
619 |
if cr.will_close: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
620 |
self.sock = None |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
621 |
self._current_response = None |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
622 |
return False |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
623 |
elif cr.complete(): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
624 |
self._current_response = None |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
625 |
return False |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
626 |
return True |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
627 |
return False |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
628 |
|
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
629 |
def _reconnect(self, where, pheaders): |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
630 |
logger.info('reconnecting during %s', where) |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
631 |
self.close() |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
632 |
self._connect(pheaders) |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
633 |
|
31411
a53f2d4c734f
httpclient: don't use mutable default argument value
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
29442
diff
changeset
|
634 |
def request(self, method, path, body=None, headers=None, |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
635 |
expect_continue=False): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
636 |
"""Send a request to the server. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
637 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
638 |
For increased flexibility, this does not return the response |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
639 |
object. Future versions of HTTPConnection that juggle multiple |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
640 |
sockets will be able to send (for example) 5 requests all at |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
641 |
once, and then let the requests arrive as data is |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
642 |
available. Use the `getresponse()` method to retrieve the |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
643 |
response. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
644 |
""" |
31411
a53f2d4c734f
httpclient: don't use mutable default argument value
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
29442
diff
changeset
|
645 |
if headers is None: |
a53f2d4c734f
httpclient: don't use mutable default argument value
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents:
29442
diff
changeset
|
646 |
headers = {} |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
647 |
method = _ensurebytes(method) |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
648 |
path = _ensurebytes(path) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
649 |
if self.busy(): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
650 |
raise httplib.CannotSendRequest( |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
651 |
'Can not send another request before ' |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
652 |
'current response is read!') |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
653 |
self._current_response_taken = False |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
654 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
655 |
logger.info('sending %s request for %s to %s on port %s', |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
656 |
method, path, self.host, self.port) |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
657 |
|
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
658 |
hdrs = _foldheaders(headers) |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
659 |
# Figure out headers that have to be computed from the request |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
660 |
# body. |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
661 |
chunked = False |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
662 |
if body and HDR_CONTENT_LENGTH not in hdrs: |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
663 |
if getattr(body, '__len__', False): |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
664 |
hdrs[HDR_CONTENT_LENGTH] = (HDR_CONTENT_LENGTH, |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
665 |
b'%d' % len(body)) |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
666 |
elif getattr(body, 'read', False): |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
667 |
hdrs[HDR_XFER_ENCODING] = (HDR_XFER_ENCODING, |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
668 |
XFER_ENCODING_CHUNKED) |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
669 |
chunked = True |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
670 |
else: |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
671 |
raise BadRequestData('body has no __len__() nor read()') |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
672 |
# Figure out expect-continue header |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
673 |
if hdrs.get('expect', ('', ''))[1].lower() == b'100-continue': |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
674 |
expect_continue = True |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
675 |
elif expect_continue: |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
676 |
hdrs['expect'] = (b'Expect', b'100-Continue') |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
677 |
# httplib compatibility: if the user specified a |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
678 |
# proxy-authorization header, that's actually intended for a |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
679 |
# proxy CONNECT action, not the real request, but only if |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
680 |
# we're going to use a proxy. |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
681 |
pheaders = dict(self._proxy_headers) |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
682 |
if self._proxy_host and self.ssl: |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
683 |
pa = hdrs.pop('proxy-authorization', None) |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
684 |
if pa is not None: |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
685 |
pheaders['proxy-authorization'] = pa |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
686 |
# Build header data |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
687 |
outgoing_headers = self._buildheaders( |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
688 |
method, path, hdrs, self.http_version) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
689 |
|
19620
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
690 |
# If we're reusing the underlying socket, there are some |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
691 |
# conditions where we'll want to retry, so make a note of the |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
692 |
# state of self.sock |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
693 |
fresh_socket = self.sock is None |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
694 |
self._connect(pheaders) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
695 |
response = None |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
696 |
first = True |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
697 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
698 |
while ((outgoing_headers or body) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
699 |
and not (response and response.complete())): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
700 |
select_timeout = self.timeout |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
701 |
out = outgoing_headers or body |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
702 |
blocking_on_continue = False |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
703 |
if expect_continue and not outgoing_headers and not ( |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
704 |
response and (response.headers or response.continued)): |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
705 |
logger.info( |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
706 |
'waiting up to %s seconds for' |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
707 |
' continue response from server', |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
708 |
self.continue_timeout) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
709 |
select_timeout = self.continue_timeout |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
710 |
blocking_on_continue = True |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
711 |
out = False |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
712 |
if out: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
713 |
w = [self.sock] |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
714 |
else: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
715 |
w = [] |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
716 |
r, w, x = select.select([self.sock], w, [], select_timeout) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
717 |
# if we were expecting a 100 continue and it's been long |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
718 |
# enough, just go ahead and assume it's ok. This is the |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
719 |
# recommended behavior from the RFC. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
720 |
if r == w == x == []: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
721 |
if blocking_on_continue: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
722 |
expect_continue = False |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
723 |
logger.info('no response to continue expectation from ' |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
724 |
'server, optimistically sending request body') |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
725 |
else: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
726 |
raise HTTPTimeoutException('timeout sending data') |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
727 |
was_first = first |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
728 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
729 |
# incoming data |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
730 |
if r: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
731 |
try: |
14341
5c3de67e7402
httpclient: import revision b8c3511a8cae from py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14293
diff
changeset
|
732 |
try: |
5c3de67e7402
httpclient: import revision b8c3511a8cae from py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14293
diff
changeset
|
733 |
data = r[0].recv(INCOMING_BUFFER_SIZE) |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
734 |
except ssl.SSLError as e: |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
735 |
if e.args[0] != ssl.SSL_ERROR_WANT_READ: |
14341
5c3de67e7402
httpclient: import revision b8c3511a8cae from py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14293
diff
changeset
|
736 |
raise |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
737 |
logger.debug('SSL_ERROR_WANT_READ while sending ' |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
738 |
'data, retrying...') |
14341
5c3de67e7402
httpclient: import revision b8c3511a8cae from py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14293
diff
changeset
|
739 |
continue |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
740 |
if not data: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
741 |
logger.info('socket appears closed in read') |
14376
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
742 |
self.sock = None |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
743 |
self._current_response = None |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
744 |
if response is not None: |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
745 |
# We're a friend of the response class, so let |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
746 |
# us use the private attribute. |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
747 |
# pylint: disable=W0212 |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
748 |
response._close() |
14376
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
749 |
# This if/elif ladder is a bit subtle, |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
750 |
# comments in each branch should help. |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
751 |
if response is not None and response.complete(): |
14376
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
752 |
# Server responded completely and then |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
753 |
# closed the socket. We should just shut |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
754 |
# things down and let the caller get their |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
755 |
# response. |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
756 |
logger.info('Got an early response, ' |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
757 |
'aborting remaining request.') |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
758 |
break |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
759 |
elif was_first and response is None: |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
760 |
# Most likely a keepalive that got killed |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
761 |
# on the server's end. Commonly happens |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
762 |
# after getting a really large response |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
763 |
# from the server. |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
764 |
logger.info( |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
765 |
'Connection appeared closed in read on first' |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
766 |
' request loop iteration, will retry.') |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
767 |
self._reconnect('read', pheaders) |
14376
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
768 |
continue |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
769 |
else: |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
770 |
# We didn't just send the first data hunk, |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
771 |
# and either have a partial response or no |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
772 |
# response at all. There's really nothing |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
773 |
# meaningful we can do here. |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
774 |
raise HTTPStateError( |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
775 |
'Connection appears closed after ' |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
776 |
'some request data was written, but the ' |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
777 |
'response was missing or incomplete!') |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
778 |
logger.debug('read %d bytes in request()', len(data)) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
779 |
if response is None: |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
780 |
response = self.response_class( |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
781 |
r[0], self.timeout, method) |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
782 |
# We're a friend of the response class, so let us |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
783 |
# use the private attribute. |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
784 |
# pylint: disable=W0212 |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
785 |
response._load_response(data) |
14376
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
786 |
# Jump to the next select() call so we load more |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
787 |
# data if the server is still sending us content. |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
788 |
continue |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
24306
diff
changeset
|
789 |
except socket.error as e: |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
790 |
if e[0] != errno.EPIPE and not was_first: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
791 |
raise |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
792 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
793 |
# outgoing data |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
794 |
if w and out: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
795 |
try: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
796 |
if getattr(out, 'read', False): |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
797 |
# pylint guesses the type of out incorrectly here |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
798 |
# pylint: disable=E1103 |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
799 |
data = out.read(OUTGOING_BUFFER_SIZE) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
800 |
if not data: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
801 |
continue |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
802 |
if len(data) < OUTGOING_BUFFER_SIZE: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
803 |
if chunked: |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
804 |
body = b'0' + EOL + EOL |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
805 |
else: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
806 |
body = None |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
807 |
if chunked: |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
808 |
# This encode is okay because we know |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
809 |
# hex() is building us only 0-9 and a-f |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
810 |
# digits. |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
811 |
asciilen = hex(len(data))[2:].encode('ascii') |
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
812 |
out = asciilen + EOL + data + EOL |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
813 |
else: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
814 |
out = data |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
815 |
amt = w[0].send(out) |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
24306
diff
changeset
|
816 |
except socket.error as e: |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
817 |
if e[0] == ssl.SSL_ERROR_WANT_WRITE and self.ssl: |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
818 |
# This means that SSL hasn't flushed its buffer into |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
819 |
# the socket yet. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
820 |
# TODO: find a way to block on ssl flushing its buffer |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
821 |
# similar to selecting on a raw socket. |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
822 |
continue |
19489
42fcb2f7787d
httpclient: update to revision 9517a2b56fe9 of httpplus (issue3905)
Augie Fackler <raf@durin42.com>
parents:
19182
diff
changeset
|
823 |
if e[0] == errno.EWOULDBLOCK or e[0] == errno.EAGAIN: |
42fcb2f7787d
httpclient: update to revision 9517a2b56fe9 of httpplus (issue3905)
Augie Fackler <raf@durin42.com>
parents:
19182
diff
changeset
|
824 |
continue |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
825 |
elif (e[0] not in (errno.ECONNRESET, errno.EPIPE) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
826 |
and not first): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
827 |
raise |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
828 |
self._reconnect('write', pheaders) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
829 |
amt = self.sock.send(out) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
830 |
logger.debug('sent %d', amt) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
831 |
first = False |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
832 |
if out is body: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
833 |
body = out[amt:] |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
834 |
else: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
835 |
outgoing_headers = out[amt:] |
29442
456609cbd840
httpclient: update to 54868ef054d2 of httpplus
Augie Fackler <raf@durin42.com>
parents:
29131
diff
changeset
|
836 |
# End of request-sending loop. |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
837 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
838 |
# close if the server response said to or responded before eating |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
839 |
# the whole request |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
840 |
if response is None: |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
841 |
response = self.response_class(self.sock, self.timeout, method) |
19620
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
842 |
if not fresh_socket: |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
843 |
if not response._select(): |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
844 |
# This means the response failed to get any response |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
845 |
# data at all, and in all probability the socket was |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
846 |
# closed before the server even saw our request. Try |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
847 |
# the request again on a fresh socket. |
27601
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
848 |
logger.debug('response._select() failed during request().' |
1ad9da968a2e
httpclient: update to 938f2107d6e2 of httpplus
Augie Fackler <augie@google.com>
parents:
25660
diff
changeset
|
849 |
' Assuming request needs to be retried.') |
19620
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
850 |
self.sock = None |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
851 |
# Call this method explicitly to re-try the |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
852 |
# request. We don't use self.request() because |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
853 |
# some tools (notably Mercurial) expect to be able |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
854 |
# to subclass and redefine request(), and they |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
855 |
# don't have the same argspec as we do. |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
856 |
# |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
857 |
# TODO restructure sending of requests to avoid |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
858 |
# this recursion |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
859 |
return HTTPConnection.request( |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
860 |
self, method, path, body=body, headers=headers, |
d4a0055af149
httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response
Augie Fackler <raf@durin42.com>
parents:
19489
diff
changeset
|
861 |
expect_continue=expect_continue) |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
862 |
data_left = bool(outgoing_headers or body) |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
863 |
if data_left: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
864 |
logger.info('stopped sending request early, ' |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
865 |
'will close the socket to be safe.') |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
866 |
response.will_close = True |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
867 |
if response.will_close: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
868 |
# The socket will be closed by the response, so we disown |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
869 |
# the socket |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
870 |
self.sock = None |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
871 |
self._current_response = response |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
872 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
873 |
def getresponse(self): |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
874 |
"""Returns the response to the most recent request.""" |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
875 |
if self._current_response is None: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
876 |
raise httplib.ResponseNotReady() |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
877 |
r = self._current_response |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
878 |
while r.headers is None: |
19182
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
879 |
# We're a friend of the response class, so let us use the |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
880 |
# private attribute. |
fae47ecaa952
httpclient: upgrade to fe8c09e4db64 of httpplus
Augie Fackler <raf@durin42.com>
parents:
19038
diff
changeset
|
881 |
# pylint: disable=W0212 |
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
882 |
if not r._select() and not r.complete(): |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
883 |
raise _readers.HTTPRemoteClosedError() |
14293
9adbb5ef0964
httpclient: import f4c380237fd5 to fix keepalive not working
Augie Fackler <durin42@gmail.com>
parents:
14243
diff
changeset
|
884 |
if r.will_close: |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
885 |
self.sock = None |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
886 |
self._current_response = None |
14293
9adbb5ef0964
httpclient: import f4c380237fd5 to fix keepalive not working
Augie Fackler <durin42@gmail.com>
parents:
14243
diff
changeset
|
887 |
elif r.complete(): |
9adbb5ef0964
httpclient: import f4c380237fd5 to fix keepalive not working
Augie Fackler <durin42@gmail.com>
parents:
14243
diff
changeset
|
888 |
self._current_response = None |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
889 |
else: |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
890 |
self._current_response_taken = True |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
891 |
return r |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
892 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
893 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
894 |
class HTTPTimeoutException(httplib.HTTPException): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
895 |
"""A timeout occurred while waiting on the server.""" |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
896 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
897 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
898 |
class BadRequestData(httplib.HTTPException): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
899 |
"""Request body object has neither __len__ nor read.""" |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
900 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
901 |
|
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
902 |
class HTTPProxyConnectFailedException(httplib.HTTPException): |
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
903 |
"""Connecting to the HTTP proxy failed.""" |
14376
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
904 |
|
15218
c81dce8a7bb6
httpclient: update to 07d8c356f4d1 of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14376
diff
changeset
|
905 |
|
14376
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
906 |
class HTTPStateError(httplib.HTTPException): |
a75e0f4ba0ab
httpclient: import revision fc731618702a of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14341
diff
changeset
|
907 |
"""Invalid internal state encountered.""" |
15218
c81dce8a7bb6
httpclient: update to 07d8c356f4d1 of py-nonblocking-http
Augie Fackler <durin42@gmail.com>
parents:
14376
diff
changeset
|
908 |
|
16643
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
909 |
# Forward this exception type from _readers since it needs to be part |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
910 |
# of the public API. |
24dbef11f477
httpclient: update to revision 892730fe7f46 of httpplus
Augie Fackler <raf@durin42.com>
parents:
15218
diff
changeset
|
911 |
HTTPRemoteClosedError = _readers.HTTPRemoteClosedError |
14243
861f28212398
Import new http library as mercurial.httpclient.
Augie Fackler <durin42@gmail.com>
parents:
diff
changeset
|
912 |
# no-check-code |