3 # Copyright 2007 Google Inc.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 """Copyright 2008 Python Software Foundation, Ian Bicking, and Google."""
25 SWITCHING_PROTOCOLS
= 101
30 NON_AUTHORITATIVE_INFORMATION
= 203
36 MULTIPLE_CHOICES
= 300
37 MOVED_PERMANENTLY
= 301
42 TEMPORARY_REDIRECT
= 307
45 PAYMENT_REQUIRED
= 402
48 METHOD_NOT_ALLOWED
= 405
50 PROXY_AUTHENTICATION_REQUIRED
= 407
55 PRECONDITION_FAILED
= 412
56 REQUEST_ENTITY_TOO_LARGE
= 413
57 REQUEST_URI_TOO_LONG
= 414
58 UNSUPPORTED_MEDIA_TYPE
= 415
59 REQUESTED_RANGE_NOT_SATISFIABLE
= 416
60 EXPECTATION_FAILED
= 417
61 UNPROCESSABLE_ENTITY
= 422
63 FAILED_DEPENDENCY
= 424
64 UPGRADE_REQUIRED
= 426
65 INTERNAL_SERVER_ERROR
= 500
68 SERVICE_UNAVAILABLE
= 503
70 HTTP_VERSION_NOT_SUPPORTED
= 505
71 INSUFFICIENT_STORAGE
= 507
76 101: 'Switching Protocols',
81 203: 'Non-Authoritative Information',
84 206: 'Partial Content',
86 300: 'Multiple Choices',
87 301: 'Moved Permanently',
93 307: 'Temporary Redirect',
97 402: 'Payment Required',
100 405: 'Method Not Allowed',
101 406: 'Not Acceptable',
102 407: 'Proxy Authentication Required',
103 408: 'Request Timeout',
106 411: 'Length Required',
107 412: 'Precondition Failed',
108 413: 'Request Entity Too Large',
109 414: 'Request-URI Too Long',
110 415: 'Unsupported Media Type',
111 416: 'Requested Range Not Satisfiable',
112 417: 'Expectation Failed',
114 500: 'Internal Server Error',
115 501: 'Not Implemented',
117 503: 'Service Unavailable',
118 504: 'Gateway Timeout',
119 505: 'HTTP Version Not Supported',
129 class HTTPConnection
:
133 default_port
= HTTP_PORT
134 _allow_truncated
= True
135 _follow_redirects
= False
137 def __init__(self
, host
, port
=None, strict
=False, timeout
=None):
138 from google
.appengine
.api
import urlfetch
139 self
._fetch
= urlfetch
.fetch
142 'POST': urlfetch
.POST
,
143 'HEAD': urlfetch
.HEAD
,
145 'DELETE': urlfetch
.DELETE
,
149 self
._method
= self
._url
= None
156 def request(self
, method
, url
, body
=None, headers
=None):
157 self
._method
= method
160 self
._body
= body
.read()
161 except AttributeError:
165 elif hasattr(headers
, 'items'):
166 headers
= headers
.items()
167 self
.headers
= headers
169 def putrequest(self
, request
, selector
, skip_host
=False, skip_accept_encoding
=False):
170 self
._method
= request
173 def putheader(self
, header
, *lines
):
174 line
= '\r\n\t'.join([str(line
) for line
in lines
])
175 self
.headers
.append((header
, line
))
177 def endheaders(self
):
180 def set_debuglevel(self
, level
=None):
183 def send(self
, data
):
186 def getresponse(self
):
187 if self
.port
and self
.port
!= self
.default_port
:
188 host
= '%s:%s' % (self
.host
, self
.port
)
191 if not self
._url
.startswith(self
.protocol
):
192 url
= '%s://%s%s' % (self
.protocol
, host
, self
._url
)
195 headers
= dict(self
.headers
)
198 method
= self
._method
_map
[self
._method
.upper()]
200 raise ValueError("%r is an unrecognized HTTP method" % self
._method
)
202 response
= self
._fetch
(url
, self
._body
, method
, headers
,
203 self
._allow
_truncated
, self
._follow
_redirects
)
204 return HTTPResponse(response
)
210 class HTTPSConnection(HTTPConnection
):
213 default_port
= HTTPS_PORT
215 def __init__(self
, host
, port
=None, key_file
=None, cert_file
=None,
216 strict
=False, timeout
=None):
217 if key_file
is not None or cert_file
is not None:
218 raise NotImplementedError(
219 "key_file and cert_file arguments are not implemented")
220 HTTPConnection
.__init
__(self
, host
, port
=port
, strict
=strict
,
224 class HTTPResponse(object):
226 def __init__(self
, fetch_response
):
227 self
._fetch
_response
= fetch_response
228 self
.fp
= StringIO
.StringIO(fetch_response
.content
)
230 def __getattr__(self
, attr
):
231 return getattr(self
.fp
, attr
)
233 def getheader(self
, name
, default
=None):
234 return self
._fetch
_response
.headers
.get(name
, default
)
236 def getheaders(self
):
237 return self
._fetch
_response
.headers
.items()
241 msg
= mimetools
.Message(StringIO
.StringIO(''))
242 for name
, value
in self
._fetch
_response
.headers
.items():
243 msg
[name
] = str(value
)
250 return self
._fetch
_response
.status_code
254 return responses
.get(self
._fetch
_response
.status_code
, 'Unknown')
258 "Compatibility class with httplib.py from 1.5."
261 _http_vsn_str
= 'HTTP/1.1'
265 _connection_class
= HTTPConnection
267 def __init__(self
, host
='', port
=None, strict
=None):
268 "Provide a default host, since the superclass requires one."
273 self
._setup
(self
._connection
_class
(host
, port
, strict
))
275 def _setup(self
, conn
):
278 self
.send
= conn
.send
279 self
.putrequest
= conn
.putrequest
280 self
.endheaders
= conn
.endheaders
281 self
.set_debuglevel
= conn
.set_debuglevel
283 conn
._http
_vsn
= self
._http
_vsn
284 conn
._http
_vsn
_str
= self
._http
_vsn
_str
288 def connect(self
, host
=None, port
=None):
289 "Accept arguments to set the host/port, since the superclass doesn't."
290 self
.__init
__(host
, port
)
293 "Provide a getfile, since the superclass' does not use this concept."
296 def putheader(self
, header
, *values
):
297 "The superclass allows only one value argument."
298 self
._conn
.putheader(header
, '\r\n\t'.join([str(v
) for v
in values
]))
301 """Compat definition since superclass does not define it.
303 Returns a tuple consisting of:
304 - server status code (e.g. '200' if all goes well)
305 - server "reason" corresponding to status code
306 - any RFC822 headers in the response from the server
308 response
= self
._conn
.getresponse()
310 self
.headers
= response
.msg
311 self
.file = response
.fp
312 return response
.status
, response
.reason
, response
.msg
321 """Compatibility with 1.5 httplib interface
323 Python 1.5.2 did not have an HTTPS class, but it defined an
324 interface for sending http requests that is also useful for
328 _connection_class
= HTTPSConnection
330 def __init__(self
, host
='', port
=None, key_file
=None, cert_file
=None,
332 if key_file
is not None or cert_file
is not None:
333 raise NotImplementedError(
334 "key_file and cert_file arguments are not implemented")
339 self
._setup
(self
._connection
_class
(host
, port
, key_file
,
342 self
.key_file
= key_file
343 self
.cert_file
= cert_file
346 class HTTPException(Exception):
349 class NotConnected(HTTPException
):
352 class InvalidURL(HTTPException
):
355 class UnknownProtocol(HTTPException
):
356 def __init__(self
, version
):
357 self
.version
= version
358 HTTPException
.__init
__(self
, version
)
360 class UnknownTransferEncoding(HTTPException
):
363 class UnimplementedFileMode(HTTPException
):
366 class IncompleteRead(HTTPException
):
367 def __init__(self
, partial
):
368 self
.partial
= partial
369 HTTPException
.__init
__(self
, partial
)
371 class ImproperConnectionState(HTTPException
):
374 class CannotSendRequest(ImproperConnectionState
):
377 class CannotSendHeader(ImproperConnectionState
):
380 class ResponseNotReady(ImproperConnectionState
):
383 class BadStatusLine(HTTPException
):
384 def __init__(self
, line
):
386 HTTPException
.__init
__(self
, line
)
388 error
= HTTPException