Added support for transport adapter plugins

#276, #298
This commit is contained in:
Jakub Roztocil 2015-02-05 15:25:00 +01:00
parent b125ce5eae
commit 687a6a734d
5 changed files with 62 additions and 14 deletions

View File

@ -15,16 +15,29 @@ JSON = 'application/json; charset=utf-8'
DEFAULT_UA = 'HTTPie/%s' % __version__ DEFAULT_UA = 'HTTPie/%s' % __version__
def get_requests_session():
requests_session = requests.Session()
for adapter_plugin_cls in plugin_manager.get_adapter_plugins():
adapter_plugin = adapter_plugin_cls()
requests_session.mount(prefix=adapter_plugin.prefix,
adapter=adapter_plugin.get_adapter())
return requests_session
def get_response(args, config_dir): def get_response(args, config_dir):
"""Send the request and return a `request.Response`.""" """Send the request and return a `request.Response`."""
requests_session = get_requests_session()
if not args.session and not args.session_read_only: if not args.session and not args.session_read_only:
requests_kwargs = get_requests_kwargs(args) kwargs = get_requests_kwargs(args)
if args.debug: if args.debug:
dump_request(requests_kwargs) dump_request(kwargs)
response = requests.request(**requests_kwargs) response = requests_session.request(**kwargs)
else: else:
response = sessions.get_response( response = sessions.get_response(
requests_session=requests_session,
args=args, args=args,
config_dir=config_dir, config_dir=config_dir,
session_name=args.session or args.session_read_only, session_name=args.session or args.session_read_only,

View File

@ -1,4 +1,12 @@
from httpie.plugins.base import AuthPlugin, FormatterPlugin, ConverterPlugin """
WARNING: The plugin API is still work in progress and will
probably be completely reworked by v1.0.0.
"""
from httpie.plugins.base import (
AuthPlugin, FormatterPlugin,
ConverterPlugin, TransportPlugin
)
from httpie.plugins.manager import PluginManager from httpie.plugins.manager import PluginManager
from httpie.plugins.builtin import BasicAuthPlugin, DigestAuthPlugin from httpie.plugins.builtin import BasicAuthPlugin, DigestAuthPlugin
from httpie.output.formatters.headers import HeadersFormatter from httpie.output.formatters.headers import HeadersFormatter

View File

@ -15,7 +15,7 @@ class AuthPlugin(BasePlugin):
""" """
Base auth plugin class. Base auth plugin class.
See <https://github.com/jkbr/httpie-ntlm> for an example auth plugin. See <https://github.com/jakubroztocil/httpie-ntlm> for an example auth plugin.
""" """
# The value that should be passed to --auth-type # The value that should be passed to --auth-type
@ -30,6 +30,25 @@ class AuthPlugin(BasePlugin):
raise NotImplementedError() raise NotImplementedError()
class TransportPlugin(BasePlugin):
"""
http://docs.python-requests.org/en/latest/user/advanced/#transport-adapters
"""
# The URL prefix the adapter should be mount to.
prefix = None
def get_adapter(self):
"""
Return a ``requests.adapters.BaseAdapter`` subclass instance to be
mounted to ``self.prefix``.
"""
raise NotImplementedError()
class ConverterPlugin(object): class ConverterPlugin(object):
def __init__(self, mime): def __init__(self, mime):

View File

@ -1,12 +1,14 @@
from itertools import groupby from itertools import groupby
from pkg_resources import iter_entry_points from pkg_resources import iter_entry_points
from httpie.plugins import AuthPlugin, FormatterPlugin, ConverterPlugin from httpie.plugins import AuthPlugin, FormatterPlugin, ConverterPlugin
from httpie.plugins.base import TransportPlugin
ENTRY_POINT_NAMES = [ ENTRY_POINT_NAMES = [
'httpie.plugins.auth.v1', 'httpie.plugins.auth.v1',
'httpie.plugins.formatter.v1', 'httpie.plugins.formatter.v1',
'httpie.plugins.converter.v1', 'httpie.plugins.converter.v1',
'httpie.plugins.transport.v1',
] ]
@ -56,3 +58,8 @@ class PluginManager(object):
def get_converters(self): def get_converters(self):
return [plugin for plugin in self return [plugin for plugin in self
if issubclass(plugin, ConverterPlugin)] if issubclass(plugin, ConverterPlugin)]
# Adapters
def get_adapter_plugins(self):
return [plugin for plugin in self
if issubclass(plugin, TransportPlugin)]

View File

@ -4,7 +4,6 @@
import re import re
import os import os
import requests
from requests.cookies import RequestsCookieJar, create_cookie from requests.cookies import RequestsCookieJar, create_cookie
from httpie.compat import urlsplit from httpie.compat import urlsplit
@ -21,7 +20,8 @@ VALID_SESSION_NAME_PATTERN = re.compile('^[a-zA-Z0-9_.-]+$')
SESSION_IGNORED_HEADER_PREFIXES = ['Content-', 'If-'] SESSION_IGNORED_HEADER_PREFIXES = ['Content-', 'If-']
def get_response(session_name, config_dir, args, read_only=False): def get_response(requests_session, session_name,
config_dir, args, read_only=False):
"""Like `client.get_response`, but applies permanent """Like `client.get_response`, but applies permanent
aspects of the session to the request. aspects of the session to the request.
@ -32,7 +32,9 @@ def get_response(session_name, config_dir, args, read_only=False):
else: else:
hostname = (args.headers.get('Host', None) hostname = (args.headers.get('Host', None)
or urlsplit(args.url).netloc.split('@')[-1]) or urlsplit(args.url).netloc.split('@')[-1])
assert re.match('^[a-zA-Z0-9_.:-]+$', hostname) if not hostname:
# HACK/FIXME: httpie-unixsocket's URLs have no hostname.
hostname = 'localhost'
# host:port => host_port # host:port => host_port
hostname = hostname.replace(':', '_') hostname = hostname.replace(':', '_')
@ -44,10 +46,10 @@ def get_response(session_name, config_dir, args, read_only=False):
session = Session(path) session = Session(path)
session.load() session.load()
requests_kwargs = get_requests_kwargs(args, base_headers=session.headers) kwargs = get_requests_kwargs(args, base_headers=session.headers)
if args.debug: if args.debug:
dump_request(requests_kwargs) dump_request(kwargs)
session.update_headers(requests_kwargs['headers']) session.update_headers(kwargs['headers'])
if args.auth: if args.auth:
session.auth = { session.auth = {
@ -56,13 +58,12 @@ def get_response(session_name, config_dir, args, read_only=False):
'password': args.auth.value, 'password': args.auth.value,
} }
elif session.auth: elif session.auth:
requests_kwargs['auth'] = session.auth kwargs['auth'] = session.auth
requests_session = requests.Session()
requests_session.cookies = session.cookies requests_session.cookies = session.cookies
try: try:
response = requests_session.request(**requests_kwargs) response = requests_session.request(**kwargs)
except Exception: except Exception:
raise raise
else: else: