mirror of
https://github.com/httpie/cli.git
synced 2025-08-16 21:41:39 +02:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
753a8d04e4 | |||
3ff03524ff | |||
a5a83c5b77 | |||
9682f955b5 | |||
0d21ff022e | |||
996e314482 | |||
687a6a734d | |||
b125ce5eae | |||
92a4352f10 | |||
c0f1fb61ac | |||
17358be1ae | |||
338d39c841 | |||
530d6c5e27 |
25
README.rst
25
README.rst
@ -98,10 +98,10 @@ If the above fails, please use ``easy_install`` instead (``$ easy_install httpie
|
|||||||
Development version
|
Development version
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
============= =============
|
=========== ============= =============
|
||||||
Mac/Linux Windows
|
Tests Mac/Linux Windows
|
||||||
|unix| |windows|
|
|coverage| |unix| |windows|
|
||||||
============= =============
|
=========== ============= =============
|
||||||
|
|
||||||
|
|
||||||
The **latest development version** can be installed directly from GitHub:
|
The **latest development version** can be installed directly from GitHub:
|
||||||
@ -595,6 +595,7 @@ Auth Plugins
|
|||||||
* `httpie-ntlm <https://github.com/jakubroztocil/httpie-ntlm>`_: NTLM (NT LAN Manager)
|
* `httpie-ntlm <https://github.com/jakubroztocil/httpie-ntlm>`_: NTLM (NT LAN Manager)
|
||||||
* `httpie-negotiate <https://github.com/ndzou/httpie-negotiate>`_: SPNEGO (GSS Negotiate)
|
* `httpie-negotiate <https://github.com/ndzou/httpie-negotiate>`_: SPNEGO (GSS Negotiate)
|
||||||
* `requests-hawk <https://github.com/mozilla-services/requests-hawk>`_: Hawk
|
* `requests-hawk <https://github.com/mozilla-services/requests-hawk>`_: Hawk
|
||||||
|
* `httpie-api-auth <https://github.com/pd/httpie-api-auth>`_: ApiAuth
|
||||||
|
|
||||||
|
|
||||||
=======
|
=======
|
||||||
@ -1312,7 +1313,13 @@ Changelog
|
|||||||
|
|
||||||
*You can click a version name to see a diff with the previous one.*
|
*You can click a version name to see a diff with the previous one.*
|
||||||
|
|
||||||
|
* `1.0.0-dev`_
|
||||||
|
* `0.9.1`_ (2015-02-07)
|
||||||
|
* Added support for Requests transport adapter plugins
|
||||||
|
to enable plugin-provided features such as
|
||||||
|
`unix socket <https://github.com/msabramo/httpie-unixsocket>`_
|
||||||
|
communication and
|
||||||
|
`HTTP/2 <https://github.com/jakubroztocil/httpie-http2>`_.
|
||||||
* `0.9.0`_ (2015-01-31)
|
* `0.9.0`_ (2015-01-31)
|
||||||
* Added ``--cert`` and ``--cert-key`` parameters to specify a client side
|
* Added ``--cert`` and ``--cert-key`` parameters to specify a client side
|
||||||
certificate and private key for SSL
|
certificate and private key for SSL
|
||||||
@ -1322,7 +1329,7 @@ Changelog
|
|||||||
now only escapes special characters (the ones that are used as key-value
|
now only escapes special characters (the ones that are used as key-value
|
||||||
separators by HTTPie).
|
separators by HTTPie).
|
||||||
* Switched from ``unittest`` to ``pytest``.
|
* Switched from ``unittest`` to ``pytest``.
|
||||||
* Added Python `wheel` suppor.
|
* Added Python `wheel` support.
|
||||||
* Various test suite improvements.
|
* Various test suite improvements.
|
||||||
* Added `CONTRIBUTING`_.
|
* Added `CONTRIBUTING`_.
|
||||||
* Fixed ``User-Agent`` overwriting when used within a session.
|
* Fixed ``User-Agent`` overwriting when used within a session.
|
||||||
@ -1456,7 +1463,8 @@ Changelog
|
|||||||
.. _0.6.0: https://github.com/jakubroztocil/httpie/compare/0.5.1...0.6.0
|
.. _0.6.0: https://github.com/jakubroztocil/httpie/compare/0.5.1...0.6.0
|
||||||
.. _0.7.1: https://github.com/jakubroztocil/httpie/compare/0.6.0...0.7.1
|
.. _0.7.1: https://github.com/jakubroztocil/httpie/compare/0.6.0...0.7.1
|
||||||
.. _0.8.0: https://github.com/jakubroztocil/httpie/compare/0.7.1...0.8.0
|
.. _0.8.0: https://github.com/jakubroztocil/httpie/compare/0.7.1...0.8.0
|
||||||
.. _0.9.0: https://github.com/jakubroztocil/httpie/compare/0.9.0...master
|
.. _0.9.0: https://github.com/jakubroztocil/httpie/compare/0.8.0...0.9.0
|
||||||
|
.. _0.9.1: https://github.com/jakubroztocil/httpie/compare/0.9.0...0.9.1
|
||||||
.. _1.0.0-dev: https://github.com/jakubroztocil/httpie/compare/0.9.0...master
|
.. _1.0.0-dev: https://github.com/jakubroztocil/httpie/compare/0.9.0...master
|
||||||
.. _LICENSE: https://github.com/jakubroztocil/httpie/blob/master/LICENSE
|
.. _LICENSE: https://github.com/jakubroztocil/httpie/blob/master/LICENSE
|
||||||
.. _Tox: http://tox.testrun.org
|
.. _Tox: http://tox.testrun.org
|
||||||
@ -1466,6 +1474,9 @@ Changelog
|
|||||||
.. |version| image:: https://badge.fury.io/py/httpie.svg
|
.. |version| image:: https://badge.fury.io/py/httpie.svg
|
||||||
:target: http://badge.fury.io/py/httpie
|
:target: http://badge.fury.io/py/httpie
|
||||||
|
|
||||||
|
.. |coverage| image:: https://coveralls.io/repos/jakubroztocil/httpie/badge.svg?branch=master
|
||||||
|
:target: https://coveralls.io/r/jakubroztocil/httpie?branch=master
|
||||||
|
|
||||||
.. |unix| image:: https://api.travis-ci.org/jakubroztocil/httpie.svg
|
.. |unix| image:: https://api.travis-ci.org/jakubroztocil/httpie.svg
|
||||||
:target: http://travis-ci.org/jakubroztocil/httpie
|
:target: http://travis-ci.org/jakubroztocil/httpie
|
||||||
:alt: Build Status of the master branch on Mac/Linux
|
:alt: Build Status of the master branch on Mac/Linux
|
||||||
|
@ -3,7 +3,7 @@ HTTPie - a CLI, cURL-like tool for humans.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
__author__ = 'Jakub Roztocil'
|
__author__ = 'Jakub Roztocil'
|
||||||
__version__ = '0.9.0'
|
__version__ = '0.9.1'
|
||||||
__licence__ = 'BSD'
|
__licence__ = 'BSD'
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,16 +15,28 @@ 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 cls in plugin_manager.get_trasnsport_plugins():
|
||||||
|
transport_plugin = cls()
|
||||||
|
requests_session.mount(prefix=transport_plugin.prefix,
|
||||||
|
adapter=transport_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,
|
||||||
|
@ -21,6 +21,10 @@ from httpie.sessions import VALID_SESSION_NAME_PATTERN
|
|||||||
from httpie.utils import load_json_preserve_order
|
from httpie.utils import load_json_preserve_order
|
||||||
|
|
||||||
|
|
||||||
|
# ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
|
||||||
|
# <http://tools.ietf.org/html/rfc3986#section-3.1>
|
||||||
|
URL_SCHEME_RE = re.compile(r'^[a-z][a-z0-9.+-]*://', re.IGNORECASE)
|
||||||
|
|
||||||
HTTP_POST = 'POST'
|
HTTP_POST = 'POST'
|
||||||
HTTP_GET = 'GET'
|
HTTP_GET = 'GET'
|
||||||
HTTP = 'http://'
|
HTTP = 'http://'
|
||||||
@ -132,7 +136,7 @@ class Parser(ArgumentParser):
|
|||||||
self._parse_items()
|
self._parse_items()
|
||||||
if not self.args.ignore_stdin and not env.stdin_isatty:
|
if not self.args.ignore_stdin and not env.stdin_isatty:
|
||||||
self._body_from_file(self.env.stdin)
|
self._body_from_file(self.env.stdin)
|
||||||
if not (self.args.url.startswith((HTTP, HTTPS))):
|
if not URL_SCHEME_RE.match(self.args.url):
|
||||||
scheme = HTTP
|
scheme = HTTP
|
||||||
|
|
||||||
# See if we're using curl style shorthand for localhost (:3000/foo)
|
# See if we're using curl style shorthand for localhost (:3000/foo)
|
||||||
|
@ -52,7 +52,14 @@ class HTTPResponse(HTTPMessage):
|
|||||||
@property
|
@property
|
||||||
def headers(self):
|
def headers(self):
|
||||||
original = self._orig.raw._original_response
|
original = self._orig.raw._original_response
|
||||||
version = {9: '0.9', 10: '1.0', 11: '1.1'}[original.version]
|
|
||||||
|
version = {
|
||||||
|
9: '0.9',
|
||||||
|
10: '1.0',
|
||||||
|
11: '1.1',
|
||||||
|
20: '2',
|
||||||
|
}[original.version]
|
||||||
|
|
||||||
status_line = 'HTTP/{version} {status} {reason}'.format(
|
status_line = 'HTTP/{version} {status} {reason}'.format(
|
||||||
version=version,
|
version=version,
|
||||||
status=original.status,
|
status=original.status,
|
||||||
|
@ -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
|
||||||
|
@ -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):
|
||||||
|
@ -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_trasnsport_plugins(self):
|
||||||
|
return [plugin for plugin in self
|
||||||
|
if issubclass(plugin, TransportPlugin)]
|
||||||
|
@ -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:
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
import json
|
import json
|
||||||
# noinspection PyCompatibility
|
# noinspection PyCompatibility
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from requests.exceptions import InvalidSchema
|
||||||
|
|
||||||
from httpie import input
|
from httpie import input
|
||||||
from httpie.input import KeyValue, KeyValueArgType, DataDict
|
from httpie.input import KeyValue, KeyValueArgType, DataDict
|
||||||
@ -321,3 +321,12 @@ class TestIgnoreStdin:
|
|||||||
error_exit_ok=True)
|
error_exit_ok=True)
|
||||||
assert r.exit_status == ExitStatus.ERROR
|
assert r.exit_status == ExitStatus.ERROR
|
||||||
assert 'because --ignore-stdin' in r.stderr
|
assert 'because --ignore-stdin' in r.stderr
|
||||||
|
|
||||||
|
|
||||||
|
class TestSchemes:
|
||||||
|
|
||||||
|
def test_custom_scheme(self):
|
||||||
|
# InvalidSchema is expected because HTTPie
|
||||||
|
# shouldn't touch a formally valid scheme.
|
||||||
|
with pytest.raises(InvalidSchema):
|
||||||
|
http('foo+bar-BAZ.123://bah')
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from utils import TestEnvironment, http, HTTP_OK, COLOR, CRLF
|
||||||
from httpie import ExitStatus
|
from httpie import ExitStatus
|
||||||
from httpie.output.formatters.colors import get_lexer
|
from httpie.output.formatters.colors import get_lexer
|
||||||
from utils import TestEnvironment, http, HTTP_OK, COLOR, CRLF
|
|
||||||
|
|
||||||
|
|
||||||
class TestVerboseFlag:
|
class TestVerboseFlag:
|
||||||
|
Reference in New Issue
Block a user