Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
988dbd7b
Commit
988dbd7b
authored
Dec 17, 2010
by
Antoine Pitrou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #10711: Remove HTTP 0.9 support from http.client. The `strict`
parameter to HTTPConnection and friends is deprecated.
parent
7cb3051d
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
63 additions
and
120 deletions
+63
-120
Doc/library/http.client.rst
Doc/library/http.client.rst
+16
-7
Lib/http/client.py
Lib/http/client.py
+23
-110
Lib/test/test_urllib.py
Lib/test/test_urllib.py
+20
-3
Misc/NEWS
Misc/NEWS
+4
-0
No files found.
Doc/library/http.client.rst
View file @
988dbd7b
...
...
@@ -23,16 +23,13 @@ HTTPS protocols. It is normally not used directly --- the module
The module provides the following classes:
.. class:: HTTPConnection(host, port=None
, strict=None[, timeout[, source_address
]])
.. class:: HTTPConnection(host, port=None
[, strict[, timeout[, source_address]
]])
An :class:`HTTPConnection` instance represents one transaction with an HTTP
server. It should be instantiated passing it a host and optional port
number. If no port number is passed, the port is extracted from the host
string if it has the form ``host:port``, else the default HTTP port (80) is
used. When True, the optional parameter *strict* (which defaults to a false
value) causes ``BadStatusLine`` to
be raised if the status line can't be parsed as a valid HTTP/1.0 or 1.1
status line. If the optional *timeout* parameter is given, blocking
used. If the optional *timeout* parameter is given, blocking
operations (like connection attempts) will timeout after that many seconds
(if it is not given, the global default timeout setting is used).
The optional *source_address* parameter may be a typle of a (host, port)
...
...
@@ -49,8 +46,12 @@ The module provides the following classes:
.. versionchanged:: 3.2
*source_address* was added.
.. versionchanged:: 3.2
The *strict* parameter is deprecated. HTTP 0.9-style "Simple Responses"
are not supported anymore.
.. class:: HTTPSConnection(host, port=None, key_file=None, cert_file=None
, strict=None[, timeout[, source_address
]], *, context=None, check_hostname=None)
.. class:: HTTPSConnection(host, port=None, key_file=None, cert_file=None
[, strict[, timeout[, source_address]
]], *, context=None, check_hostname=None)
A subclass of :class:`HTTPConnection` that uses SSL for communication with
secure servers. Default port is ``443``. If *context* is specified, it
...
...
@@ -80,12 +81,20 @@ The module provides the following classes:
This class now supports HTTPS virtual hosts if possible (that is,
if :data:`ssl.HAS_SNI` is true).
.. versionchanged:: 3.2
The *strict* parameter is deprecated. HTTP 0.9-style "Simple Responses"
are not supported anymore.
.. class:: HTTPResponse(sock, debuglevel=0
, strict=0
, method=None, url=None)
.. class:: HTTPResponse(sock, debuglevel=0
[, strict]
, method=None, url=None)
Class whose instances are returned upon successful connection. Not
instantiated directly by user.
.. versionchanged:: 3.2
The *strict* parameter is deprecated. HTTP 0.9-style "Simple Responses"
are not supported anymore.
The following exceptions are raised as appropriate:
...
...
Lib/http/client.py
View file @
988dbd7b
...
...
@@ -252,13 +252,10 @@ def parse_headers(fp, _class=HTTPMessage):
hstring
=
b''
.
join
(
headers
).
decode
(
'iso-8859-1'
)
return
email
.
parser
.
Parser
(
_class
=
_class
).
parsestr
(
hstring
)
class
HTTPResponse
(
io
.
RawIOBase
):
# strict: If true, raise BadStatusLine if the status line can't be
# parsed as a valid HTTP/1.0 or 1.1 status line. By default it is
# false because it prevents clients from talking to HTTP/0.9
# servers. Note that a response with a sufficiently corrupted
# status line will look like an HTTP/0.9 response.
_strict_sentinel
=
object
()
class
HTTPResponse
(
io
.
RawIOBase
):
# See RFC 2616 sec 19.6 and RFC 1945 sec 6 for details.
...
...
@@ -267,7 +264,7 @@ class HTTPResponse(io.RawIOBase):
# text following RFC 2047. The basic status line parsing only
# accepts iso-8859-1.
def
__init__
(
self
,
sock
,
debuglevel
=
0
,
strict
=
0
,
method
=
None
,
url
=
None
):
def
__init__
(
self
,
sock
,
debuglevel
=
0
,
strict
=
_strict_sentinel
,
method
=
None
,
url
=
None
):
# If the response includes a content-length header, we need to
# make sure that the client doesn't read more than the
# specified number of bytes. If it does, it will block until
...
...
@@ -277,7 +274,10 @@ class HTTPResponse(io.RawIOBase):
# clients unless they know what they are doing.
self
.
fp
=
sock
.
makefile
(
"rb"
)
self
.
debuglevel
=
debuglevel
self
.
strict
=
strict
if
strict
is
not
_strict_sentinel
:
warnings
.
warn
(
"the 'strict' argument isn't supported anymore; "
"http.client now always assumes HTTP/1.x compliant servers."
,
DeprecationWarning
,
2
)
self
.
_method
=
method
# The HTTPResponse object is returned via urllib. The clients
...
...
@@ -299,7 +299,6 @@ class HTTPResponse(io.RawIOBase):
self
.
will_close
=
_UNKNOWN
# conn will close at end of response
def
_read_status
(
self
):
# Initialize with Simple-Response defaults.
line
=
str
(
self
.
fp
.
readline
(),
"iso-8859-1"
)
if
self
.
debuglevel
>
0
:
print
(
"reply:"
,
repr
(
line
))
...
...
@@ -308,25 +307,17 @@ class HTTPResponse(io.RawIOBase):
# sending a valid response.
raise
BadStatusLine
(
line
)
try
:
[
version
,
status
,
reason
]
=
line
.
split
(
None
,
2
)
version
,
status
,
reason
=
line
.
split
(
None
,
2
)
except
ValueError
:
try
:
[
version
,
status
]
=
line
.
split
(
None
,
1
)
version
,
status
=
line
.
split
(
None
,
1
)
reason
=
""
except
ValueError
:
# empty version will cause next test to fail and status
# will be treated as 0.9 response.
# empty version will cause next test to fail.
version
=
""
if
not
version
.
startswith
(
"HTTP/"
):
if
self
.
strict
:
self
.
close
()
raise
BadStatusLine
(
line
)
else
:
# Assume it's a Simple-Response from an 0.9 server.
# We have to convert the first line back to raw bytes
# because self.fp.readline() needs to return bytes.
self
.
fp
=
LineAndFileWrapper
(
bytes
(
line
,
"ascii"
),
self
.
fp
)
return
"HTTP/0.9"
,
200
,
""
self
.
close
()
raise
BadStatusLine
(
line
)
# The status code is a three-digit number
try
:
...
...
@@ -357,22 +348,14 @@ class HTTPResponse(io.RawIOBase):
self
.
code
=
self
.
status
=
status
self
.
reason
=
reason
.
strip
()
if
version
==
"HTTP/1.0"
:
if
version
in
(
"HTTP/1.0"
,
"HTTP/0.9"
):
# Some servers might still return "0.9", treat it as 1.0 anyway
self
.
version
=
10
elif
version
.
startswith
(
"HTTP/1."
):
self
.
version
=
11
# use HTTP/1.1 code for HTTP/1.x where x>=1
elif
version
==
"HTTP/0.9"
:
self
.
version
=
9
else
:
raise
UnknownProtocol
(
version
)
if
self
.
version
==
9
:
self
.
length
=
None
self
.
chunked
=
False
self
.
will_close
=
True
self
.
headers
=
self
.
msg
=
email
.
message_from_string
(
''
)
return
self
.
headers
=
self
.
msg
=
parse_headers
(
self
.
fp
)
if
self
.
debuglevel
>
0
:
...
...
@@ -639,10 +622,13 @@ class HTTPConnection:
default_port
=
HTTP_PORT
auto_open
=
1
debuglevel
=
0
strict
=
0
def
__init__
(
self
,
host
,
port
=
None
,
strict
=
None
,
def
__init__
(
self
,
host
,
port
=
None
,
strict
=
_strict_sentinel
,
timeout
=
socket
.
_GLOBAL_DEFAULT_TIMEOUT
,
source_address
=
None
):
if
strict
is
not
_strict_sentinel
:
warnings
.
warn
(
"the 'strict' argument isn't supported anymore; "
"http.client now always assumes HTTP/1.x compliant servers."
,
DeprecationWarning
,
2
)
self
.
timeout
=
timeout
self
.
source_address
=
source_address
self
.
sock
=
None
...
...
@@ -654,8 +640,6 @@ class HTTPConnection:
self
.
_tunnel_port
=
None
self
.
_set_hostport
(
host
,
port
)
if
strict
is
not
None
:
self
.
strict
=
strict
def
set_tunnel
(
self
,
host
,
port
=
None
,
headers
=
None
):
""" Sets up the host and the port for the HTTP CONNECT Tunnelling.
...
...
@@ -700,8 +684,7 @@ class HTTPConnection:
header_bytes
=
header_str
.
encode
(
"ascii"
)
self
.
send
(
header_bytes
)
response
=
self
.
response_class
(
self
.
sock
,
strict
=
self
.
strict
,
method
=
self
.
_method
)
response
=
self
.
response_class
(
self
.
sock
,
method
=
self
.
_method
)
(
version
,
code
,
message
)
=
response
.
_read_status
()
if
code
!=
200
:
...
...
@@ -1025,11 +1008,9 @@ class HTTPConnection:
if
self
.
debuglevel
>
0
:
response
=
self
.
response_class
(
self
.
sock
,
self
.
debuglevel
,
strict
=
self
.
strict
,
method
=
self
.
_method
)
else
:
response
=
self
.
response_class
(
self
.
sock
,
strict
=
self
.
strict
,
method
=
self
.
_method
)
response
=
self
.
response_class
(
self
.
sock
,
method
=
self
.
_method
)
response
.
begin
()
assert
response
.
will_close
!=
_UNKNOWN
...
...
@@ -1057,7 +1038,7 @@ else:
# XXX Should key_file and cert_file be deprecated in favour of context?
def
__init__
(
self
,
host
,
port
=
None
,
key_file
=
None
,
cert_file
=
None
,
strict
=
None
,
timeout
=
socket
.
_GLOBAL_DEFAULT_TIMEOUT
,
strict
=
_strict_sentinel
,
timeout
=
socket
.
_GLOBAL_DEFAULT_TIMEOUT
,
source_address
=
None
,
*
,
context
=
None
,
check_hostname
=
None
):
super
(
HTTPSConnection
,
self
).
__init__
(
host
,
port
,
strict
,
timeout
,
source_address
)
...
...
@@ -1158,71 +1139,3 @@ class BadStatusLine(HTTPException):
# for backwards compatibility
error
=
HTTPException
class
LineAndFileWrapper
:
"""A limited file-like object for HTTP/0.9 responses."""
# The status-line parsing code calls readline(), which normally
# get the HTTP status line. For a 0.9 response, however, this is
# actually the first line of the body! Clients need to get a
# readable file object that contains that line.
def
__init__
(
self
,
line
,
file
):
self
.
_line
=
line
self
.
_file
=
file
self
.
_line_consumed
=
0
self
.
_line_offset
=
0
self
.
_line_left
=
len
(
line
)
def
__getattr__
(
self
,
attr
):
return
getattr
(
self
.
_file
,
attr
)
def
_done
(
self
):
# called when the last byte is read from the line. After the
# call, all read methods are delegated to the underlying file
# object.
self
.
_line_consumed
=
1
self
.
read
=
self
.
_file
.
read
self
.
readline
=
self
.
_file
.
readline
self
.
readlines
=
self
.
_file
.
readlines
def
read
(
self
,
amt
=
None
):
if
self
.
_line_consumed
:
return
self
.
_file
.
read
(
amt
)
assert
self
.
_line_left
if
amt
is
None
or
amt
>
self
.
_line_left
:
s
=
self
.
_line
[
self
.
_line_offset
:]
self
.
_done
()
if
amt
is
None
:
return
s
+
self
.
_file
.
read
()
else
:
return
s
+
self
.
_file
.
read
(
amt
-
len
(
s
))
else
:
assert
amt
<=
self
.
_line_left
i
=
self
.
_line_offset
j
=
i
+
amt
s
=
self
.
_line
[
i
:
j
]
self
.
_line_offset
=
j
self
.
_line_left
-=
amt
if
self
.
_line_left
==
0
:
self
.
_done
()
return
s
def
readline
(
self
):
if
self
.
_line_consumed
:
return
self
.
_file
.
readline
()
assert
self
.
_line_left
s
=
self
.
_line
[
self
.
_line_offset
:]
self
.
_done
()
return
s
def
readlines
(
self
,
size
=
None
):
if
self
.
_line_consumed
:
return
self
.
_file
.
readlines
(
size
)
assert
self
.
_line_left
L
=
[
self
.
_line
[
self
.
_line_offset
:]]
self
.
_done
()
if
size
is
None
:
return
L
+
self
.
_file
.
readlines
()
else
:
return
L
+
self
.
_file
.
readlines
(
size
)
Lib/test/test_urllib.py
View file @
988dbd7b
...
...
@@ -139,8 +139,10 @@ class urlopen_HttpTests(unittest.TestCase):
def
fakehttp
(
self
,
fakedata
):
class
FakeSocket
(
io
.
BytesIO
):
io_refs
=
1
def
sendall
(
self
,
str
):
pass
def
makefile
(
self
,
*
args
,
**
kwds
):
self
.
io_refs
+=
1
return
self
def
read
(
self
,
amt
=
None
):
if
self
.
closed
:
return
b""
...
...
@@ -148,6 +150,10 @@ class urlopen_HttpTests(unittest.TestCase):
def
readline
(
self
,
length
=
None
):
if
self
.
closed
:
return
b""
return
io
.
BytesIO
.
readline
(
self
,
length
)
def
close
(
self
):
self
.
io_refs
-=
1
if
self
.
io_refs
==
0
:
io
.
BytesIO
.
close
(
self
)
class
FakeHTTPConnection
(
http
.
client
.
HTTPConnection
):
def
connect
(
self
):
self
.
sock
=
FakeSocket
(
fakedata
)
...
...
@@ -157,8 +163,8 @@ class urlopen_HttpTests(unittest.TestCase):
def
unfakehttp
(
self
):
http
.
client
.
HTTPConnection
=
self
.
_connection_class
def
test_read
(
self
):
self
.
fakehttp
(
b"Hello!"
)
def
check_read
(
self
,
ver
):
self
.
fakehttp
(
b"H
TTP/"
+
ver
+
b" 200 OK
\
r
\
n
\
r
\
n
H
ello!"
)
try
:
fp
=
urlopen
(
"http://python.org/"
)
self
.
assertEqual
(
fp
.
readline
(),
b"Hello!"
)
...
...
@@ -168,6 +174,17 @@ class urlopen_HttpTests(unittest.TestCase):
finally
:
self
.
unfakehttp
()
def
test_read_0_9
(
self
):
# "0.9" response accepted (but not "simple responses" without
# a status line)
self
.
check_read
(
b"0.9"
)
def
test_read_1_0
(
self
):
self
.
check_read
(
b"1.0"
)
def
test_read_1_1
(
self
):
self
.
check_read
(
b"1.1"
)
def
test_read_bogus
(
self
):
# urlopen() should raise IOError for many error codes.
self
.
fakehttp
(
b'''HTTP/1.1 401 Authentication Required
...
...
@@ -191,7 +208,7 @@ Content-Type: text/html; charset=iso-8859-1
self
.
unfakehttp
()
def
test_userpass_inurl
(
self
):
self
.
fakehttp
(
b"Hello!"
)
self
.
fakehttp
(
b"H
TTP/1.0 200 OK
\
r
\
n
\
r
\
n
H
ello!"
)
try
:
fp
=
urlopen
(
"http://user:pass@python.org/"
)
self
.
assertEqual
(
fp
.
readline
(),
b"Hello!"
)
...
...
Misc/NEWS
View file @
988dbd7b
...
...
@@ -19,6 +19,10 @@ Core and Builtins
Library
-------
- Issue #10711: Remove HTTP 0.9 support from http.client. The ``strict``
parameter to HTTPConnection and friends is deprecated.
- Issue #9721: Fix the behavior of urljoin when the relative url starts with a
';' character. Patch by Wes Chow.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment