2012-07-21 02:59:43 +02:00
|
|
|
import os
|
|
|
|
import sys
|
2012-07-28 05:45:44 +02:00
|
|
|
from requests.compat import urlparse, is_windows, bytes, str
|
2012-07-21 02:59:43 +02:00
|
|
|
|
|
|
|
|
|
|
|
class Environment(object):
|
2012-07-26 06:37:03 +02:00
|
|
|
"""Holds information about the execution context.
|
|
|
|
|
|
|
|
Groups various aspects of the environment in a changeable object
|
|
|
|
and allows for mocking.
|
|
|
|
|
|
|
|
"""
|
2012-07-30 10:58:16 +02:00
|
|
|
|
|
|
|
#noinspection PyUnresolvedReferences
|
|
|
|
is_windows = is_windows
|
|
|
|
|
2012-07-27 18:08:33 +02:00
|
|
|
progname = os.path.basename(sys.argv[0])
|
|
|
|
if progname not in ['http', 'https']:
|
|
|
|
progname = 'http'
|
|
|
|
|
2012-07-21 02:59:43 +02:00
|
|
|
stdin_isatty = sys.stdin.isatty()
|
|
|
|
stdin = sys.stdin
|
|
|
|
stdout_isatty = sys.stdout.isatty()
|
|
|
|
stdout = sys.stdout
|
2012-07-24 01:09:14 +02:00
|
|
|
stderr = sys.stderr
|
|
|
|
|
2012-07-21 02:59:43 +02:00
|
|
|
# Can be set to 0 to disable colors completely.
|
|
|
|
colors = 256 if '256color' in os.environ.get('TERM', '') else 88
|
|
|
|
|
|
|
|
def __init__(self, **kwargs):
|
|
|
|
self.__dict__.update(**kwargs)
|
|
|
|
|
2012-07-30 10:58:16 +02:00
|
|
|
def init_colors(self):
|
|
|
|
# We check for real Window here, not self.is_windows as
|
|
|
|
# it could be mocked.
|
|
|
|
if (is_windows and not self.__colors_initialized
|
|
|
|
and self.stdout == sys.stdout):
|
|
|
|
import colorama.initialise
|
|
|
|
self.stdout = colorama.initialise.wrap_stream(
|
|
|
|
self.stdout, autoreset=False,
|
|
|
|
convert=None, strip=None, wrap=True)
|
|
|
|
self.__colors_initialized = True
|
|
|
|
__colors_initialized = False
|
|
|
|
|
2012-07-21 02:59:43 +02:00
|
|
|
|
|
|
|
class HTTPMessage(object):
|
|
|
|
"""Model representing an HTTP message."""
|
|
|
|
|
2012-08-01 21:13:50 +02:00
|
|
|
def __init__(self, orig):
|
|
|
|
self._orig = orig
|
|
|
|
|
|
|
|
@property
|
|
|
|
def content_type(self):
|
|
|
|
return str(self._orig.headers.get('Content-Type', ''))
|
|
|
|
|
|
|
|
|
|
|
|
class HTTPResponse(HTTPMessage):
|
|
|
|
"""A `requests.models.Response` wrapper."""
|
|
|
|
|
|
|
|
@property
|
|
|
|
def line(self):
|
|
|
|
"""Return Status-Line"""
|
|
|
|
original = self._orig.raw._original_response
|
|
|
|
return str('HTTP/{version} {status} {reason}'.format(
|
|
|
|
version='.'.join(str(original.version)),
|
|
|
|
status=original.status,
|
|
|
|
reason=original.reason
|
|
|
|
))
|
2012-07-28 05:45:44 +02:00
|
|
|
|
2012-08-01 21:13:50 +02:00
|
|
|
@property
|
|
|
|
def headers(self):
|
|
|
|
return str(self._orig.raw._original_response.msg)
|
2012-07-28 05:45:44 +02:00
|
|
|
|
2012-08-01 21:13:50 +02:00
|
|
|
@property
|
|
|
|
def encoding(self):
|
|
|
|
return self._orig.encoding or 'utf8'
|
2012-07-21 02:59:43 +02:00
|
|
|
|
2012-08-01 21:13:50 +02:00
|
|
|
@property
|
|
|
|
def body(self):
|
|
|
|
# Only now the response body is fetched.
|
|
|
|
# Shouldn't be touched unless the body is actually needed.
|
|
|
|
return self._orig.content
|
|
|
|
|
|
|
|
|
|
|
|
class HTTPRequest(HTTPMessage):
|
|
|
|
"""A `requests.models.Request` wrapper."""
|
|
|
|
|
|
|
|
@property
|
|
|
|
def line(self):
|
|
|
|
"""Return Request-Line"""
|
|
|
|
url = urlparse(self._orig.url)
|
2012-07-21 02:59:43 +02:00
|
|
|
|
2012-07-25 14:32:57 +02:00
|
|
|
# Querystring
|
|
|
|
qs = ''
|
2012-08-01 21:13:50 +02:00
|
|
|
if url.query or self._orig.params:
|
2012-07-25 14:32:57 +02:00
|
|
|
qs = '?'
|
|
|
|
if url.query:
|
|
|
|
qs += url.query
|
|
|
|
# Requests doesn't make params part of ``request.url``.
|
2012-08-01 21:13:50 +02:00
|
|
|
if self._orig.params:
|
2012-07-25 14:32:57 +02:00
|
|
|
if url.query:
|
|
|
|
qs += '&'
|
2012-07-26 00:26:23 +02:00
|
|
|
#noinspection PyUnresolvedReferences
|
2012-08-01 21:13:50 +02:00
|
|
|
qs += type(self._orig)._encode_params(self._orig.params)
|
2012-07-25 14:32:57 +02:00
|
|
|
|
|
|
|
# Request-Line
|
2012-08-01 21:13:50 +02:00
|
|
|
return str('{method} {path}{query} HTTP/1.1'.format(
|
|
|
|
method=self._orig.method,
|
2012-07-21 02:59:43 +02:00
|
|
|
path=url.path or '/',
|
2012-07-25 14:32:57 +02:00
|
|
|
query=qs
|
2012-07-28 05:45:44 +02:00
|
|
|
))
|
2012-07-25 14:32:57 +02:00
|
|
|
|
2012-08-01 21:13:50 +02:00
|
|
|
@property
|
|
|
|
def headers(self):
|
|
|
|
headers = dict(self._orig.headers)
|
2012-07-25 14:32:57 +02:00
|
|
|
content_type = headers.get('Content-Type')
|
2012-07-28 05:45:44 +02:00
|
|
|
|
|
|
|
if isinstance(content_type, bytes):
|
|
|
|
# Happens when uploading files.
|
|
|
|
# TODO: submit a bug report for Requests
|
2012-08-01 21:13:50 +02:00
|
|
|
headers['Content-Type'] = str(content_type)
|
2012-07-28 05:45:44 +02:00
|
|
|
|
2012-07-25 14:32:57 +02:00
|
|
|
if 'Host' not in headers:
|
2012-08-01 21:13:50 +02:00
|
|
|
headers['Host'] = urlparse(self._orig.url).netloc
|
|
|
|
|
|
|
|
return '\n'.join('%s: %s' % (name, value)
|
|
|
|
for name, value in headers.items())
|
|
|
|
|
|
|
|
@property
|
|
|
|
def encoding(self):
|
|
|
|
return 'utf8'
|
2012-07-25 14:32:57 +02:00
|
|
|
|
2012-08-01 21:13:50 +02:00
|
|
|
@property
|
|
|
|
def body(self):
|
|
|
|
"""Reconstruct and return the original request body bytes."""
|
|
|
|
if self._orig.files:
|
2012-08-01 00:52:30 +02:00
|
|
|
# TODO: would be nice if we didn't need to encode the files again
|
2012-08-01 21:13:50 +02:00
|
|
|
# FIXME: Also the boundary header doesn't match the one used.
|
|
|
|
for fn, fd in self._orig.files.values():
|
2012-08-01 00:52:30 +02:00
|
|
|
# Rewind the files as they have already been read before.
|
|
|
|
fd.seek(0)
|
2012-08-01 21:13:50 +02:00
|
|
|
body, _ = self._orig._encode_files(self._orig.files)
|
2012-07-28 05:45:44 +02:00
|
|
|
else:
|
|
|
|
try:
|
2012-08-01 21:13:50 +02:00
|
|
|
body = self._orig.data
|
2012-07-28 05:45:44 +02:00
|
|
|
except AttributeError:
|
|
|
|
# requests < 0.12.1
|
2012-08-01 21:13:50 +02:00
|
|
|
body = self._orig._enc_data
|
2012-07-29 06:58:50 +02:00
|
|
|
|
2012-07-28 05:45:44 +02:00
|
|
|
if isinstance(body, dict):
|
|
|
|
#noinspection PyUnresolvedReferences
|
2012-08-01 21:13:50 +02:00
|
|
|
body = type(self._orig)._encode_params(body)
|
2012-07-29 06:58:50 +02:00
|
|
|
|
|
|
|
if isinstance(body, str):
|
|
|
|
body = body.encode('utf8')
|
2012-07-21 02:59:43 +02:00
|
|
|
|
2012-08-01 21:13:50 +02:00
|
|
|
return body
|