forked from extern/httpie-cli
Added exit codes for HTTP 3xx, 4xx, 5xx (3, 4, 5).
Also added `--ignore-http-status` to ensure 0 exit status. HTTP 3xx result in 0 exit status when `--allow-redirects` is set.
This commit is contained in:
parent
0a673613ef
commit
0572158ba1
15
README.rst
15
README.rst
@ -170,9 +170,9 @@ See ``http -h`` for more details::
|
|||||||
usage: http [-h] [--version] [--json | --form] [--traceback]
|
usage: http [-h] [--version] [--json | --form] [--traceback]
|
||||||
[--pretty | --ugly]
|
[--pretty | --ugly]
|
||||||
[--print OUTPUT_OPTIONS | --verbose | --headers | --body]
|
[--print OUTPUT_OPTIONS | --verbose | --headers | --body]
|
||||||
[--style STYLE] [--auth AUTH] [--auth-type {basic,digest}]
|
[--style STYLE] [--ignore-http-status] [--auth AUTH]
|
||||||
[--verify VERIFY] [--proxy PROXY] [--allow-redirects]
|
[--auth-type {basic,digest}] [--verify VERIFY] [--proxy PROXY]
|
||||||
[--timeout TIMEOUT]
|
[--allow-redirects] [--timeout TIMEOUT]
|
||||||
[METHOD] URL [ITEM [ITEM ...]]
|
[METHOD] URL [ITEM [ITEM ...]]
|
||||||
|
|
||||||
HTTPie - cURL for humans. <http://httpie.org>
|
HTTPie - cURL for humans. <http://httpie.org>
|
||||||
@ -235,6 +235,14 @@ See ``http -h`` for more details::
|
|||||||
make sure that the $TERM environment variable is set
|
make sure that the $TERM environment variable is set
|
||||||
to "xterm-256color" or similar (e.g., via `export TERM
|
to "xterm-256color" or similar (e.g., via `export TERM
|
||||||
=xterm-256color' in your ~/.bashrc).
|
=xterm-256color' in your ~/.bashrc).
|
||||||
|
--ignore-http-status This flag tells HTTP to ignore the HTTP status code
|
||||||
|
and exit with 0. By default, HTTPie exits with 0 only
|
||||||
|
if no errors occur and the request is successful. When
|
||||||
|
the server replies with a 4xx (Client Error) or 5xx
|
||||||
|
(Server Error) status code, HTTPie exits with 4 or 5
|
||||||
|
respectively. If the response is 3xx (Redirect) and
|
||||||
|
--allow-redirects isn't set, then the exit status is
|
||||||
|
3.
|
||||||
--auth AUTH, -a AUTH username:password. If only the username is provided
|
--auth AUTH, -a AUTH username:password. If only the username is provided
|
||||||
(-a username), HTTPie will prompt for the password.
|
(-a username), HTTPie will prompt for the password.
|
||||||
--auth-type {basic,digest}
|
--auth-type {basic,digest}
|
||||||
@ -287,6 +295,7 @@ Changelog
|
|||||||
---------
|
---------
|
||||||
|
|
||||||
* `0.2.6dev <https://github.com/jkbr/httpie/compare/0.2.5...master>`_
|
* `0.2.6dev <https://github.com/jkbr/httpie/compare/0.2.5...master>`_
|
||||||
|
* Added exit status codes for HTTP 3xx, 4xx and 5xx (3, 4, 5).
|
||||||
* If the output is piped to another program or redirected to a file,
|
* If the output is piped to another program or redirected to a file,
|
||||||
the new default behaviour is to only print the response body.
|
the new default behaviour is to only print the response body.
|
||||||
(It can still be overriden via the ``--print`` flag.)
|
(It can still be overriden via the ``--print`` flag.)
|
||||||
|
@ -3,8 +3,9 @@
|
|||||||
The main entry point. Invoke as `http' or `python -m httpie'.
|
The main entry point. Invoke as `http' or `python -m httpie'.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import sys
|
||||||
from .core import main
|
from .core import main
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
sys.exit(main())
|
||||||
|
@ -125,6 +125,21 @@ parser.add_argument(
|
|||||||
''') % ', '.join(sorted(AVAILABLE_STYLES))
|
''') % ', '.join(sorted(AVAILABLE_STYLES))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
'--ignore-http-status', default=False, action='store_true',
|
||||||
|
help=_('''
|
||||||
|
This flag tells HTTP to ignore the HTTP status code
|
||||||
|
and exit with 0.
|
||||||
|
|
||||||
|
By default, HTTPie exits with 0 only if no errors occur
|
||||||
|
and the request is successful. When the server
|
||||||
|
replies with a 4xx (Client Error) or 5xx (Server Error)
|
||||||
|
status code, HTTPie exits with 4 or 5 respectively.
|
||||||
|
If the response is 3xx (Redirect) and --allow-redirects
|
||||||
|
isn't set, then the exit status is 3.
|
||||||
|
''')
|
||||||
|
)
|
||||||
|
|
||||||
# ``requests.request`` keyword arguments.
|
# ``requests.request`` keyword arguments.
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--auth', '-a', type=cliparse.AuthCredentialsType(cliparse.SEP_COMMON),
|
'--auth', '-a', type=cliparse.AuthCredentialsType(cliparse.SEP_COMMON),
|
||||||
|
@ -114,10 +114,39 @@ def get_output(args, env, response):
|
|||||||
return ''.join(buf)
|
return ''.join(buf)
|
||||||
|
|
||||||
|
|
||||||
|
def get_exist_status(code, allow_redirects=False):
|
||||||
|
"""
|
||||||
|
Translate HTTP status code to exit status.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if 300 <= code <= 399 and not allow_redirects:
|
||||||
|
# Redirect
|
||||||
|
return 3
|
||||||
|
elif 400 <= code <= 499:
|
||||||
|
# Client Error
|
||||||
|
return 4
|
||||||
|
elif 500 <= code <= 599:
|
||||||
|
# Server Error
|
||||||
|
return 5
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def main(args=sys.argv[1:], env=Environment()):
|
def main(args=sys.argv[1:], env=Environment()):
|
||||||
|
"""
|
||||||
|
Run the main program and write the output to ``env.stdout``.
|
||||||
|
|
||||||
|
Return exit status.
|
||||||
|
|
||||||
|
"""
|
||||||
args = cli.parser.parse_args(args=args, env=env)
|
args = cli.parser.parse_args(args=args, env=env)
|
||||||
response = get_response(args)
|
response = get_response(args)
|
||||||
output = get_output(args, env, response)
|
output = get_output(args, env, response)
|
||||||
output_bytes = output.encode('utf8')
|
output_bytes = output.encode('utf8')
|
||||||
f = getattr(env.stdout, 'buffer', env.stdout)
|
f = getattr(env.stdout, 'buffer', env.stdout)
|
||||||
f.write(output_bytes)
|
f.write(output_bytes)
|
||||||
|
if args.ignore_http_status:
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return get_exist_status(
|
||||||
|
response.status_code, args.allow_redirects)
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
Colorizing of HTTP messages and content processing.
|
Colorizing of HTTP messages and content processing.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import os
|
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
import pygments
|
import pygments
|
||||||
|
@ -21,8 +21,7 @@ import json
|
|||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
import argparse
|
import argparse
|
||||||
from requests import Response
|
from requests.compat import is_py26, is_py3, str
|
||||||
from requests.compat import is_py26, is_py3
|
|
||||||
|
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
@ -51,28 +50,40 @@ def httpbin(path):
|
|||||||
return HTTPBIN_URL + path
|
return HTTPBIN_URL + path
|
||||||
|
|
||||||
|
|
||||||
|
class Response(str):
|
||||||
|
"""
|
||||||
|
A unicode subclass holding the output of `main()` and the exit status.
|
||||||
|
|
||||||
|
"""
|
||||||
|
exit_status = None
|
||||||
|
|
||||||
|
|
||||||
def http(*args, **kwargs):
|
def http(*args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Invoke `httpie.__main__.main` with `args` and `kwargs`,
|
Invoke `httpie.core.main()` with `args` and `kwargs`,
|
||||||
and return a unicode response.
|
and return a unicode response.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if 'env' not in kwargs:
|
if 'env' not in kwargs:
|
||||||
# Ensure that we have terminal by default
|
# Ensure that we have terminal by default (needed for Travis).
|
||||||
# (needed for Travis).
|
|
||||||
kwargs['env'] = Environment(
|
kwargs['env'] = Environment(
|
||||||
colors=0,
|
colors=0,
|
||||||
stdin_isatty=True,
|
stdin_isatty=True,
|
||||||
stdout_isatty=True,
|
stdout_isatty=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
stdout = kwargs['env'].stdout = tempfile.TemporaryFile()
|
stdout = kwargs['env'].stdout = tempfile.TemporaryFile()
|
||||||
main(args=args, **kwargs)
|
|
||||||
|
exit_status = main(args=args, **kwargs)
|
||||||
|
|
||||||
stdout.seek(0)
|
stdout.seek(0)
|
||||||
response = stdout.read().decode('utf8')
|
|
||||||
|
response = Response(stdout.read().decode('utf8'))
|
||||||
|
response.exit_status = exit_status
|
||||||
|
|
||||||
stdout.close()
|
stdout.close()
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@ -494,6 +505,52 @@ class AuthTest(BaseTestCase):
|
|||||||
self.assertIn('"user": "user"', r)
|
self.assertIn('"user": "user"', r)
|
||||||
|
|
||||||
|
|
||||||
|
class ExitStatusTest(BaseTestCase):
|
||||||
|
|
||||||
|
def test_3xx_exits_3(self):
|
||||||
|
r = http(
|
||||||
|
'GET',
|
||||||
|
httpbin('/status/301')
|
||||||
|
)
|
||||||
|
self.assertIn('HTTP/1.1 301', r)
|
||||||
|
self.assertEqual(r.exit_status, 3)
|
||||||
|
|
||||||
|
def test_3xx_redirects_allowed_exits_0(self):
|
||||||
|
r = http(
|
||||||
|
'--allow-redirects',
|
||||||
|
'GET',
|
||||||
|
httpbin('/status/301')
|
||||||
|
)
|
||||||
|
# The redirect will be followed so 200 is expected.
|
||||||
|
self.assertIn('HTTP/1.1 200 OK', r)
|
||||||
|
self.assertEqual(r.exit_status, 0)
|
||||||
|
|
||||||
|
def test_4xx_exits_4(self):
|
||||||
|
r = http(
|
||||||
|
'GET',
|
||||||
|
httpbin('/status/401')
|
||||||
|
)
|
||||||
|
self.assertIn('HTTP/1.1 401', r)
|
||||||
|
self.assertEqual(r.exit_status, 4)
|
||||||
|
|
||||||
|
def test_5xx_exits_5(self):
|
||||||
|
r = http(
|
||||||
|
'GET',
|
||||||
|
httpbin('/status/500')
|
||||||
|
)
|
||||||
|
self.assertIn('HTTP/1.1 500', r)
|
||||||
|
self.assertEqual(r.exit_status, 5)
|
||||||
|
|
||||||
|
def test_ignore_http_status_exits_0(self):
|
||||||
|
r = http(
|
||||||
|
'--ignore-http-status',
|
||||||
|
'GET',
|
||||||
|
httpbin('/status/500')
|
||||||
|
)
|
||||||
|
self.assertIn('HTTP/1.1 500', r)
|
||||||
|
self.assertEqual(r.exit_status, 0)
|
||||||
|
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
# CLI argument parsing related tests.
|
# CLI argument parsing related tests.
|
||||||
#################################################################
|
#################################################################
|
||||||
|
Loading…
Reference in New Issue
Block a user