mirror of
https://github.com/httpie/cli.git
synced 2024-11-22 15:53:13 +01:00
0.3.0
This commit is contained in:
parent
a41dd7ac6d
commit
e25d64a610
44
README.rst
44
README.rst
@ -1,8 +1,8 @@
|
||||
***********************
|
||||
HTTPie: cURL for Humans
|
||||
***********************
|
||||
****************************************
|
||||
HTTPie: a CLI, cURL-like tool for humans
|
||||
****************************************
|
||||
|
||||
v0.2.8-alpha (`stable version`_)
|
||||
v0.3.0
|
||||
|
||||
HTTPie is a **command line HTTP client** whose goal is to make CLI interaction
|
||||
with web services as **human-friendly** as possible. It provides a
|
||||
@ -42,6 +42,7 @@ Main Features
|
||||
* HTTPS, proxies, and authentication
|
||||
* Arbitrary request data
|
||||
* Custom headers
|
||||
* Persistent sessions
|
||||
* Python 2.6, 2.7 and 3.x support
|
||||
* Linux, Mac OS X and Windows support
|
||||
* Documentation
|
||||
@ -825,34 +826,35 @@ Streamed output by small chunks alá ``tail -f``:
|
||||
Sessions
|
||||
========
|
||||
|
||||
HTTPie supports named, per-host sessions, where custom headers, authorization,
|
||||
and cookies (manually specified or sent by the server) persist between requests:
|
||||
By default, every request is completely independent of the previous ones.
|
||||
|
||||
HTTPie supports persistent sessions, where custom headers, authorization,
|
||||
and cookies (manually specified or sent by the server) persist between
|
||||
requests. Sessions are named and host-bound.
|
||||
|
||||
Create a new session named ``user1``:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ http --session user1 -a user1:password example.org X-Foo:Bar
|
||||
$ http --session=user1 -a user1:password example.org X-Foo:Bar
|
||||
|
||||
Now you can refer to the session by its name:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ http --session user1 example.org
|
||||
$ http --session=user1 example.org
|
||||
|
||||
|
||||
To switch to another session simple pass a different name:
|
||||
To create or reuse a different session, simple specify a different name:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ http --session user2 -a user2:password example.org X-Bar:Foo
|
||||
$ http --session=user2 -a user2:password example.org X-Bar:Foo
|
||||
|
||||
To use a session without updating it from the request/response exchange
|
||||
once it is created, specify the session name via
|
||||
``--session-read-only=SESSION_NAME`` instead.
|
||||
|
||||
You can view and manipulate existing sessions via the ``httpie`` management
|
||||
command, see ``httpie --help``.
|
||||
|
||||
Sessions are stored as JSON in ``~/.httpie/sessions/<host>/<name>.json``
|
||||
Sessions are stored as JSON files in ``~/.httpie/sessions/<host>/<name>.json``
|
||||
(``%APPDATA%\httpie\sessions\<host>\<name>.json`` on Windows).
|
||||
|
||||
See also `config`_.
|
||||
@ -862,8 +864,8 @@ See also `config`_.
|
||||
Config
|
||||
======
|
||||
|
||||
HTTPie provides a simple configuration file containing a JSON
|
||||
object with the following keys:
|
||||
HTTPie uses a simple configuration file that contains a JSON object with the
|
||||
following keys:
|
||||
|
||||
========================= =================================================
|
||||
``__version__`` HTTPie automatically sets this to its version.
|
||||
@ -1025,9 +1027,9 @@ Changelog
|
||||
|
||||
*You can click a version name to see a diff with the previous one.*
|
||||
|
||||
* `0.2.8-alpha`_
|
||||
* `0.3.0`_ (2012-09-21)
|
||||
* Allow output redirection on Windows.
|
||||
* Added config file.
|
||||
* Added configuration file.
|
||||
* Added persistent session support.
|
||||
* Renamed ``--allow-redirects`` to ``--follow``.
|
||||
* Improved the usability of ``http --help``.
|
||||
@ -1117,7 +1119,7 @@ Changelog
|
||||
.. _0.2.5: https://github.com/jkbr/httpie/compare/0.2.2...0.2.5
|
||||
.. _0.2.6: https://github.com/jkbr/httpie/compare/0.2.5...0.2.6
|
||||
.. _0.2.7: https://github.com/jkbr/httpie/compare/0.2.5...0.2.7
|
||||
.. _0.2.8-alpha: https://github.com/jkbr/httpie/compare/0.2.7...master
|
||||
.. _stable version: https://github.com/jkbr/httpie/tree/0.2.7#readme
|
||||
.. _0.3.0: https://github.com/jkbr/httpie/compare/0.2.7...0.3.0
|
||||
.. _stable version: https://github.com/jkbr/httpie/tree/0.3.0#readme
|
||||
.. _AUTHORS.rst: https://github.com/jkbr/httpie/blob/master/AUTHORS.rst
|
||||
.. _LICENSE: https://github.com/jkbr/httpie/blob/master/LICENSE
|
||||
|
@ -1,13 +1,13 @@
|
||||
"""
|
||||
HTTPie - cURL for humans.
|
||||
HTTPie - a CLI, cURL-like tool for humans.
|
||||
|
||||
"""
|
||||
__author__ = 'Jakub Roztocil'
|
||||
__version__ = '0.2.8-alpha'
|
||||
__version__ = '0.3.0'
|
||||
__licence__ = 'BSD'
|
||||
|
||||
|
||||
class EXIT:
|
||||
class exit:
|
||||
OK = 0
|
||||
ERROR = 1
|
||||
ERROR_TIMEOUT = 2
|
||||
|
@ -1,6 +1,8 @@
|
||||
"""CLI arguments definition.
|
||||
|
||||
NOTE: the CLI interface may change before reaching v1.0.
|
||||
TODO: make the options config friendly, i.e., no mutually exclusive groups to
|
||||
allow options overwriting.
|
||||
|
||||
"""
|
||||
from argparse import FileType, OPTIONAL, ZERO_OR_MORE, SUPPRESS
|
||||
@ -9,7 +11,7 @@ from requests.compat import is_windows
|
||||
|
||||
from . import __doc__
|
||||
from . import __version__
|
||||
from .config import DEFAULT_CONFIG_DIR
|
||||
from .sessions import DEFAULT_SESSIONS_DIR
|
||||
from .output import AVAILABLE_STYLES, DEFAULT_STYLE
|
||||
from .input import (Parser, AuthCredentialsArgType, KeyValueArgType,
|
||||
SEP_PROXY, SEP_CREDENTIALS, SEP_GROUP_ITEMS,
|
||||
@ -231,14 +233,14 @@ sessions.add_argument(
|
||||
Create, or reuse and update a session.
|
||||
Withing a session, custom headers, auth credential, as well as any
|
||||
cookies sent by the server persist between requests.
|
||||
You can use the `httpie' management command to manipulate
|
||||
and inspect existing sessions. See `httpie --help'.
|
||||
''')
|
||||
Session files are stored in %s/<HOST>/<SESSION_NAME>.json.
|
||||
''' % DEFAULT_SESSIONS_DIR)
|
||||
)
|
||||
sessions.add_argument(
|
||||
'--session-read-only', metavar='SESSION_NAME',
|
||||
help=_('''
|
||||
Create or reuse a session, but do not update it once saved.
|
||||
Create or read a session without updating it form the
|
||||
request/response exchange.
|
||||
''')
|
||||
)
|
||||
|
||||
|
@ -23,22 +23,22 @@ from .cli import parser
|
||||
from .client import get_response
|
||||
from .models import Environment
|
||||
from .output import output_stream, write, write_with_colors_win_p3k
|
||||
from . import EXIT
|
||||
from . import exit
|
||||
|
||||
|
||||
def get_exist_status(code, follow=False):
|
||||
"""Translate HTTP status code to exit status."""
|
||||
if 300 <= code <= 399 and not follow:
|
||||
# Redirect
|
||||
return EXIT.ERROR_HTTP_3XX
|
||||
return exit.ERROR_HTTP_3XX
|
||||
elif 400 <= code <= 499:
|
||||
# Client Error
|
||||
return EXIT.ERROR_HTTP_4XX
|
||||
return exit.ERROR_HTTP_4XX
|
||||
elif 500 <= code <= 599:
|
||||
# Server Error
|
||||
return EXIT.ERROR_HTTP_5XX
|
||||
return exit.ERROR_HTTP_5XX
|
||||
else:
|
||||
return EXIT.OK
|
||||
return exit.OK
|
||||
|
||||
|
||||
def print_debug_info(env):
|
||||
@ -66,12 +66,12 @@ def main(args=sys.argv[1:], env=Environment()):
|
||||
|
||||
debug = '--debug' in args
|
||||
traceback = debug or '--traceback' in args
|
||||
status = EXIT.OK
|
||||
status = exit.OK
|
||||
|
||||
if debug:
|
||||
print_debug_info(env)
|
||||
if args == ['--debug']:
|
||||
sys.exit(EXIT.OK)
|
||||
sys.exit(exit.OK)
|
||||
|
||||
try:
|
||||
args = parser.parse_args(args=args, env=env)
|
||||
@ -108,9 +108,9 @@ def main(args=sys.argv[1:], env=Environment()):
|
||||
if traceback:
|
||||
raise
|
||||
env.stderr.write('\n')
|
||||
status = EXIT.ERROR
|
||||
status = exit.ERROR
|
||||
except requests.Timeout:
|
||||
status = EXIT.ERROR_TIMEOUT
|
||||
status = exit.ERROR_TIMEOUT
|
||||
error('Request timed out (%ss).', args.timeout)
|
||||
except Exception as e:
|
||||
# TODO: distinguish between expected and unexpected errors.
|
||||
@ -118,6 +118,6 @@ def main(args=sys.argv[1:], env=Environment()):
|
||||
if traceback:
|
||||
raise
|
||||
error('%s: %s', type(e).__name__, str(e))
|
||||
status = EXIT.ERROR
|
||||
status = exit.ERROR
|
||||
|
||||
return status
|
||||
|
@ -20,6 +20,7 @@ from .output import PygmentsProcessor
|
||||
|
||||
|
||||
SESSIONS_DIR_NAME = 'sessions'
|
||||
DEFAULT_SESSIONS_DIR = os.path.join(DEFAULT_CONFIG_DIR, SESSIONS_DIR_NAME)
|
||||
|
||||
|
||||
def get_response(name, request_kwargs, config_dir, read_only=False):
|
||||
@ -92,8 +93,8 @@ class Host(object):
|
||||
@classmethod
|
||||
def all(cls):
|
||||
"""Return a generator yielding a host at a time."""
|
||||
for name in sorted(glob.glob1(SESSIONS_DIR, '*')):
|
||||
if os.path.isdir(os.path.join(SESSIONS_DIR, name)):
|
||||
for name in sorted(glob.glob1(DEFAULT_SESSIONS_DIR, '*')):
|
||||
if os.path.isdir(os.path.join(DEFAULT_SESSIONS_DIR, name)):
|
||||
yield Host(name)
|
||||
|
||||
|
||||
@ -156,6 +157,9 @@ class Session(BaseConfigDict):
|
||||
}
|
||||
|
||||
|
||||
# The commands are disabled for now.
|
||||
# TODO: write tests for the commands.
|
||||
|
||||
def list_command(args):
|
||||
if args.host:
|
||||
for name, path in Host(args.host):
|
||||
|
3
setup.py
3
setup.py
@ -47,7 +47,8 @@ setup(
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'http = httpie.__main__:main',
|
||||
'httpie = httpie.manage:main',
|
||||
# Not ready yet.
|
||||
# 'httpie = httpie.manage:main',
|
||||
],
|
||||
},
|
||||
install_requires=requirements,
|
||||
|
@ -19,6 +19,7 @@ To make it run faster and offline you can::
|
||||
HTTPBIN_URL=http://localhost:5000 tox
|
||||
|
||||
"""
|
||||
from functools import partial
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
@ -28,6 +29,7 @@ import tempfile
|
||||
import unittest
|
||||
import shutil
|
||||
|
||||
from requests.compat import urlparse
|
||||
try:
|
||||
from urllib.request import urlopen
|
||||
except ImportError:
|
||||
@ -55,7 +57,7 @@ from requests.compat import is_windows, is_py26, bytes, str
|
||||
TESTS_ROOT = os.path.abspath(os.path.dirname(__file__))
|
||||
sys.path.insert(0, os.path.realpath(os.path.join(TESTS_ROOT, '..')))
|
||||
|
||||
from httpie import EXIT
|
||||
from httpie import exit
|
||||
from httpie import input
|
||||
from httpie.models import Environment
|
||||
from httpie.core import main
|
||||
@ -183,7 +185,7 @@ def http(*args, **kwargs):
|
||||
sys.stderr.write(env.stderr.read())
|
||||
raise
|
||||
except SystemExit:
|
||||
exit_status = EXIT.ERROR
|
||||
exit_status = exit.ERROR
|
||||
|
||||
env.stdout.seek(0)
|
||||
env.stderr.seek(0)
|
||||
@ -865,7 +867,7 @@ class ExitStatusTest(BaseTestCase):
|
||||
httpbin('/status/200')
|
||||
)
|
||||
self.assertIn(OK, r)
|
||||
self.assertEqual(r.exit_status, EXIT.OK)
|
||||
self.assertEqual(r.exit_status, exit.OK)
|
||||
|
||||
def test_error_response_exits_0_without_check_status(self):
|
||||
r = http(
|
||||
@ -873,7 +875,7 @@ class ExitStatusTest(BaseTestCase):
|
||||
httpbin('/status/500')
|
||||
)
|
||||
self.assertIn('HTTP/1.1 500', r)
|
||||
self.assertEqual(r.exit_status, EXIT.OK)
|
||||
self.assertEqual(r.exit_status, exit.OK)
|
||||
self.assertTrue(not r.stderr)
|
||||
|
||||
def test_timeout_exit_status(self):
|
||||
@ -882,7 +884,7 @@ class ExitStatusTest(BaseTestCase):
|
||||
'GET',
|
||||
httpbin('/delay/1')
|
||||
)
|
||||
self.assertEqual(r.exit_status, EXIT.ERROR_TIMEOUT)
|
||||
self.assertEqual(r.exit_status, exit.ERROR_TIMEOUT)
|
||||
|
||||
def test_3xx_check_status_exits_3_and_stderr_when_stdout_redirected(self):
|
||||
r = http(
|
||||
@ -893,7 +895,7 @@ class ExitStatusTest(BaseTestCase):
|
||||
env=TestEnvironment(stdout_isatty=False,)
|
||||
)
|
||||
self.assertIn('HTTP/1.1 301', r)
|
||||
self.assertEqual(r.exit_status, EXIT.ERROR_HTTP_3XX)
|
||||
self.assertEqual(r.exit_status, exit.ERROR_HTTP_3XX)
|
||||
self.assertIn('301 moved permanently', r.stderr.lower())
|
||||
|
||||
@skipIf(requests_version == '0.13.6',
|
||||
@ -907,7 +909,7 @@ class ExitStatusTest(BaseTestCase):
|
||||
)
|
||||
# The redirect will be followed so 200 is expected.
|
||||
self.assertIn('HTTP/1.1 200 OK', r)
|
||||
self.assertEqual(r.exit_status, EXIT.OK)
|
||||
self.assertEqual(r.exit_status, exit.OK)
|
||||
|
||||
def test_4xx_check_status_exits_4(self):
|
||||
r = http(
|
||||
@ -916,7 +918,7 @@ class ExitStatusTest(BaseTestCase):
|
||||
httpbin('/status/401')
|
||||
)
|
||||
self.assertIn('HTTP/1.1 401', r)
|
||||
self.assertEqual(r.exit_status, EXIT.ERROR_HTTP_4XX)
|
||||
self.assertEqual(r.exit_status, exit.ERROR_HTTP_4XX)
|
||||
# Also stderr should be empty since stdout isn't redirected.
|
||||
self.assertTrue(not r.stderr)
|
||||
|
||||
@ -927,7 +929,7 @@ class ExitStatusTest(BaseTestCase):
|
||||
httpbin('/status/500')
|
||||
)
|
||||
self.assertIn('HTTP/1.1 500', r)
|
||||
self.assertEqual(r.exit_status, EXIT.ERROR_HTTP_5XX)
|
||||
self.assertEqual(r.exit_status, exit.ERROR_HTTP_5XX)
|
||||
|
||||
|
||||
class WindowsOnlyTests(BaseTestCase):
|
||||
@ -1267,7 +1269,7 @@ class SessionTest(BaseTestCase):
|
||||
shutil.rmtree(self.config_dir)
|
||||
|
||||
def test_session_create(self):
|
||||
# Verify that the has been created
|
||||
# Verify that the session has been created.
|
||||
r = http(
|
||||
'--session=test',
|
||||
'GET',
|
||||
@ -1316,7 +1318,7 @@ class SessionTest(BaseTestCase):
|
||||
self.assertNotEqual(r1.json['headers']['Authorization'],
|
||||
r3.json['headers']['Authorization'])
|
||||
|
||||
def test_session_only(self):
|
||||
def test_session_read_only(self):
|
||||
# Get a response from the original session.
|
||||
r1 = http(
|
||||
'--session=test',
|
||||
|
Loading…
Reference in New Issue
Block a user