mirror of
https://github.com/httpie/cli.git
synced 2025-08-14 10:29:39 +02:00
Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
70a78249c1 | |||
fc85988368 | |||
83bd8059de | |||
3af5f1f305 | |||
4351650691 | |||
770976a66e | |||
29b692d597 | |||
8936d1b71e | |||
4f32b76223 | |||
c9d770017e | |||
cdf691c212 | |||
684a4708d7 | |||
5754e33a75 | |||
14fe7dbb27 | |||
3a6ac7d126 | |||
e9080e6b22 | |||
c73858b9c3 | |||
7340b2b64d | |||
8d246415fd | |||
381dd4f619 | |||
e6bad645ed | |||
6e9cd139a6 | |||
deee2dffd0 | |||
c3be722188 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -1,5 +1,5 @@
|
|||||||
name: Build
|
name: Build
|
||||||
on: [push]
|
on: [push, pull_request]
|
||||||
jobs:
|
jobs:
|
||||||
extras:
|
extras:
|
||||||
# Run coverage and extra tests only once
|
# Run coverage and extra tests only once
|
||||||
|
@ -6,6 +6,18 @@ This document records all notable changes to `HTTPie <https://httpie.org>`_.
|
|||||||
This project adheres to `Semantic Versioning <https://semver.org/>`_.
|
This project adheres to `Semantic Versioning <https://semver.org/>`_.
|
||||||
|
|
||||||
|
|
||||||
|
`2.1.0`_ (2020-04-18)
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
* Added ``--path-as-is`` to bypass dot segment (``/../`` or ``/./``)
|
||||||
|
URL squashing (#895).
|
||||||
|
* Changed the default value ``Accept`` header value for JSON requests from
|
||||||
|
``application/json, */*`` to ``application/json, */*;q=0.5``
|
||||||
|
to clearly indicate preference (#488).
|
||||||
|
* Fixed ``--form`` file upload mixed with redirected ``stdin`` error handling
|
||||||
|
(#840).
|
||||||
|
|
||||||
|
|
||||||
`2.0.0`_ (2020-01-12)
|
`2.0.0`_ (2020-01-12)
|
||||||
-------------------------
|
-------------------------
|
||||||
* Removed Python 2.7 support (`EOL Jan 2020 <https://www.python.org/doc/sunset-python-2/>`_).
|
* Removed Python 2.7 support (`EOL Jan 2020 <https://www.python.org/doc/sunset-python-2/>`_).
|
||||||
@ -14,7 +26,7 @@ This project adheres to `Semantic Versioning <https://semver.org/>`_.
|
|||||||
* Replaced the old collect-all-then-process handling of HTTP communication
|
* Replaced the old collect-all-then-process handling of HTTP communication
|
||||||
with one-by-one processing of each HTTP request or response as they become
|
with one-by-one processing of each HTTP request or response as they become
|
||||||
available. This means that you can see headers immediately,
|
available. This means that you can see headers immediately,
|
||||||
see what is being send even when the request fails, etc.
|
see what is being sent even if the request fails, etc.
|
||||||
* Removed automatic config file creation to avoid concurrency issues.
|
* Removed automatic config file creation to avoid concurrency issues.
|
||||||
* Removed the default 30-second connection ``--timeout`` limit.
|
* Removed the default 30-second connection ``--timeout`` limit.
|
||||||
* Removed Python’s default limit of 100 response headers.
|
* Removed Python’s default limit of 100 response headers.
|
||||||
@ -409,4 +421,9 @@ This project adheres to `Semantic Versioning <https://semver.org/>`_.
|
|||||||
.. _1.0.2: https://github.com/jakubroztocil/httpie/compare/1.0.1...1.0.2
|
.. _1.0.2: https://github.com/jakubroztocil/httpie/compare/1.0.1...1.0.2
|
||||||
.. _1.0.3: https://github.com/jakubroztocil/httpie/compare/1.0.2...1.0.3
|
.. _1.0.3: https://github.com/jakubroztocil/httpie/compare/1.0.2...1.0.3
|
||||||
.. _2.0.0: https://github.com/jakubroztocil/httpie/compare/1.0.3...2.0.0
|
.. _2.0.0: https://github.com/jakubroztocil/httpie/compare/1.0.3...2.0.0
|
||||||
.. _2.1.0-dev: https://github.com/jakubroztocil/httpie/compare/2.0.0...master
|
.. _2.1.0: https://github.com/jakubroztocil/httpie/compare/2.0.0...2.1.0
|
||||||
|
|
||||||
|
|
||||||
|
.. _#488:https://github.com/jakubroztocil/httpie/issues/488
|
||||||
|
.. _#840:https://github.com/jakubroztocil/httpie/issues/840
|
||||||
|
.. _#895:https://github.com/jakubroztocil/httpie/issues/895
|
||||||
|
2
LICENSE
2
LICENSE
@ -1,4 +1,4 @@
|
|||||||
Copyright © 2012-2019 Jakub Roztocil <jakub@roztocil.co>
|
Copyright © 2012-2020 Jakub Roztocil <jakub@roztocil.co>
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are met:
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
374
README.rst
374
README.rst
@ -27,11 +27,20 @@ generally interacting with HTTP servers.
|
|||||||
.. section-numbering::
|
.. section-numbering::
|
||||||
|
|
||||||
|
|
||||||
|
About this document
|
||||||
|
===================
|
||||||
|
|
||||||
|
This documentation is best viewed at `httpie.org/docs <https://httpie.org/docs>`_,
|
||||||
|
where you can select your corresponding HTTPie version as well as run examples directly from the
|
||||||
|
browser using a `termible.io <https://termible.io?utm_source=httpie-readme>`_ embedded terminal.
|
||||||
|
If you are reading this on GitHub, then this text covers the current *development* version.
|
||||||
|
You are invited to submit fixes and improvements to the the docs by editing
|
||||||
|
`README.rst <https://github.com/jakubroztocil/httpie/blob/master/README.rst>`_.
|
||||||
|
|
||||||
|
|
||||||
Main features
|
Main features
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
|
||||||
* Expressive and intuitive syntax
|
* Expressive and intuitive syntax
|
||||||
* Formatted and colorized terminal output
|
* Formatted and colorized terminal output
|
||||||
* Built-in JSON support
|
* Built-in JSON support
|
||||||
@ -86,7 +95,7 @@ system package manager, for example:
|
|||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# Debian, Ubuntu, etc.
|
# Debian, Ubuntu, etc.
|
||||||
$ apt-get install httpie
|
$ apt install httpie
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
@ -157,13 +166,13 @@ Otherwise with ``pip``:
|
|||||||
|
|
||||||
|
|
||||||
Verify that now we have the
|
Verify that now we have the
|
||||||
`current development version identifier <https://github.com/jakubroztocil/httpie/blob/0af6ae1be444588bbc4747124e073423151178a0/httpie/__init__.py#L5>`_
|
`current development version identifier <https://github.com/jakubroztocil/httpie/blob/master/httpie/__init__.py#L6>`_
|
||||||
with the ``-dev`` suffix, for example:
|
with the ``-dev`` suffix, for example:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http --version
|
$ http --version
|
||||||
1.0.0-dev
|
# 2.0.0-dev
|
||||||
|
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
@ -175,7 +184,7 @@ Hello World:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http httpie.org
|
$ http https://httpie.org/hello
|
||||||
|
|
||||||
|
|
||||||
Synopsis:
|
Synopsis:
|
||||||
@ -195,21 +204,28 @@ Custom `HTTP method`_, `HTTP headers`_ and `JSON`_ data:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http PUT example.org X-API-Token:123 name=John
|
$ http PUT httpbin.org/put X-API-Token:123 name=John
|
||||||
|
|
||||||
|
|
||||||
Submitting `forms`_:
|
Submitting `forms`_:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http -f POST example.org hello=World
|
$ http -f POST httpbin.org/post hello=World
|
||||||
|
|
||||||
|
|
||||||
See the request that is being sent using one of the `output options`_:
|
See the request that is being sent using one of the `output options`_:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http -v example.org
|
$ http -v httpbin.org/get
|
||||||
|
|
||||||
|
|
||||||
|
Build and print a request without sending it using `offline mode`_:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ http --offline httpbin.org/post hello=offline
|
||||||
|
|
||||||
|
|
||||||
Use `Github API`_ to post a comment on an
|
Use `Github API`_ to post a comment on an
|
||||||
@ -225,29 +241,33 @@ Upload a file using `redirected input`_:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http example.org < file.json
|
$ http httpbin.org/post < files/data.json
|
||||||
|
|
||||||
|
|
||||||
Download a file and save it via `redirected output`_:
|
Download a file and save it via `redirected output`_:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http example.org/file > file
|
$ http httpbin.org/image/png > image.png
|
||||||
|
|
||||||
|
|
||||||
Download a file ``wget`` style:
|
Download a file ``wget`` style:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http --download example.org/file
|
$ http --download httpbin.org/image/png
|
||||||
|
|
||||||
Use named `sessions`_ to make certain aspects or the communication persistent
|
Use named `sessions`_ to make certain aspects of the communication persistent
|
||||||
between requests to the same host:
|
between requests to the same host:
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http --session=logged-in -a username:password httpbin.org/get API-Key:123
|
$ http --session=logged-in -a username:password httpbin.org/get API-Key:123
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http --session=logged-in httpbin.org/headers
|
$ http --session=logged-in httpbin.org/headers
|
||||||
|
|
||||||
|
|
||||||
@ -267,14 +287,14 @@ The name of the HTTP method comes right before the URL argument:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http DELETE example.org/todos/7
|
$ http DELETE httpbin.org/delete
|
||||||
|
|
||||||
|
|
||||||
Which looks similar to the actual ``Request-Line`` that is sent:
|
Which looks similar to the actual ``Request-Line`` that is sent:
|
||||||
|
|
||||||
.. code-block:: http
|
.. code-block:: http
|
||||||
|
|
||||||
DELETE /todos/7 HTTP/1.1
|
DELETE /delete HTTP/1.1
|
||||||
|
|
||||||
|
|
||||||
When the ``METHOD`` argument is omitted from the command, HTTPie defaults to
|
When the ``METHOD`` argument is omitted from the command, HTTPie defaults to
|
||||||
@ -296,7 +316,7 @@ If you find yourself manually constructing URLs with querystring parameters
|
|||||||
on the terminal, you may appreciate the ``param==value`` syntax for appending
|
on the terminal, you may appreciate the ``param==value`` syntax for appending
|
||||||
URL parameters.
|
URL parameters.
|
||||||
|
|
||||||
With that, you don't have to worry about escaping the ``&``
|
With that, you don’t have to worry about escaping the ``&``
|
||||||
separators for your shell. Additionally, any special characters in the
|
separators for your shell. Additionally, any special characters in the
|
||||||
parameter name or value get automatically URL-escaped
|
parameter name or value get automatically URL-escaped
|
||||||
(as opposed to parameters specified in the full URL, which HTTPie doesn’t
|
(as opposed to parameters specified in the full URL, which HTTPie doesn’t
|
||||||
@ -380,6 +400,34 @@ Example for the `httpie-unixsocket <https://github.com/httpie/httpie-unixsocket>
|
|||||||
# Now the scheme can be omitted
|
# Now the scheme can be omitted
|
||||||
$ http-unix %2Fvar%2Frun%2Fdocker.sock/info
|
$ http-unix %2Fvar%2Frun%2Fdocker.sock/info
|
||||||
|
|
||||||
|
|
||||||
|
``--path-as-is``
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The standard behaviour of HTTP clients is to normalize the path portion of URLs by squashing dot segments
|
||||||
|
as a typically filesystem would:
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ http -v example.org/./../../etc/password
|
||||||
|
|
||||||
|
.. code-block:: http
|
||||||
|
|
||||||
|
GET /etc/password HTTP/1.1
|
||||||
|
|
||||||
|
|
||||||
|
The ``--path-as-is`` option allows you to disable this behavior:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ http --path-as-is -v example.org/./../../etc/password
|
||||||
|
|
||||||
|
.. code-block:: http
|
||||||
|
|
||||||
|
GET /../../etc/password HTTP/1.1
|
||||||
|
|
||||||
|
|
||||||
Request items
|
Request items
|
||||||
=============
|
=============
|
||||||
|
|
||||||
@ -420,14 +468,14 @@ their type is distinguished only by the separator used:
|
|||||||
+-----------------------+-----------------------------------------------------+
|
+-----------------------+-----------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
Note that data fields aren't the only way to specify request data:
|
Note that data fields aren’t the only way to specify request data:
|
||||||
`Redirected input`_ is a mechanism for passing arbitrary request data.
|
`Redirected input`_ is a mechanism for passing arbitrary request data.
|
||||||
|
|
||||||
|
|
||||||
Escaping rules
|
Escaping rules
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
You can use ``\`` to escape characters that shouldn't be used as separators
|
You can use ``\`` to escape characters that shouldn’t be used as separators
|
||||||
(or parts thereof). For instance, ``foo\==bar`` will become a data key/value
|
(or parts thereof). For instance, ``foo\==bar`` will become a data key/value
|
||||||
pair (``foo=`` and ``bar``) instead of a URL parameter.
|
pair (``foo=`` and ``bar``) instead of a URL parameter.
|
||||||
|
|
||||||
@ -464,15 +512,15 @@ Simple example:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http PUT example.org name=John email=john@example.org
|
$ http PUT httpbin.org/put name=John email=john@example.org
|
||||||
|
|
||||||
.. code-block:: http
|
.. code-block:: http
|
||||||
|
|
||||||
PUT / HTTP/1.1
|
PUT / HTTP/1.1
|
||||||
Accept: application/json, */*
|
Accept: application/json, */*;q=0.5
|
||||||
Accept-Encoding: gzip, deflate
|
Accept-Encoding: gzip, deflate
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Host: example.org
|
Host: httpbin.org
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "John",
|
"name": "John",
|
||||||
@ -490,7 +538,7 @@ both of which can be overwritten:
|
|||||||
|
|
||||||
================ =======================================
|
================ =======================================
|
||||||
``Content-Type`` ``application/json``
|
``Content-Type`` ``application/json``
|
||||||
``Accept`` ``application/json, */*``
|
``Accept`` ``application/json, */*;q=0.5``
|
||||||
================ =======================================
|
================ =======================================
|
||||||
|
|
||||||
|
|
||||||
@ -499,8 +547,8 @@ Explicit JSON
|
|||||||
|
|
||||||
You can use ``--json, -j`` to explicitly set ``Accept``
|
You can use ``--json, -j`` to explicitly set ``Accept``
|
||||||
to ``application/json`` regardless of whether you are sending data
|
to ``application/json`` regardless of whether you are sending data
|
||||||
(it's a shortcut for setting the header via the usual header notation:
|
(it’s a shortcut for setting the header via the usual header notation:
|
||||||
``http url Accept:'application/json, */*'``). Additionally,
|
``http url Accept:'application/json, */*;q=0.5'``). Additionally,
|
||||||
HTTPie will try to detect JSON responses even when the
|
HTTPie will try to detect JSON responses even when the
|
||||||
``Content-Type`` is incorrectly ``text/plain`` or unknown.
|
``Content-Type`` is incorrectly ``text/plain`` or unknown.
|
||||||
|
|
||||||
@ -509,25 +557,28 @@ HTTPie will try to detect JSON responses even when the
|
|||||||
Non-string JSON fields
|
Non-string JSON fields
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
Non-string fields use the ``:=`` separator, which allows you to embed raw JSON
|
Non-string JSON fields use the ``:=`` separator, which allows you to embed arbitrary JSON data
|
||||||
into the resulting object. Text and raw JSON files can also be embedded into
|
into the resulting JSON object. Additionally, text and raw JSON files can also be embedded into
|
||||||
fields using ``=@`` and ``:=@``:
|
fields using ``=@`` and ``:=@``:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http PUT api.example.com/person/1 \
|
$ http PUT httpbin.org/put \
|
||||||
name=John \
|
name=John \ # String (default)
|
||||||
age:=29 married:=false hobbies:='["http", "pies"]' \ # Raw JSON
|
age:=29 \ # Raw JSON — Number
|
||||||
description=@about-john.txt \ # Embed text file
|
married:=false \ # Raw JSON — Boolean
|
||||||
bookmarks:=@bookmarks.json # Embed JSON file
|
hobbies:='["http", "pies"]' \ # Raw JSON — Array
|
||||||
|
favorite:='{"tool": "HTTPie"}' \ # Raw JSON — Object
|
||||||
|
bookmarks:=@files/data.json \ # Embed JSON file
|
||||||
|
description=@files/text.txt # Embed text file
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: http
|
.. code-block:: http
|
||||||
|
|
||||||
PUT /person/1 HTTP/1.1
|
PUT /person/1 HTTP/1.1
|
||||||
Accept: application/json, */*
|
Accept: application/json, */*;q=0.5
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Host: api.example.com
|
Host: httpbin.org
|
||||||
|
|
||||||
{
|
{
|
||||||
"age": 29,
|
"age": 29,
|
||||||
@ -538,19 +589,33 @@ fields using ``=@`` and ``:=@``:
|
|||||||
"description": "John is a nice guy who likes pies.",
|
"description": "John is a nice guy who likes pies.",
|
||||||
"married": false,
|
"married": false,
|
||||||
"name": "John",
|
"name": "John",
|
||||||
|
"favorite": {
|
||||||
|
"tool": "HTTPie"
|
||||||
|
},
|
||||||
"bookmarks": {
|
"bookmarks": {
|
||||||
"HTTPie": "https://httpie.org",
|
"HTTPie": "https://httpie.org",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Please note that with this syntax the command gets unwieldy when sending
|
Raw and complex JSON
|
||||||
complex data. In that case it's always better to use `redirected input`_:
|
--------------------
|
||||||
|
|
||||||
|
Please note that with the `request items`_ data field syntax, commands
|
||||||
|
can quickly become unwieldy when sending complex structures.
|
||||||
|
In such cases, it’s better to pass the full raw JSON data via
|
||||||
|
`redirected input`_, for example:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http POST api.example.com/person/1 < person.json
|
$ echo '{"hello": "world"}' | http POST httpbin.org/post
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ http POST httpbin.org/post < files/data.json
|
||||||
|
|
||||||
|
Furthermore, this syntax only allows you to send an object as the JSON document, but not an array, etc.
|
||||||
|
Here, again, the solution is to use `redirected input`_.
|
||||||
|
|
||||||
Forms
|
Forms
|
||||||
=====
|
=====
|
||||||
@ -568,12 +633,12 @@ Regular forms
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http --form POST api.example.org/person/1 name='John Smith'
|
$ http --form POST httpbin.org/post name='John Smith'
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: http
|
.. code-block:: http
|
||||||
|
|
||||||
POST /person/1 HTTP/1.1
|
POST /post HTTP/1.1
|
||||||
Content-Type: application/x-www-form-urlencoded; charset=utf-8
|
Content-Type: application/x-www-form-urlencoded; charset=utf-8
|
||||||
|
|
||||||
name=John+Smith
|
name=John+Smith
|
||||||
@ -587,7 +652,7 @@ If one or more file fields is present, the serialization and content type is
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http -f POST example.com/jobs name='John Smith' cv@~/Documents/cv.pdf
|
$ http -f POST httpbin.org/post name='John Smith' cv@~/files/data.xml
|
||||||
|
|
||||||
|
|
||||||
The request above is the same as if the following HTML form were
|
The request above is the same as if the following HTML form were
|
||||||
@ -611,17 +676,17 @@ To set custom headers you can use the ``Header:Value`` notation:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http example.org User-Agent:Bacon/1.0 'Cookie:valued-visitor=yes;foo=bar' \
|
$ http httpbin.org/headers User-Agent:Bacon/1.0 'Cookie:valued-visitor=yes;foo=bar' \
|
||||||
X-Foo:Bar Referer:https://httpie.org/
|
X-Foo:Bar Referer:https://httpie.org/
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: http
|
.. code-block:: http
|
||||||
|
|
||||||
GET / HTTP/1.1
|
GET /headers HTTP/1.1
|
||||||
Accept: */*
|
Accept: */*
|
||||||
Accept-Encoding: gzip, deflate
|
Accept-Encoding: gzip, deflate
|
||||||
Cookie: valued-visitor=yes;foo=bar
|
Cookie: valued-visitor=yes;foo=bar
|
||||||
Host: example.org
|
Host: httpbin.org
|
||||||
Referer: https://httpie.org/
|
Referer: https://httpie.org/
|
||||||
User-Agent: Bacon/1.0
|
User-Agent: Bacon/1.0
|
||||||
X-Foo: Bar
|
X-Foo: Bar
|
||||||
@ -679,6 +744,50 @@ HTTPie reads before giving up (the default ``0``, i.e., there’s no limit).
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Offline mode
|
||||||
|
============
|
||||||
|
|
||||||
|
Use ``--offline`` to construct HTTP requests without sending them anywhere.
|
||||||
|
With ``--offline``, HTTPie builds a request based on the specified options and arguments, prints it to ``stdout``,
|
||||||
|
and then exists. It works completely offline; no network connection is ever made.
|
||||||
|
This has a number of use cases, including:
|
||||||
|
|
||||||
|
|
||||||
|
Generating API documentation examples that you can copy & paste without sending a request:
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ http --offline POST server.chess/api/games API-Key:ZZZ w=magnus b=hikaru t=180 i=2
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ http --offline MOVE server.chess/api/games/123 API-Key:ZZZ p=b a=R1a3 t=77
|
||||||
|
|
||||||
|
|
||||||
|
Generating raw requests that can be sent with any other client:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# 1. save a raw request to a file:
|
||||||
|
$ http --offline POST httpbin.org/post hello=world > request.http
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# 2. send it over the wire with, for example, the fantastic netcat tool:
|
||||||
|
$ nc httpbin.org 80 < request.http
|
||||||
|
|
||||||
|
|
||||||
|
You can also use the ``--offline`` mode for debugging and exploring HTTP and HTTPie, and for “dry runs”.
|
||||||
|
|
||||||
|
``--offline`` has the side-effect of automatically activating ``--print=HB``, i.e., both the request headers and the body
|
||||||
|
are printed. You can customize the output with the usual `output options`_, with the exception that there
|
||||||
|
is not response to be printed. You can use ``--offline`` in combination with all the other options (e.g., ``--session``).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Cookies
|
Cookies
|
||||||
=======
|
=======
|
||||||
|
|
||||||
@ -691,7 +800,7 @@ Send a single cookie:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http example.org Cookie:sessionid=foo
|
$ http httpbin.org/cookies Cookie:sessionid=foo
|
||||||
|
|
||||||
.. code-block:: http
|
.. code-block:: http
|
||||||
|
|
||||||
@ -700,7 +809,7 @@ Send a single cookie:
|
|||||||
Accept-Encoding: gzip, deflate
|
Accept-Encoding: gzip, deflate
|
||||||
Connection: keep-alive
|
Connection: keep-alive
|
||||||
Cookie: sessionid=foo
|
Cookie: sessionid=foo
|
||||||
Host: example.org
|
Host: httpbin.org
|
||||||
User-Agent: HTTPie/0.9.9
|
User-Agent: HTTPie/0.9.9
|
||||||
|
|
||||||
|
|
||||||
@ -709,7 +818,7 @@ Send multiple cookies
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http example.org 'Cookie:sessionid=foo;another-cookie=bar'
|
$ http httpbin.org/cookies 'Cookie:sessionid=foo;another-cookie=bar'
|
||||||
|
|
||||||
.. code-block:: http
|
.. code-block:: http
|
||||||
|
|
||||||
@ -718,11 +827,11 @@ Send multiple cookies
|
|||||||
Accept-Encoding: gzip, deflate
|
Accept-Encoding: gzip, deflate
|
||||||
Connection: keep-alive
|
Connection: keep-alive
|
||||||
Cookie: sessionid=foo;another-cookie=bar
|
Cookie: sessionid=foo;another-cookie=bar
|
||||||
Host: example.org
|
Host: httpbin.org
|
||||||
User-Agent: HTTPie/0.9.9
|
User-Agent: HTTPie/0.9.9
|
||||||
|
|
||||||
|
|
||||||
If you often deal with cookies in your requests, then chances are you'd appreciate
|
If you often deal with cookies in your requests, then chances are you’d appreciate
|
||||||
the `sessions`_ feature.
|
the `sessions`_ feature.
|
||||||
|
|
||||||
|
|
||||||
@ -735,7 +844,7 @@ The currently supported authentication schemes are Basic and Digest
|
|||||||
=================== ======================================================
|
=================== ======================================================
|
||||||
``--auth, -a`` Pass a ``username:password`` pair as
|
``--auth, -a`` Pass a ``username:password`` pair as
|
||||||
the argument. Or, if you only specify a username
|
the argument. Or, if you only specify a username
|
||||||
(``-a username``), you'll be prompted for
|
(``-a username``), you’ll be prompted for
|
||||||
the password before the request is sent.
|
the password before the request is sent.
|
||||||
To send an empty password, pass ``username:``.
|
To send an empty password, pass ``username:``.
|
||||||
The ``username:password@hostname`` URL syntax is
|
The ``username:password@hostname`` URL syntax is
|
||||||
@ -755,7 +864,7 @@ Basic auth
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http -a username:password example.org
|
$ http -a username:password httpbin.org/basic-auth/username/password
|
||||||
|
|
||||||
|
|
||||||
Digest auth
|
Digest auth
|
||||||
@ -764,7 +873,7 @@ Digest auth
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http -A digest -a username:password example.org
|
$ http -A digest -a username:password httpbin.org/digest-auth/httpie/username/password
|
||||||
|
|
||||||
|
|
||||||
Password prompt
|
Password prompt
|
||||||
@ -772,7 +881,15 @@ Password prompt
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http -a username example.org
|
$ http -a username httpbin.org/basic-auth/username/password
|
||||||
|
|
||||||
|
|
||||||
|
Empty password
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ http -a username: httpbin.org/headers
|
||||||
|
|
||||||
|
|
||||||
``.netrc``
|
``.netrc``
|
||||||
@ -810,7 +927,7 @@ Auth plugins
|
|||||||
|
|
||||||
Additional authentication mechanism can be installed as plugins.
|
Additional authentication mechanism can be installed as plugins.
|
||||||
They can be found on the `Python Package Index <https://pypi.python.org/pypi?%3Aaction=search&term=httpie&submit=search>`_.
|
They can be found on the `Python Package Index <https://pypi.python.org/pypi?%3Aaction=search&term=httpie&submit=search>`_.
|
||||||
Here's a few picks:
|
Here’s a few picks:
|
||||||
|
|
||||||
* `httpie-api-auth <https://github.com/pd/httpie-api-auth>`_: ApiAuth
|
* `httpie-api-auth <https://github.com/pd/httpie-api-auth>`_: ApiAuth
|
||||||
* `httpie-aws-auth <https://github.com/httpie/httpie-aws-auth>`_: AWS / Amazon S3
|
* `httpie-aws-auth <https://github.com/httpie/httpie-aws-auth>`_: AWS / Amazon S3
|
||||||
@ -871,7 +988,7 @@ To change the default limit of maximum ``30`` redirects, use the
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http --follow --all --max-redirects=5 httpbin.org/redirect/3
|
$ http --follow --all --max-redirects=2 httpbin.org/redirect/3
|
||||||
|
|
||||||
|
|
||||||
Proxies
|
Proxies
|
||||||
@ -913,7 +1030,7 @@ SOCKS
|
|||||||
-----
|
-----
|
||||||
|
|
||||||
Homebrew-installed HTTPie comes with SOCKS proxy support out of the box.
|
Homebrew-installed HTTPie comes with SOCKS proxy support out of the box.
|
||||||
To enable SOCKS proxy support for non-Homebrew installations, you'll
|
To enable SOCKS proxy support for non-Homebrew installations, you’ll
|
||||||
might need to install ``requests[socks]`` manually using ``pip``:
|
might need to install ``requests[socks]`` manually using ``pip``:
|
||||||
|
|
||||||
|
|
||||||
@ -935,12 +1052,12 @@ HTTPS
|
|||||||
Server SSL certificate verification
|
Server SSL certificate verification
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
||||||
To skip the host's SSL certificate verification, you can pass ``--verify=no``
|
To skip the host’s SSL certificate verification, you can pass ``--verify=no``
|
||||||
(default is ``yes``):
|
(default is ``yes``):
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http --verify=no https://example.org
|
$ http --verify=no https://httpbin.org/get
|
||||||
|
|
||||||
|
|
||||||
Custom CA bundle
|
Custom CA bundle
|
||||||
@ -1009,7 +1126,7 @@ documentation examples:
|
|||||||
|
|
||||||
$ http --verbose PUT httpbin.org/put hello=world
|
$ http --verbose PUT httpbin.org/put hello=world
|
||||||
PUT /put HTTP/1.1
|
PUT /put HTTP/1.1
|
||||||
Accept: application/json, */*
|
Accept: application/json, */*;q=0.5
|
||||||
Accept-Encoding: gzip, deflate
|
Accept-Encoding: gzip, deflate
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
Host: httpbin.org
|
Host: httpbin.org
|
||||||
@ -1071,7 +1188,7 @@ authentication is used (``--auth=digest``), etc.
|
|||||||
|
|
||||||
|
|
||||||
The intermediary requests/response are by default formatted according to
|
The intermediary requests/response are by default formatted according to
|
||||||
``--print, -p`` (and its shortcuts described above). If you'd like to change
|
``--print, -p`` (and its shortcuts described above). If you’d like to change
|
||||||
that, use the ``--history-print, -P`` option. It takes the same
|
that, use the ``--history-print, -P`` option. It takes the same
|
||||||
arguments as ``--print, -p`` but applies to the intermediary requests only.
|
arguments as ``--print, -p`` but applies to the intermediary requests only.
|
||||||
|
|
||||||
@ -1086,22 +1203,22 @@ Conditional body download
|
|||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
As an optimization, the response body is downloaded from the server
|
As an optimization, the response body is downloaded from the server
|
||||||
only if it's part of the output. This is similar to performing a ``HEAD``
|
only if it’s part of the output. This is similar to performing a ``HEAD``
|
||||||
request, except that it applies to any HTTP method you use.
|
request, except that it applies to any HTTP method you use.
|
||||||
|
|
||||||
Let's say that there is an API that returns the whole resource when it is
|
Let’s say that there is an API that returns the whole resource when it is
|
||||||
updated, but you are only interested in the response headers to see the
|
updated, but you are only interested in the response headers to see the
|
||||||
status code after an update:
|
status code after an update:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http --headers PATCH example.org/Really-Huge-Resource name='New Name'
|
$ http --headers PATCH httpbin.org/patch name='New Name'
|
||||||
|
|
||||||
|
|
||||||
Since we are only printing the HTTP headers here, the connection to the server
|
Since we are only printing the HTTP headers here, the connection to the server
|
||||||
is closed as soon as all the response headers have been received.
|
is closed as soon as all the response headers have been received.
|
||||||
Therefore, bandwidth and time isn't wasted downloading the body
|
Therefore, bandwidth and time isn’t wasted downloading the body
|
||||||
which you don't care about. The response headers are downloaded always,
|
which you don’t care about. The response headers are downloaded always,
|
||||||
even if they are not part of the output
|
even if they are not part of the output
|
||||||
|
|
||||||
|
|
||||||
@ -1117,28 +1234,28 @@ Redirect from a file:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http PUT example.com/person/1 X-API-Token:123 < person.json
|
$ http PUT httpbin.org/put X-API-Token:123 < files/data.json
|
||||||
|
|
||||||
|
|
||||||
Or the output of another program:
|
Or the output of another program:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ grep '401 Unauthorized' /var/log/httpd/error_log | http POST example.org/intruders
|
$ grep '401 Unauthorized' /var/log/httpd/error_log | http POST httpbin.org/post
|
||||||
|
|
||||||
|
|
||||||
You can use ``echo`` for simple data:
|
You can use ``echo`` for simple data:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ echo '{"name": "John"}' | http PATCH example.com/person/1 X-API-Token:123
|
$ echo '{"name": "John"}' | http PATCH httpbin.org/patch X-API-Token:123
|
||||||
|
|
||||||
|
|
||||||
You can also use a Bash *here string*:
|
You can also use a Bash *here string*:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http example.com/ <<<'{"name": "John"}'
|
$ http httpbin.org/post <<<'{"name": "John"}'
|
||||||
|
|
||||||
|
|
||||||
You can even pipe web services together using HTTPie:
|
You can even pipe web services together using HTTPie:
|
||||||
@ -1152,14 +1269,14 @@ You can use ``cat`` to enter multiline data on the terminal:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ cat | http POST example.com
|
$ cat | http POST httpbin.org/post
|
||||||
<paste>
|
<paste>
|
||||||
^D
|
^D
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ cat | http POST example.com/todos Content-Type:text/plain
|
$ cat | http POST httpbin.org/post Content-Type:text/plain
|
||||||
- buy milk
|
- buy milk
|
||||||
- call parents
|
- call parents
|
||||||
^D
|
^D
|
||||||
@ -1169,7 +1286,7 @@ On OS X, you can send the contents of the clipboard with ``pbpaste``:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ pbpaste | http PUT example.com
|
$ pbpaste | http PUT httpbin.org/put
|
||||||
|
|
||||||
|
|
||||||
Passing data through ``stdin`` cannot be combined with data fields specified
|
Passing data through ``stdin`` cannot be combined with data fields specified
|
||||||
@ -1198,7 +1315,7 @@ verbatim contents of that XML file with ``Content-Type: application/xml``:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http PUT httpbin.org/put @/data/file.xml
|
$ http PUT httpbin.org/put @files/data.xml
|
||||||
|
|
||||||
|
|
||||||
Terminal output
|
Terminal output
|
||||||
@ -1213,8 +1330,16 @@ Colors and formatting
|
|||||||
|
|
||||||
Syntax highlighting is applied to HTTP headers and bodies (where it makes
|
Syntax highlighting is applied to HTTP headers and bodies (where it makes
|
||||||
sense). You can choose your preferred color scheme via the ``--style`` option
|
sense). You can choose your preferred color scheme via the ``--style`` option
|
||||||
if you don't like the default one (see ``$ http --help`` for the possible
|
if you don’t like the default one. There dozens of styles available, here are just a few special or notable ones:
|
||||||
values).
|
|
||||||
|
==================== ========================================================================
|
||||||
|
``auto`` Follows your terminal ANSI color styles. This is the default style used by HTTPie.
|
||||||
|
``default`` Default styles of the underlying Pygments library. Not actually used by default by HTTPie.
|
||||||
|
You can enable it with ``--style=default``
|
||||||
|
``monokai`` A popular color scheme. Enable with ``--style=monokai``.
|
||||||
|
``fruity`` A bold, colorful scheme. Enable with ``--style=fruity``.
|
||||||
|
… See ``$ http --help`` for all the possible ``--style`` values.
|
||||||
|
==================== ========================================================================
|
||||||
|
|
||||||
Also, the following formatting is applied:
|
Also, the following formatting is applied:
|
||||||
|
|
||||||
@ -1243,7 +1368,7 @@ that the response body is binary,
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http example.org/Movie.mov
|
$ http httpbin.org/bytes/2000
|
||||||
|
|
||||||
|
|
||||||
You will nearly instantly see something like this:
|
You will nearly instantly see something like this:
|
||||||
@ -1251,10 +1376,7 @@ You will nearly instantly see something like this:
|
|||||||
.. code-block:: http
|
.. code-block:: http
|
||||||
|
|
||||||
HTTP/1.1 200 OK
|
HTTP/1.1 200 OK
|
||||||
Accept-Ranges: bytes
|
Content-Type: application/octet-stream
|
||||||
Content-Encoding: gzip
|
|
||||||
Content-Type: video/quicktime
|
|
||||||
Transfer-Encoding: chunked
|
|
||||||
|
|
||||||
+-----------------------------------------+
|
+-----------------------------------------+
|
||||||
| NOTE: binary data not shown in terminal |
|
| NOTE: binary data not shown in terminal |
|
||||||
@ -1267,11 +1389,11 @@ Redirected output
|
|||||||
HTTPie uses a different set of defaults for redirected output than for
|
HTTPie uses a different set of defaults for redirected output than for
|
||||||
`terminal output`_. The differences being:
|
`terminal output`_. The differences being:
|
||||||
|
|
||||||
* Formatting and colors aren't applied (unless ``--pretty`` is specified).
|
* Formatting and colors aren’t applied (unless ``--pretty`` is specified).
|
||||||
* Only the response body is printed (unless one of the `output options`_ is set).
|
* Only the response body is printed (unless one of the `output options`_ is set).
|
||||||
* Also, binary data isn't suppressed.
|
* Also, binary data isn’t suppressed.
|
||||||
|
|
||||||
The reason is to make piping HTTPie's output to another programs and
|
The reason is to make piping HTTPie’s output to another programs and
|
||||||
downloading files work with no extra flags. Most of the time, only the raw
|
downloading files work with no extra flags. Most of the time, only the raw
|
||||||
response body is of an interest when the output is redirected.
|
response body is of an interest when the output is redirected.
|
||||||
|
|
||||||
@ -1279,7 +1401,7 @@ Download a file:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http example.org/Movie.mov > Movie.mov
|
$ http httpbin.org/image/png > image.png
|
||||||
|
|
||||||
|
|
||||||
Download an image of Octocat, resize it using ImageMagick, upload it elsewhere:
|
Download an image of Octocat, resize it using ImageMagick, upload it elsewhere:
|
||||||
@ -1294,7 +1416,7 @@ Force colorizing and formatting, and show both the request and the response in
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http --pretty=all --verbose example.org | less -R
|
$ http --pretty=all --verbose httpbin.org/get | less -R
|
||||||
|
|
||||||
|
|
||||||
The ``-R`` flag tells ``less`` to interpret color escape sequences included
|
The ``-R`` flag tells ``less`` to interpret color escape sequences included
|
||||||
@ -1373,7 +1495,7 @@ Resuming downloads
|
|||||||
|
|
||||||
If ``--output, -o`` is specified, you can resume a partial download using the
|
If ``--output, -o`` is specified, you can resume a partial download using the
|
||||||
``--continue, -c`` option. This only works with servers that support
|
``--continue, -c`` option. This only works with servers that support
|
||||||
``Range`` requests and ``206 Partial Content`` responses. If the server doesn't
|
``Range`` requests and ``206 Partial Content`` responses. If the server doesn’t
|
||||||
support that, the whole file will simply be downloaded:
|
support that, the whole file will simply be downloaded:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
@ -1386,7 +1508,9 @@ Other notes
|
|||||||
* The ``--download`` option only changes how the response body is treated.
|
* The ``--download`` option only changes how the response body is treated.
|
||||||
* You can still set custom headers, use sessions, ``--verbose, -v``, etc.
|
* You can still set custom headers, use sessions, ``--verbose, -v``, etc.
|
||||||
* ``--download`` always implies ``--follow`` (redirects are followed).
|
* ``--download`` always implies ``--follow`` (redirects are followed).
|
||||||
* HTTPie exits with status code ``1`` (error) if the body hasn't been fully
|
* ``--download`` also implies ``--check-status``
|
||||||
|
(error HTTP status will result in a non-zero exist static code).
|
||||||
|
* HTTPie exits with status code ``1`` (error) if the body hasn’t been fully
|
||||||
downloaded.
|
downloaded.
|
||||||
* ``Accept-Encoding`` cannot be set with ``--download``.
|
* ``Accept-Encoding`` cannot be set with ``--download``.
|
||||||
|
|
||||||
@ -1424,7 +1548,7 @@ Prettified streamed response:
|
|||||||
$ http --stream -f -a YOUR-TWITTER-NAME https://stream.twitter.com/1/statuses/filter.json track='Justin Bieber'
|
$ http --stream -f -a YOUR-TWITTER-NAME https://stream.twitter.com/1/statuses/filter.json track='Justin Bieber'
|
||||||
|
|
||||||
|
|
||||||
Streamed output by small chunks alá ``tail -f``:
|
Streamed output by small chunks à la ``tail -f``:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
@ -1450,11 +1574,19 @@ to the same host.
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
# Create a new session
|
# Create a new session:
|
||||||
$ http --session=/tmp/session.json example.org API-Token:123
|
$ http --session=./session.json httpbin.org/headers API-Token:123
|
||||||
|
|
||||||
# Re-use an existing session — API-Token will be set:
|
|
||||||
$ http --session=/tmp/session.json example.org
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# Inspect / edit the generated session file:
|
||||||
|
$ cat session.json
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# Re-use the existing session — the API-Token header will be set:
|
||||||
|
$ http --session=./session.json httpbin.org/headers
|
||||||
|
|
||||||
|
|
||||||
All session data, including credentials, cookie data,
|
All session data, including credentials, cookie data,
|
||||||
@ -1469,31 +1601,39 @@ Named sessions
|
|||||||
|
|
||||||
|
|
||||||
You can create one or more named session per host. For example, this is how
|
You can create one or more named session per host. For example, this is how
|
||||||
you can create a new session named ``user1`` for ``example.org``:
|
you can create a new session named ``user1`` for ``httpbin.org``:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http --session=user1 -a user1:password example.org X-Foo:Bar
|
$ http --session=user1 -a user1:password httpbin.org/get X-Foo:Bar
|
||||||
|
|
||||||
From now on, you can refer to the session by its name. When you choose to
|
From now on, you can refer to the session by its name (``user1``). When you choose
|
||||||
use the session again, any previously specified authentication or HTTP headers
|
to use the session again, any previously specified authentication or HTTP headers
|
||||||
will automatically be set:
|
will automatically be set:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http --session=user1 example.org
|
$ http --session=user1 httpbin.org/get
|
||||||
|
|
||||||
To create or reuse a different session, simple specify a different name:
|
To create or reuse a different session, simple specify a different name:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http --session=user2 -a user2:password example.org X-Bar:Foo
|
$ http --session=user2 -a user2:password httpbin.org/get X-Bar:Foo
|
||||||
|
|
||||||
Named sessions’s data is stored in JSON files in the the ``sessions``
|
Named sessions’s data is stored in JSON files in the the ``sessions``
|
||||||
subdirectory of the `config`_ directory:
|
subdirectory of the `config`_ directory:
|
||||||
``~/.httpie/sessions/<host>/<name>.json``
|
``~/.httpie/sessions/<host>/<name>.json``
|
||||||
(``%APPDATA%\httpie\sessions\<host>\<name>.json`` on Windows).
|
(``%APPDATA%\httpie\sessions\<host>\<name>.json`` on Windows).
|
||||||
|
|
||||||
|
If you have executed the above commands on a unix machine,
|
||||||
|
you should be able list the generated sessions files using:
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ ls -l ~/.httpie/sessions/httpbin.org
|
||||||
|
|
||||||
|
|
||||||
Anonymous sessions
|
Anonymous sessions
|
||||||
------------------
|
------------------
|
||||||
@ -1503,19 +1643,43 @@ allows for sessions to be re-used across multiple hosts:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# Create a session:
|
||||||
$ http --session=/tmp/session.json example.org
|
$ http --session=/tmp/session.json example.org
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# Use the session to make a request to another host:
|
||||||
$ http --session=/tmp/session.json admin.example.org
|
$ http --session=/tmp/session.json admin.example.org
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# You can also refer to a previously created named session:
|
||||||
$ http --session=~/.httpie/sessions/another.example.org/test.json example.org
|
$ http --session=~/.httpie/sessions/another.example.org/test.json example.org
|
||||||
$ http --session-read-only=/tmp/session.json example.org
|
|
||||||
|
|
||||||
|
When creating anonymous sessions, please remember to always include at least
|
||||||
|
one ``/``, even if the session files is located in the current directory
|
||||||
|
(i.e., ``--session=./session.json`` instead of just ``--session=session.json``),
|
||||||
|
otherwise HTTPie assumes a named session instead.
|
||||||
|
|
||||||
|
|
||||||
Readonly session
|
Readonly session
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
To use an existing session file without updating it from the request/response
|
To use an existing session file without updating it from the request/response
|
||||||
exchange once it is created, specify the session name via
|
exchange after it has been created, specify the session name via
|
||||||
``--session-read-only=SESSION_NAME_OR_PATH`` instead.
|
``--session-read-only=SESSION_NAME_OR_PATH`` instead.
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# If the session file doesn’t exist, then it is created:
|
||||||
|
$ http --session-read-only=./ro-session.json httpbin.org/headers Custom-Header:orig-value
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# But it is not updated:
|
||||||
|
$ http --session-read-only=./ro-session.json httpbin.org/headers Custom-Header:new-value
|
||||||
|
|
||||||
Config
|
Config
|
||||||
======
|
======
|
||||||
@ -1536,7 +1700,7 @@ environment variable:
|
|||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ export HTTPIE_CONFIG_DIR=/tmp/httpie
|
$ export HTTPIE_CONFIG_DIR=/tmp/httpie
|
||||||
$ http example.org
|
$ http httpbin.org/get
|
||||||
|
|
||||||
To view the exact location run ``http --debug``.
|
To view the exact location run ``http --debug``.
|
||||||
|
|
||||||
@ -1598,7 +1762,7 @@ respectively.
|
|||||||
|
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
if http --check-status --ignore-stdin --timeout=2.5 HEAD example.org/health &> /dev/null; then
|
if http --check-status --ignore-stdin --timeout=2.5 HEAD httpbin.org/get &> /dev/null; then
|
||||||
echo 'OK!'
|
echo 'OK!'
|
||||||
else
|
else
|
||||||
case $? in
|
case $? in
|
||||||
@ -1624,7 +1788,7 @@ What happens is that when HTTPie is invoked for example from a cron job,
|
|||||||
``stdin`` is not connected to a terminal.
|
``stdin`` is not connected to a terminal.
|
||||||
Therefore, rules for `redirected input`_ apply, i.e., HTTPie starts to read it
|
Therefore, rules for `redirected input`_ apply, i.e., HTTPie starts to read it
|
||||||
expecting that the request body will be passed through.
|
expecting that the request body will be passed through.
|
||||||
And since there's no data nor ``EOF``, it will be stuck. So unless you're
|
And since there’s no data nor ``EOF``, it will be stuck. So unless you’re
|
||||||
piping some data to HTTPie, this flag should be used in scripts.
|
piping some data to HTTPie, this flag should be used in scripts.
|
||||||
|
|
||||||
Also, it might be good to set a connection ``--timeout`` limit to prevent
|
Also, it might be good to set a connection ``--timeout`` limit to prevent
|
||||||
@ -1639,14 +1803,15 @@ Interface design
|
|||||||
----------------
|
----------------
|
||||||
|
|
||||||
The syntax of the command arguments closely corresponds to the actual HTTP
|
The syntax of the command arguments closely corresponds to the actual HTTP
|
||||||
requests sent over the wire. It has the advantage that it's easy to remember
|
requests sent over the wire. It has the advantage that it’s easy to remember
|
||||||
and read. It is often possible to translate an HTTP request to an HTTPie
|
and read. It is often possible to translate an HTTP request to an HTTPie
|
||||||
argument list just by inlining the request elements. For example, compare this
|
argument list just by inlining the request elements. For example, compare this
|
||||||
HTTP request:
|
HTTP request:
|
||||||
|
|
||||||
.. code-block:: http
|
.. code-block:: http
|
||||||
|
|
||||||
POST /collection HTTP/1.1
|
POST /post HTTP/1.1
|
||||||
|
Host: httpbin.org
|
||||||
X-API-Key: 123
|
X-API-Key: 123
|
||||||
User-Agent: Bacon/1.0
|
User-Agent: Bacon/1.0
|
||||||
Content-Type: application/x-www-form-urlencoded
|
Content-Type: application/x-www-form-urlencoded
|
||||||
@ -1658,7 +1823,7 @@ with the HTTPie command that sends it:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ http -f POST example.org/collection \
|
$ http -f POST httpbin.org/post \
|
||||||
X-API-Key:123 \
|
X-API-Key:123 \
|
||||||
User-Agent:Bacon/1.0 \
|
User-Agent:Bacon/1.0 \
|
||||||
name=value \
|
name=value \
|
||||||
@ -1667,7 +1832,7 @@ with the HTTPie command that sends it:
|
|||||||
|
|
||||||
Notice that both the order of elements and the syntax is very similar,
|
Notice that both the order of elements and the syntax is very similar,
|
||||||
and that only a small portion of the command is used to control HTTPie and
|
and that only a small portion of the command is used to control HTTPie and
|
||||||
doesn't directly correspond to any part of the request (here it's only ``-f``
|
doesn’t directly correspond to any part of the request (here it’s only ``-f``
|
||||||
asking HTTPie to send a form request).
|
asking HTTPie to send a form request).
|
||||||
|
|
||||||
The two modes, ``--pretty=all`` (default for terminal) and ``--pretty=none``
|
The two modes, ``--pretty=all`` (default for terminal) and ``--pretty=none``
|
||||||
@ -1793,4 +1958,3 @@ have contributed.
|
|||||||
.. |downloads| image:: https://pepy.tech/badge/httpie
|
.. |downloads| image:: https://pepy.tech/badge/httpie
|
||||||
:target: https://pepy.tech/project/httpie
|
:target: https://pepy.tech/project/httpie
|
||||||
:alt: Download count
|
:alt: Download count
|
||||||
|
|
||||||
|
@ -9,22 +9,23 @@ class Httpie < Formula
|
|||||||
|
|
||||||
desc "User-friendly cURL replacement (command-line HTTP client)"
|
desc "User-friendly cURL replacement (command-line HTTP client)"
|
||||||
homepage "https://httpie.org/"
|
homepage "https://httpie.org/"
|
||||||
url "https://files.pythonhosted.org/packages/d5/a4/ab61c1dbfdef33c7b7f5f7df0d79eb5cd55a106601a4acc17f983f320b4a/httpie-1.0.3.tar.gz"
|
url "https://files.pythonhosted.org/packages/35/6c/93da2ebd4eb768c3733437ce01b5fae297522434fdeabeeabdc4f42aabd3/httpie-2.0.0.tar.gz"
|
||||||
sha256 "6d1b6e21da7d3ec030ae95536d4032c1129bdaf9de4adc72c596b87e5f646e80"
|
sha256 "8c04f9756f1a7eac71a6dfa0834d0f6813dc8a982d8564f3a7418dcd19107c09"
|
||||||
|
revision 1
|
||||||
head "https://github.com/jakubroztocil/httpie.git"
|
head "https://github.com/jakubroztocil/httpie.git"
|
||||||
|
|
||||||
bottle do
|
bottle do
|
||||||
cellar :any_skip_relocation
|
cellar :any_skip_relocation
|
||||||
sha256 "158258be68ac93de13860be2bef02da6fd8b68aa24b2e6609bcff1ec3f93e7a0" => :mojave
|
sha256 "19694b5ec311939a8b73cc329ca49386155ed3a17e4eca691779c725d36286b5" => :catalina
|
||||||
sha256 "54352116b6fa2c3bd65f26136fdcb57986dbff8a52de5febf7aea59c126d29e1" => :high_sierra
|
sha256 "8c7d93d55ea3351e25fadfdd3748ca0a3ff7dd62ab9dbf31b7243fba76890c4d" => :mojave
|
||||||
sha256 "9cce71768fe388808e11b26d651b44a6b54219f5406845b4273b5099f5c1f76f" => :sierra
|
sha256 "e0d5269bb5d03a1797c8612005fa46d6a35f2b84eb76e9607ef1169464b566ea" => :high_sierra
|
||||||
end
|
end
|
||||||
|
|
||||||
depends_on "python"
|
depends_on "python@3.8"
|
||||||
|
|
||||||
resource "Pygments" do
|
resource "Pygments" do
|
||||||
url "https://files.pythonhosted.org/packages/7e/ae/26808275fc76bf2832deb10d3a3ed3107bc4de01b85dcccbe525f2cd6d1e/Pygments-2.4.2.tar.gz"
|
url "https://files.pythonhosted.org/packages/cb/9f/27d4844ac5bf158a33900dbad7985951e2910397998e85712da03ce125f0/Pygments-2.5.2.tar.gz"
|
||||||
sha256 "881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297"
|
sha256 "98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe"
|
||||||
end
|
end
|
||||||
|
|
||||||
resource "requests" do
|
resource "requests" do
|
||||||
@ -33,13 +34,13 @@ class Httpie < Formula
|
|||||||
end
|
end
|
||||||
|
|
||||||
resource "certifi" do
|
resource "certifi" do
|
||||||
url "https://files.pythonhosted.org/packages/c5/67/5d0548226bcc34468e23a0333978f0e23d28d0b3f0c71a151aef9c3f7680/certifi-2019.6.16.tar.gz"
|
url "https://files.pythonhosted.org/packages/41/bf/9d214a5af07debc6acf7f3f257265618f1db242a3f8e49a9b516f24523a6/certifi-2019.11.28.tar.gz"
|
||||||
sha256 "945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695"
|
sha256 "25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
|
||||||
end
|
end
|
||||||
|
|
||||||
resource "urllib3" do
|
resource "urllib3" do
|
||||||
url "https://files.pythonhosted.org/packages/4c/13/2386233f7ee40aa8444b47f7463338f3cbdf00c316627558784e3f542f07/urllib3-1.25.3.tar.gz"
|
url "https://files.pythonhosted.org/packages/ad/fc/54d62fa4fc6e675678f9519e677dfc29b8964278d75333cf142892caf015/urllib3-1.25.7.tar.gz"
|
||||||
sha256 "dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232"
|
sha256 "f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745"
|
||||||
end
|
end
|
||||||
|
|
||||||
resource "idna" do
|
resource "idna" do
|
||||||
@ -53,8 +54,8 @@ class Httpie < Formula
|
|||||||
end
|
end
|
||||||
|
|
||||||
resource "PySocks" do
|
resource "PySocks" do
|
||||||
url "https://files.pythonhosted.org/packages/15/ab/35824cfdee1aac662e3298275fa1e6cbedb52126d1785f8977959b769ccf/PySocks-1.7.0.tar.gz"
|
url "https://files.pythonhosted.org/packages/bd/11/293dd436aea955d45fc4e8a35b6ae7270f5b8e00b53cf6c024c83b657a11/PySocks-1.7.1.tar.gz"
|
||||||
sha256 "d9031ea45fdfacbe59a99273e9f0448ddb33c1580fe3831c1b09557c5718977c"
|
sha256 "3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"
|
||||||
end
|
end
|
||||||
|
|
||||||
def install
|
def install
|
||||||
|
@ -3,6 +3,6 @@ HTTPie - a CLI, cURL-like tool for humans.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version__ = '2.0.0'
|
__version__ = '2.1.0'
|
||||||
__author__ = 'Jakub Roztocil'
|
__author__ = 'Jakub Roztocil'
|
||||||
__licence__ = 'BSD'
|
__licence__ = 'BSD'
|
||||||
|
@ -78,7 +78,7 @@ class HTTPieArgumentParser(argparse.ArgumentParser):
|
|||||||
|
|
||||||
# Arguments processing and environment setup.
|
# Arguments processing and environment setup.
|
||||||
self._apply_no_options(no_options)
|
self._apply_no_options(no_options)
|
||||||
self._validate_download_options()
|
self._process_download_options()
|
||||||
self._setup_standard_streams()
|
self._setup_standard_streams()
|
||||||
self._process_output_options()
|
self._process_output_options()
|
||||||
self._process_pretty_options()
|
self._process_pretty_options()
|
||||||
@ -243,10 +243,11 @@ class HTTPieArgumentParser(argparse.ArgumentParser):
|
|||||||
Bytes are always read.
|
Bytes are always read.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if self.args.data:
|
if self.args.data or self.args.files:
|
||||||
self.error('Request body (from stdin or a file) and request '
|
self.error('Request body (from stdin or a file) and request '
|
||||||
'data (key=value) cannot be mixed. Pass '
|
'data (key=value) cannot be mixed. Pass '
|
||||||
'--ignore-stdin to let key/value take priority.')
|
'--ignore-stdin to let key/value take priority. '
|
||||||
|
'See https://httpie.org/doc#scripting for details.')
|
||||||
self.args.data = getattr(fd, 'buffer', fd).read()
|
self.args.data = getattr(fd, 'buffer', fd).read()
|
||||||
|
|
||||||
def _guess_method(self):
|
def _guess_method(self):
|
||||||
@ -378,7 +379,11 @@ class HTTPieArgumentParser(argparse.ArgumentParser):
|
|||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
self.args.prettify = PRETTY_MAP[self.args.prettify]
|
self.args.prettify = PRETTY_MAP[self.args.prettify]
|
||||||
|
|
||||||
def _validate_download_options(self):
|
def _process_download_options(self):
|
||||||
|
if self.args.offline:
|
||||||
|
self.args.download = False
|
||||||
|
self.args.download_resume = False
|
||||||
|
return
|
||||||
if not self.args.download:
|
if not self.args.download:
|
||||||
if self.args.download_resume:
|
if self.args.download_resume:
|
||||||
self.error('--continue only works with --download')
|
self.error('--continue only works with --download')
|
||||||
|
@ -552,6 +552,15 @@ network.add_argument(
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
network.add_argument(
|
||||||
|
'--path-as-is',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help="""
|
||||||
|
Bypass dot segment (/../ or /./) URL squashing.
|
||||||
|
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# SSL
|
# SSL
|
||||||
|
@ -6,6 +6,7 @@ import zlib
|
|||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Iterable, Union
|
from typing import Iterable, Union
|
||||||
|
from urllib.parse import urlparse, urlunparse
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from requests.adapters import HTTPAdapter
|
from requests.adapters import HTTPAdapter
|
||||||
@ -29,7 +30,7 @@ except (ImportError, AttributeError):
|
|||||||
|
|
||||||
FORM_CONTENT_TYPE = 'application/x-www-form-urlencoded; charset=utf-8'
|
FORM_CONTENT_TYPE = 'application/x-www-form-urlencoded; charset=utf-8'
|
||||||
JSON_CONTENT_TYPE = 'application/json'
|
JSON_CONTENT_TYPE = 'application/json'
|
||||||
JSON_ACCEPT = f'{JSON_CONTENT_TYPE}, */*'
|
JSON_ACCEPT = f'{JSON_CONTENT_TYPE}, */*;q=0.5'
|
||||||
DEFAULT_UA = f'HTTPie/{__version__}'
|
DEFAULT_UA = f'HTTPie/{__version__}'
|
||||||
|
|
||||||
|
|
||||||
@ -77,6 +78,11 @@ def collect_messages(
|
|||||||
|
|
||||||
request = requests.Request(**request_kwargs)
|
request = requests.Request(**request_kwargs)
|
||||||
prepared_request = requests_session.prepare_request(request)
|
prepared_request = requests_session.prepare_request(request)
|
||||||
|
if args.path_as_is:
|
||||||
|
prepared_request.url = ensure_path_as_is(
|
||||||
|
orig_url=args.url,
|
||||||
|
prepped_url=prepared_request.url,
|
||||||
|
)
|
||||||
if args.compress and prepared_request.body:
|
if args.compress and prepared_request.body:
|
||||||
compress_body(prepared_request, always=args.compress > 1)
|
compress_body(prepared_request, always=args.compress > 1)
|
||||||
response_count = 0
|
response_count = 0
|
||||||
@ -278,3 +284,30 @@ def make_request_kwargs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_path_as_is(orig_url: str, prepped_url: str) -> str:
|
||||||
|
"""
|
||||||
|
Handle `--path-as-is` by replacing the path component of the prepared
|
||||||
|
URL with the path component from the original URL. Other parts stay
|
||||||
|
untouched because other (welcome) processing on the URL might have
|
||||||
|
taken place.
|
||||||
|
|
||||||
|
<https://github.com/jakubroztocil/httpie/issues/895>
|
||||||
|
|
||||||
|
|
||||||
|
<https://ec.haxx.se/http/http-basics#path-as-is>
|
||||||
|
<https://curl.haxx.se/libcurl/c/CURLOPT_PATH_AS_IS.html>
|
||||||
|
|
||||||
|
>>> ensure_path_as_is('http://foo/../', 'http://foo/?foo=bar')
|
||||||
|
'http://foo/../?foo=bar'
|
||||||
|
|
||||||
|
"""
|
||||||
|
parsed_orig, parsed_prepped = urlparse(orig_url), urlparse(prepped_url)
|
||||||
|
final_dict = {
|
||||||
|
# noinspection PyProtectedMember
|
||||||
|
**parsed_prepped._asdict(),
|
||||||
|
'path': parsed_orig.path,
|
||||||
|
}
|
||||||
|
final_url = urlunparse(tuple(final_dict.values()))
|
||||||
|
return final_url
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Union, IO, Optional
|
from typing import IO, Optional
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -90,7 +90,7 @@ def main(
|
|||||||
exit_status = ExitStatus.ERROR_TOO_MANY_REDIRECTS
|
exit_status = ExitStatus.ERROR_TOO_MANY_REDIRECTS
|
||||||
env.log_error(
|
env.log_error(
|
||||||
f'Too many redirects'
|
f'Too many redirects'
|
||||||
f' (--max-redirects=parsed_args.max_redirects).'
|
f' (--max-redirects={parsed_args.max_redirects}).'
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# TODO: Further distinction between expected and unexpected errors.
|
# TODO: Further distinction between expected and unexpected errors.
|
||||||
|
@ -196,7 +196,6 @@ class Downloader:
|
|||||||
"""
|
"""
|
||||||
:param resume: Should the download resume if partial download
|
:param resume: Should the download resume if partial download
|
||||||
already exists.
|
already exists.
|
||||||
:type resume: bool
|
|
||||||
|
|
||||||
:param output_file: The file to store response body in. If not
|
:param output_file: The file to store response body in. If not
|
||||||
provided, it will be guessed from the response.
|
provided, it will be guessed from the response.
|
||||||
@ -322,7 +321,6 @@ class Downloader:
|
|||||||
|
|
||||||
:param chunk: A chunk of response body data that has just
|
:param chunk: A chunk of response body data that has just
|
||||||
been downloaded and written to the output.
|
been downloaded and written to the output.
|
||||||
:type chunk: bytes
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.status.chunk_downloaded(len(chunk))
|
self.status.chunk_downloaded(len(chunk))
|
||||||
|
37
setup.py
37
setup.py
@ -10,8 +10,11 @@ import httpie
|
|||||||
|
|
||||||
|
|
||||||
class PyTest(TestCommand):
|
class PyTest(TestCommand):
|
||||||
# `$ python setup.py test' simply installs minimal requirements
|
"""
|
||||||
# and runs the tests with no fancy stuff like parallel execution.
|
Running `$ python setup.py test' simply installs minimal requirements
|
||||||
|
and runs the tests with no fancy stuff like parallel execution.
|
||||||
|
|
||||||
|
"""
|
||||||
def finalize_options(self):
|
def finalize_options(self):
|
||||||
TestCommand.finalize_options(self)
|
TestCommand.finalize_options(self)
|
||||||
self.test_args = [
|
self.test_args = [
|
||||||
@ -26,8 +29,6 @@ class PyTest(TestCommand):
|
|||||||
|
|
||||||
|
|
||||||
tests_require = [
|
tests_require = [
|
||||||
# Pytest needs to come last.
|
|
||||||
# https://bitbucket.org/pypa/setuptools/issue/196/
|
|
||||||
'pytest-httpbin',
|
'pytest-httpbin',
|
||||||
'pytest',
|
'pytest',
|
||||||
'mock',
|
'mock',
|
||||||
@ -38,28 +39,24 @@ install_requires = [
|
|||||||
'requests>=2.22.0',
|
'requests>=2.22.0',
|
||||||
'Pygments>=2.5.2',
|
'Pygments>=2.5.2',
|
||||||
]
|
]
|
||||||
|
install_requires_win_only = [
|
||||||
|
'colorama>=0.2.4',
|
||||||
|
]
|
||||||
|
|
||||||
# Conditional dependencies:
|
# Conditional dependencies:
|
||||||
|
|
||||||
# sdist
|
# sdist
|
||||||
if 'bdist_wheel' not in sys.argv:
|
if 'bdist_wheel' not in sys.argv:
|
||||||
try:
|
|
||||||
# noinspection PyUnresolvedReferences
|
|
||||||
import argparse
|
|
||||||
except ImportError:
|
|
||||||
install_requires.append('argparse>=1.2.1')
|
|
||||||
|
|
||||||
if 'win32' in str(sys.platform).lower():
|
if 'win32' in str(sys.platform).lower():
|
||||||
# Terminal colors for Windows
|
# Terminal colors for Windows
|
||||||
install_requires.append('colorama>=0.2.4')
|
install_requires.extend(install_requires_win_only)
|
||||||
|
|
||||||
|
|
||||||
# bdist_wheel
|
# bdist_wheel
|
||||||
extras_require = {
|
extras_require = {
|
||||||
# https://wheel.readthedocs.io/en/latest/#defining-conditional-dependencies
|
# https://wheel.readthedocs.io/en/latest/#defining-conditional-dependencies
|
||||||
'python_version == "3.0" or python_version == "3.1"': ['argparse>=1.2.1'],
|
':sys_platform == "win32"': install_requires_win_only,
|
||||||
':sys_platform == "win32"': ['colorama>=0.2.4'],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -74,7 +71,7 @@ setup(
|
|||||||
description=httpie.__doc__.strip(),
|
description=httpie.__doc__.strip(),
|
||||||
long_description=long_description(),
|
long_description=long_description(),
|
||||||
url='https://httpie.org/',
|
url='https://httpie.org/',
|
||||||
download_url='https://github.com/jakubroztocil/httpie',
|
download_url=f'https://github.com/jakubroztocil/httpie/archive/{httpie.__version__}.tar.gz',
|
||||||
author=httpie.__author__,
|
author=httpie.__author__,
|
||||||
author_email='jakub@roztocil.co',
|
author_email='jakub@roztocil.co',
|
||||||
license=httpie.__licence__,
|
license=httpie.__licence__,
|
||||||
@ -85,6 +82,7 @@ setup(
|
|||||||
'https = httpie.__main__:main',
|
'https = httpie.__main__:main',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
python_requires='>=3.6',
|
||||||
extras_require=extras_require,
|
extras_require=extras_require,
|
||||||
install_requires=install_requires,
|
install_requires=install_requires,
|
||||||
tests_require=tests_require,
|
tests_require=tests_require,
|
||||||
@ -92,9 +90,7 @@ setup(
|
|||||||
classifiers=[
|
classifiers=[
|
||||||
'Development Status :: 5 - Production/Stable',
|
'Development Status :: 5 - Production/Stable',
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
'Programming Language :: Python :: 3.5',
|
'Programming Language :: Python :: 3 :: Only',
|
||||||
'Programming Language :: Python :: 3.6',
|
|
||||||
'Programming Language :: Python :: 3.7',
|
|
||||||
'Environment :: Console',
|
'Environment :: Console',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
'Intended Audience :: System Administrators',
|
'Intended Audience :: System Administrators',
|
||||||
@ -106,4 +102,11 @@ setup(
|
|||||||
'Topic :: Text Processing',
|
'Topic :: Text Processing',
|
||||||
'Topic :: Utilities'
|
'Topic :: Utilities'
|
||||||
],
|
],
|
||||||
|
project_urls={
|
||||||
|
'Documentation': 'https://httpie.org/docs',
|
||||||
|
'Source': 'https://github.com/jakubroztocil/httpie',
|
||||||
|
'Online Demo': 'https://httpie.org/run',
|
||||||
|
'Donate': 'https://httpie.org/donate',
|
||||||
|
'Twitter': 'https://twitter.com/clihttp',
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
@ -22,6 +22,7 @@ def test_default_headers_case_insensitive(httpbin):
|
|||||||
assert 'Content-Type' not in r
|
assert 'Content-Type' not in r
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyPep8Naming
|
||||||
class TestImplicitHTTPMethod:
|
class TestImplicitHTTPMethod:
|
||||||
def test_implicit_GET(self, httpbin):
|
def test_implicit_GET(self, httpbin):
|
||||||
r = http(httpbin.url + '/get')
|
r = http(httpbin.url + '/get')
|
||||||
@ -51,9 +52,9 @@ class TestImplicitHTTPMethod:
|
|||||||
|
|
||||||
class TestAutoContentTypeAndAcceptHeaders:
|
class TestAutoContentTypeAndAcceptHeaders:
|
||||||
"""
|
"""
|
||||||
Test that Accept and Content-Type correctly defaults to JSON,
|
Test that `Accept` and `Content-Type` correctly default to JSON,
|
||||||
but can still be overridden. The same with Content-Type when --form
|
but can still be overridden. The same with Content-Type when `--form`
|
||||||
-f is used.
|
`-f` is used.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -84,7 +85,7 @@ class TestAutoContentTypeAndAcceptHeaders:
|
|||||||
assert r.json['headers']['Accept'] == JSON_ACCEPT
|
assert r.json['headers']['Accept'] == JSON_ACCEPT
|
||||||
assert r.json['headers']['Content-Type'] == 'application/json'
|
assert r.json['headers']['Content-Type'] == 'application/json'
|
||||||
|
|
||||||
def test_POST_explicit_JSON_auto_JSON_accept(self, httpbin):
|
def test_POST_explicit_JSON_JSON_ACCEPT(self, httpbin):
|
||||||
r = http('--json', 'POST', httpbin.url + '/post')
|
r = http('--json', 'POST', httpbin.url + '/post')
|
||||||
assert HTTP_OK in r
|
assert HTTP_OK in r
|
||||||
assert r.json['headers']['Accept'] == JSON_ACCEPT
|
assert r.json['headers']['Accept'] == JSON_ACCEPT
|
||||||
|
@ -55,6 +55,25 @@ def test_GET(httpbin_both):
|
|||||||
assert HTTP_OK in r
|
assert HTTP_OK in r
|
||||||
|
|
||||||
|
|
||||||
|
def test_path_dot_normalization():
|
||||||
|
r = http(
|
||||||
|
'--offline',
|
||||||
|
'example.org/../../etc/password',
|
||||||
|
'param==value'
|
||||||
|
)
|
||||||
|
assert 'GET /etc/password?param=value' in r
|
||||||
|
|
||||||
|
|
||||||
|
def test_path_as_is():
|
||||||
|
r = http(
|
||||||
|
'--offline',
|
||||||
|
'--path-as-is',
|
||||||
|
'example.org/../../etc/password',
|
||||||
|
'param==value'
|
||||||
|
)
|
||||||
|
assert 'GET /../../etc/password?param=value' in r
|
||||||
|
|
||||||
|
|
||||||
def test_DELETE(httpbin_both):
|
def test_DELETE(httpbin_both):
|
||||||
r = http('DELETE', httpbin_both + '/delete')
|
r = http('DELETE', httpbin_both + '/delete')
|
||||||
assert HTTP_OK in r
|
assert HTTP_OK in r
|
||||||
@ -98,6 +117,27 @@ def test_POST_file(httpbin_both):
|
|||||||
assert FILE_CONTENT in r
|
assert FILE_CONTENT in r
|
||||||
|
|
||||||
|
|
||||||
|
def test_form_POST_file_redirected_stdin(httpbin):
|
||||||
|
"""
|
||||||
|
<https://github.com/jakubroztocil/httpie/issues/840>
|
||||||
|
|
||||||
|
"""
|
||||||
|
with open(FILE_PATH) as f:
|
||||||
|
r = http(
|
||||||
|
'--form',
|
||||||
|
'POST',
|
||||||
|
httpbin + '/post',
|
||||||
|
'file@' + FILE_PATH,
|
||||||
|
tolerate_error_exit_status=True,
|
||||||
|
env=MockEnvironment(
|
||||||
|
stdin=f,
|
||||||
|
stdin_isatty=False,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
assert r.exit_status == ExitStatus.ERROR
|
||||||
|
assert 'cannot be mixed' in r.stderr
|
||||||
|
|
||||||
|
|
||||||
def test_headers(httpbin_both):
|
def test_headers(httpbin_both):
|
||||||
r = http('GET', httpbin_both + '/headers', 'Foo:bar')
|
r = http('GET', httpbin_both + '/headers', 'Foo:bar')
|
||||||
assert HTTP_OK in r
|
assert HTTP_OK in r
|
||||||
@ -141,3 +181,21 @@ def test_json_input_preserve_order(httpbin_both):
|
|||||||
assert HTTP_OK in r
|
assert HTTP_OK in r
|
||||||
assert r.json['data'] == \
|
assert r.json['data'] == \
|
||||||
'{"order": {"map": {"1": "first", "2": "second"}}}'
|
'{"order": {"map": {"1": "first", "2": "second"}}}'
|
||||||
|
|
||||||
|
|
||||||
|
def test_offline():
|
||||||
|
r = http(
|
||||||
|
'--offline',
|
||||||
|
'https://this-should.never-resolve/foo',
|
||||||
|
)
|
||||||
|
assert 'GET /foo' in r
|
||||||
|
|
||||||
|
|
||||||
|
def test_offline_download():
|
||||||
|
"""Absence of response should be handled gracefully with --download"""
|
||||||
|
r = http(
|
||||||
|
'--offline',
|
||||||
|
'--download',
|
||||||
|
'https://this-should.never-resolve/foo',
|
||||||
|
)
|
||||||
|
assert 'GET /foo' in r
|
||||||
|
@ -3,6 +3,7 @@ import os
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from httpie.cli.exceptions import ParseError
|
from httpie.cli.exceptions import ParseError
|
||||||
|
from httpie.status import ExitStatus
|
||||||
from utils import MockEnvironment, http, HTTP_OK
|
from utils import MockEnvironment, http, HTTP_OK
|
||||||
from fixtures import FILE_PATH_ARG, FILE_PATH, FILE_CONTENT
|
from fixtures import FILE_PATH_ARG, FILE_PATH, FILE_CONTENT
|
||||||
|
|
||||||
@ -77,4 +78,5 @@ class TestRequestBodyFromFilePath:
|
|||||||
env=env,
|
env=env,
|
||||||
tolerate_error_exit_status=True,
|
tolerate_error_exit_status=True,
|
||||||
)
|
)
|
||||||
|
assert r.exit_status == ExitStatus.ERROR
|
||||||
assert 'cannot be mixed' in r.stderr
|
assert 'cannot be mixed' in r.stderr
|
||||||
|
Reference in New Issue
Block a user