mirror of
https://github.com/httpie/cli.git
synced 2024-11-28 08:38:44 +02:00
Added exit status for timed-out requests.
This commit is contained in:
parent
76feea2f68
commit
c01dd8d64a
12
README.rst
12
README.rst
@ -7,7 +7,7 @@ v0.2.8dev
|
||||
☞ `README for stable version`_
|
||||
|
||||
HTTPie is a **command line HTTP client** whose goal is to make CLI interaction
|
||||
with HTTP-based services as **human-friendly** as possible. It provides a
|
||||
with web services as **human-friendly** as possible. It provides a
|
||||
simple ``http`` command that allows for sending arbitrary HTTP requests with a
|
||||
simple and natural syntax, and displays colorized responses. HTTPie can be used
|
||||
for **testing, debugging**, and generally **interacting** with HTTP servers.
|
||||
@ -82,7 +82,8 @@ Or, you can install the **development version** directly from GitHub:
|
||||
|
||||
|
||||
There are also packages available for `Ubuntu`_, `Debian`_, and possibly other
|
||||
Linux distributions as well.
|
||||
Linux distributions as well. However, they may be a significant delay between
|
||||
releases and package updates.
|
||||
|
||||
|
||||
=====
|
||||
@ -809,16 +810,18 @@ When using HTTPie from **shell scripts**, it can be handy to set the
|
||||
``--check-status`` flag. It instructs HTTPie to exit with an error if the
|
||||
HTTP status is one of ``3xx``, ``4xx``, or ``5xx``. The exit status will
|
||||
be ``3`` (unless ``--allow-redirects`` is set), ``4``, or ``5``,
|
||||
respectively:
|
||||
respectively. Also, the ``--timeout`` option allows to overwrite the default
|
||||
30s timeout:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
if http --check-status HEAD example.org/health &> /dev/null; then
|
||||
if http --timeout=2.5 --check-status HEAD example.org/health &> /dev/null; then
|
||||
echo 'OK!'
|
||||
else
|
||||
case $? in
|
||||
2) echo 'Request timed out!' ;;
|
||||
3) echo 'Unexpected HTTP 3xx Redirection!' ;;
|
||||
4) echo 'HTTP 4xx Client Error!' ;;
|
||||
5) echo 'HTTP 5xx Server Error!' ;;
|
||||
@ -933,6 +936,7 @@ Changelog
|
||||
=========
|
||||
|
||||
* `0.2.8dev`_
|
||||
* Added exit status code ``2`` for timed-out requests.
|
||||
* Added ``--colors`` and ``--format`` in addition to ``--pretty``, to
|
||||
be able to separate colorizing and formatting.
|
||||
* `0.2.7`_ (2012-08-07)
|
||||
|
@ -10,7 +10,9 @@ __licence__ = 'BSD'
|
||||
class EXIT:
|
||||
OK = 0
|
||||
ERROR = 1
|
||||
# Used only when requested:
|
||||
ERROR_TIMEOUT = 2
|
||||
|
||||
# Used only when requested with --check-status:
|
||||
ERROR_HTTP_3XX = 3
|
||||
ERROR_HTTP_4XX = 4
|
||||
ERROR_HTTP_5XX = 5
|
||||
|
@ -11,13 +11,11 @@ from . import __doc__
|
||||
from . import __version__
|
||||
from .output import AVAILABLE_STYLES, DEFAULT_STYLE
|
||||
from .input import (Parser, AuthCredentialsArgType, KeyValueArgType,
|
||||
PRETTY_STDOUT_TTY_ONLY,
|
||||
SEP_PROXY, SEP_CREDENTIALS, SEP_GROUP_ITEMS,
|
||||
OUT_REQ_HEAD, OUT_REQ_BODY, OUT_RESP_HEAD,
|
||||
OUT_RESP_BODY, OUTPUT_OPTIONS,
|
||||
PRETTY_STDOUT_TTY_ONLY, PRETTY_ALL,
|
||||
PRETTY_FORMAT,
|
||||
PRETTY_COLORS)
|
||||
PRETTY_FORMAT, PRETTY_COLORS)
|
||||
|
||||
|
||||
def _(text):
|
||||
@ -49,7 +47,7 @@ group_type.add_argument(
|
||||
The Content-Type is set to application/x-www-form-urlencoded
|
||||
(if not specified).
|
||||
The presence of any file fields results
|
||||
into a multipart/form-data request.
|
||||
in a multipart/form-data request.
|
||||
''')
|
||||
)
|
||||
|
||||
@ -57,7 +55,6 @@ group_type.add_argument(
|
||||
# Output options.
|
||||
#############################################
|
||||
|
||||
|
||||
parser.add_argument(
|
||||
'--output', '-o', type=argparse.FileType('w+b'),
|
||||
metavar='FILE',
|
||||
@ -65,7 +62,7 @@ parser.add_argument(
|
||||
'''
|
||||
Save output to FILE.
|
||||
This option is a replacement for piping output to FILE,
|
||||
which would on Windows result into corrupted data
|
||||
which would on Windows result in corrupted data
|
||||
being saved.
|
||||
|
||||
'''
|
||||
@ -151,8 +148,8 @@ parser.add_argument(
|
||||
''') % (', '.join(sorted(AVAILABLE_STYLES)), DEFAULT_STYLE)
|
||||
)
|
||||
|
||||
parser.add_argument('--stream', '-S', action='store_true', default=False, help=_(
|
||||
'''
|
||||
parser.add_argument('--stream', '-S', action='store_true', default=False,
|
||||
help=_('''
|
||||
Always stream the output by line, i.e., behave like `tail -f'.
|
||||
|
||||
Without --stream and with --pretty (either set or implied),
|
||||
@ -187,7 +184,7 @@ parser.add_argument(
|
||||
|
||||
# ``requests.request`` keyword arguments.
|
||||
parser.add_argument(
|
||||
'--auth', '-a',
|
||||
'--auth', '-a', metavar='USER:PASS',
|
||||
type=AuthCredentialsArgType(SEP_CREDENTIALS),
|
||||
help=_('''
|
||||
username:password.
|
||||
@ -230,10 +227,10 @@ parser.add_argument(
|
||||
''')
|
||||
)
|
||||
parser.add_argument(
|
||||
'--timeout', type=float, default=30,
|
||||
'--timeout', type=float, default=30, metavar='SECONDS',
|
||||
help=_('''
|
||||
The timeout of the request in seconds. The default value is 30
|
||||
seconds.
|
||||
The connection timeout of the request in seconds.
|
||||
The default value is 30 seconds.
|
||||
''')
|
||||
)
|
||||
parser.add_argument(
|
||||
|
@ -10,6 +10,7 @@ Invocation flow:
|
||||
5. Exit.
|
||||
|
||||
"""
|
||||
from _socket import gaierror
|
||||
import sys
|
||||
import json
|
||||
import errno
|
||||
@ -143,7 +144,7 @@ def main(args=sys.argv[1:], env=Environment()):
|
||||
|
||||
except IOError as e:
|
||||
if not traceback and e.errno == errno.EPIPE:
|
||||
# Ignore broken pipes unless --debug.
|
||||
# Ignore broken pipes unless --traceback.
|
||||
env.stderr.write('\n')
|
||||
else:
|
||||
raise
|
||||
@ -153,7 +154,9 @@ def main(args=sys.argv[1:], env=Environment()):
|
||||
raise
|
||||
env.stderr.write('\n')
|
||||
status = EXIT.ERROR
|
||||
|
||||
except requests.Timeout:
|
||||
status = EXIT.ERROR_TIMEOUT
|
||||
error('Request timed out (%ss).', args.timeout)
|
||||
except Exception as e:
|
||||
# TODO: distinguish between expected and unexpected errors.
|
||||
# network errors vs. bugs, etc.
|
||||
|
@ -20,10 +20,9 @@ from .input import (OUT_REQ_BODY, OUT_REQ_HEAD,
|
||||
OUT_RESP_HEAD, OUT_RESP_BODY)
|
||||
|
||||
|
||||
# Colors on Windows via colorama aren't that great and fruity
|
||||
# seems to give the best result there.
|
||||
# Colors on Windows via colorama don't look that
|
||||
# great and fruity seems to give the best result there.
|
||||
DEFAULT_STYLE = 'solarized' if not is_windows else 'fruity'
|
||||
|
||||
#noinspection PySetFunctionToLiteral
|
||||
AVAILABLE_STYLES = set([DEFAULT_STYLE]) | set(STYLE_MAP.keys())
|
||||
|
||||
@ -335,10 +334,9 @@ class BaseProcessor(object):
|
||||
|
||||
def __init__(self, env, **kwargs):
|
||||
"""
|
||||
:param env:
|
||||
an class:`Environment` instance
|
||||
:param kwargs:
|
||||
additional keyword argument that some processor might require.
|
||||
:param env: an class:`Environment` instance
|
||||
:param kwargs: additional keyword argument that some
|
||||
processor might require.
|
||||
|
||||
"""
|
||||
self.env = env
|
||||
@ -347,8 +345,7 @@ class BaseProcessor(object):
|
||||
def process_headers(self, headers):
|
||||
"""Return processed `headers`
|
||||
|
||||
:param headers:
|
||||
The headers as text.
|
||||
:param headers: The headers as text.
|
||||
|
||||
"""
|
||||
return headers
|
||||
@ -356,14 +353,9 @@ class BaseProcessor(object):
|
||||
def process_body(self, content, content_type, subtype):
|
||||
"""Return processed `content`.
|
||||
|
||||
:param content:
|
||||
The body content as text
|
||||
|
||||
:param content_type:
|
||||
Full content type, e.g., 'application/atom+xml'.
|
||||
|
||||
:param subtype:
|
||||
E.g. 'xml'.
|
||||
:param content: The body content as text
|
||||
:param content_type: Full content type, e.g., 'application/atom+xml'.
|
||||
:param subtype: E.g. 'xml'.
|
||||
|
||||
"""
|
||||
return content
|
||||
@ -458,13 +450,18 @@ class OutputProcessor(object):
|
||||
}
|
||||
|
||||
def __init__(self, env, groups, **kwargs):
|
||||
"""
|
||||
:param env: a :class:`models.Environment` instance
|
||||
:param groups: the groups of processors to be applied
|
||||
:param kwargs: additional keyword arguments for processors
|
||||
|
||||
processors = []
|
||||
"""
|
||||
self.processors = []
|
||||
for group in groups:
|
||||
for cls in self.installed_processors[group]:
|
||||
processors.append(cls(env, **kwargs))
|
||||
|
||||
self.processors = [p for p in processors if p.enabled]
|
||||
processor = cls(env, **kwargs)
|
||||
if processor.enable:
|
||||
self.processors.append(processor)
|
||||
|
||||
def process_headers(self, headers):
|
||||
for processor in self.processors:
|
||||
|
@ -860,6 +860,15 @@ class ExitStatusTest(BaseTestCase):
|
||||
)
|
||||
self.assertIn('HTTP/1.1 500', r)
|
||||
self.assertEqual(r.exit_status, EXIT.OK)
|
||||
self.assertTrue(not r.stderr)
|
||||
|
||||
def test_timeout_exit_status(self):
|
||||
r = http(
|
||||
'--timeout=0.5',
|
||||
'GET',
|
||||
httpbin('/delay/1')
|
||||
)
|
||||
self.assertEqual(r.exit_status, EXIT.ERROR_TIMEOUT)
|
||||
|
||||
def test_3xx_check_status_exits_3_and_stderr_when_stdout_redirected(self):
|
||||
r = http(
|
||||
|
Loading…
Reference in New Issue
Block a user