mirror of
https://github.com/httpie/cli.git
synced 2024-11-24 08:22:22 +02:00
Added support for auth plugins.
This commit is contained in:
parent
f7b703b4bf
commit
2acb303552
@ -514,6 +514,13 @@ Authorization information from your ``.netrc`` file is honored as well:
|
||||
[...]
|
||||
|
||||
|
||||
-------
|
||||
Plugins
|
||||
-------
|
||||
|
||||
* `httpie-ntlm <https://github.com/jkbr/httpie-ntlm>`_
|
||||
|
||||
|
||||
=======
|
||||
Proxies
|
||||
=======
|
||||
@ -1206,6 +1213,7 @@ Changelog
|
||||
|
||||
* `0.7.0-dev`_
|
||||
* Added ``--ignore-stdin``.
|
||||
* Added support for auth plugins.
|
||||
* `0.6.0`_ (2013-06-03)
|
||||
* XML data is now formatted.
|
||||
* ``--session`` and ``--session-read-only`` now also accept paths to
|
||||
|
@ -3,7 +3,7 @@ HTTPie - a CLI, cURL-like tool for humans.
|
||||
|
||||
"""
|
||||
__author__ = 'Jakub Roztocil'
|
||||
__version__ = '0.6.0'
|
||||
__version__ = '0.7.0'
|
||||
__licence__ = 'BSD'
|
||||
|
||||
|
||||
|
@ -10,6 +10,8 @@ from argparse import (RawDescriptionHelpFormatter, FileType,
|
||||
|
||||
from . import __doc__
|
||||
from . import __version__
|
||||
from .plugins.builtin import BuiltinAuthPlugin
|
||||
from .plugins import plugin_manager
|
||||
from .sessions import DEFAULT_SESSIONS_DIR
|
||||
from .output import AVAILABLE_STYLES, DEFAULT_STYLE
|
||||
from .input import (Parser, AuthCredentialsArgType, KeyValueArgType,
|
||||
@ -381,14 +383,32 @@ auth.add_argument(
|
||||
""",
|
||||
)
|
||||
|
||||
_auth_plugins = plugin_manager.get_auth_plugins()
|
||||
auth.add_argument(
|
||||
'--auth-type',
|
||||
choices=['basic', 'digest'],
|
||||
default='basic',
|
||||
choices=[plugin.auth_type for plugin in _auth_plugins],
|
||||
default=_auth_plugins[0].auth_type,
|
||||
help="""
|
||||
The authentication mechanism to be used. Defaults to "basic".
|
||||
The authentication mechanism to be used. Defaults to "{default}".
|
||||
|
||||
{types}
|
||||
|
||||
"""
|
||||
.format(default=_auth_plugins[0].auth_type, types='\n '.join(
|
||||
'"{type}": {name}{package}{description}'.format(
|
||||
type=plugin.auth_type,
|
||||
name=plugin.name,
|
||||
package=(
|
||||
'' if issubclass(plugin, BuiltinAuthPlugin)
|
||||
else ' (provided by %s)' % plugin.package_name
|
||||
),
|
||||
description=(
|
||||
'' if not plugin.description else
|
||||
'\n ' + ('\n '.join(wrap(plugin.description)))
|
||||
)
|
||||
)
|
||||
for plugin in _auth_plugins
|
||||
)),
|
||||
)
|
||||
|
||||
|
||||
|
@ -7,6 +7,7 @@ import requests.auth
|
||||
|
||||
from . import sessions
|
||||
from . import __version__
|
||||
from .plugins import plugin_manager
|
||||
|
||||
|
||||
FORM = 'application/x-www-form-urlencoded; charset=utf-8'
|
||||
@ -14,6 +15,12 @@ JSON = 'application/json; charset=utf-8'
|
||||
DEFAULT_UA = 'HTTPie/%s' % __version__
|
||||
|
||||
|
||||
class HTTPie(object):
|
||||
|
||||
def __init__(self, env, plugin_manager):
|
||||
pass
|
||||
|
||||
|
||||
def get_response(args, config_dir):
|
||||
"""Send the request and return a `request.Response`."""
|
||||
|
||||
@ -27,6 +34,7 @@ def get_response(args, config_dir):
|
||||
response = requests.request(**requests_kwargs)
|
||||
else:
|
||||
response = sessions.get_response(
|
||||
args=args,
|
||||
config_dir=config_dir,
|
||||
session_name=args.session or args.session_read_only,
|
||||
requests_kwargs=requests_kwargs,
|
||||
@ -69,10 +77,8 @@ def get_requests_kwargs(args):
|
||||
|
||||
credentials = None
|
||||
if args.auth:
|
||||
credentials = {
|
||||
'basic': requests.auth.HTTPBasicAuth,
|
||||
'digest': requests.auth.HTTPDigestAuth,
|
||||
}[args.auth_type](args.auth.key, args.auth.value)
|
||||
auth_plugin = plugin_manager.get_auth_plugin(args.auth_type)()
|
||||
credentials = auth_plugin.get_auth(args.auth.key, args.auth.value)
|
||||
|
||||
kwargs = {
|
||||
'stream': True,
|
||||
|
@ -18,13 +18,13 @@ from httpie import __version__ as httpie_version
|
||||
from requests import __version__ as requests_version
|
||||
from pygments import __version__ as pygments_version
|
||||
|
||||
from .cli import parser
|
||||
from .compat import str, is_py3
|
||||
from .client import get_response
|
||||
from .downloads import Download
|
||||
from .models import Environment
|
||||
from .output import build_output_stream, write, write_with_colors_win_py3
|
||||
from . import ExitStatus
|
||||
from .plugins import plugin_manager
|
||||
|
||||
|
||||
def get_exit_status(http_status, follow=False):
|
||||
@ -58,6 +58,9 @@ def main(args=sys.argv[1:], env=Environment()):
|
||||
Return exit status code.
|
||||
|
||||
"""
|
||||
plugin_manager.load_installed_plugins()
|
||||
from .cli import parser
|
||||
|
||||
if env.config.default_options:
|
||||
args = env.config.default_options + args
|
||||
|
||||
|
@ -6,7 +6,7 @@ import sys
|
||||
import re
|
||||
import json
|
||||
import mimetypes
|
||||
import getpass
|
||||
from getpass import getpass
|
||||
from io import BytesIO
|
||||
#noinspection PyCompatibility
|
||||
from argparse import ArgumentParser, ArgumentTypeError, ArgumentError
|
||||
|
9
httpie/plugins/__init__.py
Normal file
9
httpie/plugins/__init__.py
Normal file
@ -0,0 +1,9 @@
|
||||
from .base import AuthPlugin
|
||||
from .manager import PluginManager
|
||||
from .builtin import BasicAuthPlugin, DigestAuthPlugin
|
||||
|
||||
|
||||
plugin_manager = PluginManager()
|
||||
plugin_manager.register(BasicAuthPlugin)
|
||||
plugin_manager.register(DigestAuthPlugin)
|
||||
|
28
httpie/plugins/base.py
Normal file
28
httpie/plugins/base.py
Normal file
@ -0,0 +1,28 @@
|
||||
class AuthPlugin(object):
|
||||
"""
|
||||
Base auth plugin class.
|
||||
|
||||
See <https://github.com/jkbr/httpie-ntlm> for an example auth plugin.
|
||||
|
||||
"""
|
||||
|
||||
# The value that should be passed to --auth-type
|
||||
# to use this auth plugin. Eg. "my-auth"
|
||||
auth_type = None
|
||||
|
||||
# The name of the plugin, eg. "My auth".
|
||||
name = None
|
||||
|
||||
# Optional short description. Will be be shown in the help
|
||||
# under --auth-type.
|
||||
description = None
|
||||
|
||||
# This be set automatically once the plugin has been loaded.
|
||||
package_name = None
|
||||
|
||||
def get_auth(self, username, password):
|
||||
"""
|
||||
Return a ``requests.auth.AuthBase`` subclass instance.
|
||||
|
||||
"""
|
||||
raise NotImplementedError()
|
26
httpie/plugins/builtin.py
Normal file
26
httpie/plugins/builtin.py
Normal file
@ -0,0 +1,26 @@
|
||||
import requests.auth
|
||||
|
||||
from .base import AuthPlugin
|
||||
|
||||
|
||||
class BuiltinAuthPlugin(AuthPlugin):
|
||||
|
||||
package_name = '(builtin)'
|
||||
|
||||
|
||||
class BasicAuthPlugin(BuiltinAuthPlugin):
|
||||
|
||||
name = 'Basic HTTP auth'
|
||||
auth_type = 'basic'
|
||||
|
||||
def get_auth(self, username, password):
|
||||
return requests.auth.HTTPBasicAuth(username, password)
|
||||
|
||||
|
||||
class DigestAuthPlugin(BuiltinAuthPlugin):
|
||||
|
||||
name = 'Digest HTTP auth'
|
||||
auth_type = 'digest'
|
||||
|
||||
def get_auth(self, username, password):
|
||||
return requests.auth.HTTPDigestAuth(username, password)
|
35
httpie/plugins/manager.py
Normal file
35
httpie/plugins/manager.py
Normal file
@ -0,0 +1,35 @@
|
||||
from pkg_resources import iter_entry_points
|
||||
|
||||
|
||||
ENTRY_POINT_NAMES = [
|
||||
'httpie.plugins.auth.v1'
|
||||
]
|
||||
|
||||
|
||||
class PluginManager(object):
|
||||
|
||||
def __init__(self):
|
||||
self._plugins = []
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._plugins)
|
||||
|
||||
def register(self, plugin):
|
||||
self._plugins.append(plugin)
|
||||
|
||||
def get_auth_plugins(self):
|
||||
return list(self._plugins)
|
||||
|
||||
def get_auth_plugin_mapping(self):
|
||||
return dict((plugin.auth_type, plugin) for plugin in self)
|
||||
|
||||
def get_auth_plugin(self, auth_type):
|
||||
return self.get_auth_plugin_mapping()[auth_type]
|
||||
|
||||
def load_installed_plugins(self):
|
||||
|
||||
for entry_point_name in ENTRY_POINT_NAMES:
|
||||
for entry_point in iter_entry_points(entry_point_name):
|
||||
plugin = entry_point.load()
|
||||
plugin.package_name = entry_point.dist.key
|
||||
self.register(entry_point.load())
|
@ -6,10 +6,10 @@ import os
|
||||
|
||||
import requests
|
||||
from requests.cookies import RequestsCookieJar, create_cookie
|
||||
from requests.auth import HTTPBasicAuth, HTTPDigestAuth
|
||||
|
||||
from .compat import urlsplit
|
||||
from .config import BaseConfigDict, DEFAULT_CONFIG_DIR
|
||||
from httpie.plugins import plugin_manager
|
||||
|
||||
|
||||
SESSIONS_DIR_NAME = 'sessions'
|
||||
@ -21,7 +21,8 @@ VALID_SESSION_NAME_PATTERN = re.compile('^[a-zA-Z0-9_.-]+$')
|
||||
SESSION_IGNORED_HEADER_PREFIXES = ['Content-', 'If-']
|
||||
|
||||
|
||||
def get_response(session_name, requests_kwargs, config_dir, read_only=False):
|
||||
def get_response(session_name, requests_kwargs, config_dir, args,
|
||||
read_only=False):
|
||||
"""Like `client.get_response`, but applies permanent
|
||||
aspects of the session to the request.
|
||||
|
||||
@ -50,9 +51,12 @@ def get_response(session_name, requests_kwargs, config_dir, read_only=False):
|
||||
requests_kwargs['headers'] = dict(session.headers, **request_headers)
|
||||
session.update_headers(request_headers)
|
||||
|
||||
auth = requests_kwargs.get('auth', None)
|
||||
if auth:
|
||||
session.auth = auth
|
||||
if args.auth:
|
||||
session.auth = {
|
||||
'type': args.auth_type,
|
||||
'username': args.auth.key,
|
||||
'password': args.auth.value,
|
||||
}
|
||||
elif session.auth:
|
||||
requests_kwargs['auth'] = session.auth
|
||||
|
||||
@ -140,15 +144,10 @@ class Session(BaseConfigDict):
|
||||
auth = self.get('auth', None)
|
||||
if not auth or not auth['type']:
|
||||
return
|
||||
Auth = {'basic': HTTPBasicAuth,
|
||||
'digest': HTTPDigestAuth}[auth['type']]
|
||||
return Auth(auth['username'], auth['password'])
|
||||
auth_plugin = plugin_manager.get_auth_plugin(auth['type'])()
|
||||
return auth_plugin.get_auth(auth['username'], auth['password'])
|
||||
|
||||
@auth.setter
|
||||
def auth(self, cred):
|
||||
self['auth'] = {
|
||||
'type': {HTTPBasicAuth: 'basic',
|
||||
HTTPDigestAuth: 'digest'}[type(cred)],
|
||||
'username': cred.username,
|
||||
'password': cred.password,
|
||||
}
|
||||
def auth(self, auth):
|
||||
assert set(['type', 'username', 'password']) == set(auth.keys())
|
||||
self['auth'] = auth
|
||||
|
Loading…
Reference in New Issue
Block a user