Compare commits

...

24 Commits
2.0.0 ... 2.1.0

Author SHA1 Message Date
70a78249c1 2.1.0
#488 #840 #895
2020-04-18 12:54:40 +02:00
fc85988368 Change default JSON Accept to application/json, */*;q=0.5
See #488
2020-04-18 12:03:38 +02:00
83bd8059de accept wip 2020-04-18 12:03:37 +02:00
3af5f1f305 Add an --offline example 2020-04-16 11:47:56 +02:00
4351650691 Ignore --download with --offline 2020-04-16 11:41:12 +02:00
770976a66e Add --path-as-is docs 2020-04-16 11:29:58 +02:00
29b692d597 Add --offline mode docs 2020-04-16 11:29:33 +02:00
8936d1b71e Add tests for --offline 2020-04-16 11:28:21 +02:00
4f32b76223 Readme WIP 2020-04-15 18:07:43 +02:00
c9d770017e Fix 'Too many redirects' error message formatting 2020-04-15 17:43:08 +02:00
cdf691c212 Change default JSON Accept to application/json, */*;q=0.5
Close #488
2020-04-13 22:12:06 +02:00
684a4708d7 Add --path-as-is
Close #895
2020-04-13 20:18:56 +02:00
Mio
5754e33a75 Removed duplicate type annotation. (#888) 2020-04-13 18:15:48 +02:00
14fe7dbb27 apt (#890)
Co-authored-by: Doug Beney <contact@dougie.io>
2020-04-13 18:15:16 +02:00
3a6ac7d126 Remove unused imports 2020-04-13 17:37:27 +02:00
e9080e6b22 Build on PRs as well 2020-04-13 17:24:18 +02:00
c73858b9c3 Update examples 2020-03-27 10:03:30 +01:00
7340b2b64d Update --download doc 2020-03-27 10:03:30 +01:00
8d246415fd 2020 2020-03-22 12:29:01 +01:00
381dd4f619 Actually fixed --form file upload w/ redirected stdin error handling
#840
2020-01-23 15:56:29 +01:00
e6bad645ed Fixed --form file upload mixed with redirected stdin error handling.
Close #840
2020-01-23 15:55:00 +01:00
6e9cd139a6 Clean up Python-version related PyPI classifiers (#841)
- Removes 'Programming Language :: Python :: 3.5' per the
  README, which specifies 'Python version 3.6 or greater is required.'
- Adds 'Programming Language :: Python :: 3 :: Only' in place
2020-01-23 15:05:07 +01:00
deee2dffd0 Update CHANGELOG.rst 2020-01-13 14:50:58 +01:00
c3be722188 Update brew formula 2020-01-12 11:44:58 +01:00
17 changed files with 445 additions and 156 deletions

View File

@ -1,5 +1,5 @@
name: Build
on: [push]
on: [push, pull_request]
jobs:
extras:
# Run coverage and extra tests only once

View File

@ -6,6 +6,18 @@ This document records all notable changes to `HTTPie <https://httpie.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)
-------------------------
* 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
with one-by-one processing of each HTTP request or response as they become
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 the default 30-second connection ``--timeout`` limit.
* Removed Pythons 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.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.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

View File

@ -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
modification, are permitted provided that the following conditions are met:

View File

@ -27,11 +27,20 @@ generally interacting with HTTP servers.
.. 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
=============
* Expressive and intuitive syntax
* Formatted and colorized terminal output
* Built-in JSON support
@ -86,7 +95,7 @@ system package manager, for example:
.. code-block:: bash
# Debian, Ubuntu, etc.
$ apt-get install httpie
$ apt install httpie
.. code-block:: bash
@ -157,13 +166,13 @@ Otherwise with ``pip``:
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:
.. code-block:: bash
$ http --version
1.0.0-dev
# 2.0.0-dev
Usage
@ -175,7 +184,7 @@ Hello World:
.. code-block:: bash
$ http httpie.org
$ http https://httpie.org/hello
Synopsis:
@ -195,21 +204,28 @@ Custom `HTTP method`_, `HTTP headers`_ and `JSON`_ data:
.. 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`_:
.. 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`_:
.. 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
@ -225,29 +241,33 @@ Upload a file using `redirected input`_:
.. code-block:: bash
$ http example.org < file.json
$ http httpbin.org/post < files/data.json
Download a file and save it via `redirected output`_:
.. code-block:: bash
$ http example.org/file > file
$ http httpbin.org/image/png > image.png
Download a file ``wget`` style:
.. 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:
.. code-block:: bash
$ http --session=logged-in -a username:password httpbin.org/get API-Key:123
.. code-block:: bash
$ 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
$ http DELETE example.org/todos/7
$ http DELETE httpbin.org/delete
Which looks similar to the actual ``Request-Line`` that is sent:
.. 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
@ -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
URL parameters.
With that, you don't have to worry about escaping the ``&``
With that, you dont have to worry about escaping the ``&``
separators for your shell. Additionally, any special characters in the
parameter name or value get automatically URL-escaped
(as opposed to parameters specified in the full URL, which HTTPie doesnt
@ -380,6 +400,34 @@ Example for the `httpie-unixsocket <https://github.com/httpie/httpie-unixsocket>
# Now the scheme can be omitted
$ 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
=============
@ -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 arent the only way to specify request data:
`Redirected input`_ is a mechanism for passing arbitrary request data.
Escaping rules
--------------
You can use ``\`` to escape characters that shouldn't be used as separators
You can use ``\`` to escape characters that shouldnt be used as separators
(or parts thereof). For instance, ``foo\==bar`` will become a data key/value
pair (``foo=`` and ``bar``) instead of a URL parameter.
@ -464,15 +512,15 @@ Simple example:
.. 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
PUT / HTTP/1.1
Accept: application/json, */*
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Host: example.org
Host: httpbin.org
{
"name": "John",
@ -490,7 +538,7 @@ both of which can be overwritten:
================ =======================================
``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``
to ``application/json`` regardless of whether you are sending data
(it's a shortcut for setting the header via the usual header notation:
``http url Accept:'application/json, */*'``). Additionally,
(its a shortcut for setting the header via the usual header notation:
``http url Accept:'application/json, */*;q=0.5'``). Additionally,
HTTPie will try to detect JSON responses even when the
``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 fields use the ``:=`` separator, which allows you to embed raw JSON
into the resulting object. Text and raw JSON files can also be embedded into
Non-string JSON fields use the ``:=`` separator, which allows you to embed arbitrary JSON data
into the resulting JSON object. Additionally, text and raw JSON files can also be embedded into
fields using ``=@`` and ``:=@``:
.. code-block:: bash
$ http PUT api.example.com/person/1 \
name=John \
age:=29 married:=false hobbies:='["http", "pies"]' \ # Raw JSON
description=@about-john.txt \ # Embed text file
bookmarks:=@bookmarks.json # Embed JSON file
$ http PUT httpbin.org/put \
name=John \ # String (default)
age:=29 \ # Raw JSON — Number
married:=false \ # Raw JSON — Boolean
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
PUT /person/1 HTTP/1.1
Accept: application/json, */*
Accept: application/json, */*;q=0.5
Content-Type: application/json
Host: api.example.com
Host: httpbin.org
{
"age": 29,
@ -538,19 +589,33 @@ fields using ``=@`` and ``:=@``:
"description": "John is a nice guy who likes pies.",
"married": false,
"name": "John",
"favorite": {
"tool": "HTTPie"
},
"bookmarks": {
"HTTPie": "https://httpie.org",
}
}
Please note that with this syntax the command gets unwieldy when sending
complex data. In that case it's always better to use `redirected input`_:
Raw and complex JSON
--------------------
Please note that with the `request items`_ data field syntax, commands
can quickly become unwieldy when sending complex structures.
In such cases, its better to pass the full raw JSON data via
`redirected input`_, for example:
.. 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
=====
@ -568,12 +633,12 @@ Regular forms
.. 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
POST /person/1 HTTP/1.1
POST /post HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=utf-8
name=John+Smith
@ -587,7 +652,7 @@ If one or more file fields is present, the serialization and content type is
.. 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
@ -611,17 +676,17 @@ To set custom headers you can use the ``Header:Value`` notation:
.. 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/
.. code-block:: http
GET / HTTP/1.1
GET /headers HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Cookie: valued-visitor=yes;foo=bar
Host: example.org
Host: httpbin.org
Referer: https://httpie.org/
User-Agent: Bacon/1.0
X-Foo: Bar
@ -679,6 +744,50 @@ HTTPie reads before giving up (the default ``0``, i.e., theres 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
=======
@ -691,7 +800,7 @@ Send a single cookie:
.. code-block:: bash
$ http example.org Cookie:sessionid=foo
$ http httpbin.org/cookies Cookie:sessionid=foo
.. code-block:: http
@ -700,7 +809,7 @@ Send a single cookie:
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: sessionid=foo
Host: example.org
Host: httpbin.org
User-Agent: HTTPie/0.9.9
@ -709,7 +818,7 @@ Send multiple cookies
.. 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
@ -718,11 +827,11 @@ Send multiple cookies
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: sessionid=foo;another-cookie=bar
Host: example.org
Host: httpbin.org
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 youd appreciate
the `sessions`_ feature.
@ -735,7 +844,7 @@ The currently supported authentication schemes are Basic and Digest
=================== ======================================================
``--auth, -a`` Pass a ``username:password`` pair as
the argument. Or, if you only specify a username
(``-a username``), you'll be prompted for
(``-a username``), youll be prompted for
the password before the request is sent.
To send an empty password, pass ``username:``.
The ``username:password@hostname`` URL syntax is
@ -755,7 +864,7 @@ Basic auth
.. code-block:: bash
$ http -a username:password example.org
$ http -a username:password httpbin.org/basic-auth/username/password
Digest auth
@ -764,7 +873,7 @@ Digest auth
.. 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
@ -772,7 +881,15 @@ Password prompt
.. 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``
@ -810,7 +927,7 @@ Auth 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>`_.
Here's a few picks:
Heres a few picks:
* `httpie-api-auth <https://github.com/pd/httpie-api-auth>`_: ApiAuth
* `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
$ http --follow --all --max-redirects=5 httpbin.org/redirect/3
$ http --follow --all --max-redirects=2 httpbin.org/redirect/3
Proxies
@ -913,7 +1030,7 @@ SOCKS
-----
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, youll
might need to install ``requests[socks]`` manually using ``pip``:
@ -935,12 +1052,12 @@ HTTPS
Server SSL certificate verification
-----------------------------------
To skip the host's SSL certificate verification, you can pass ``--verify=no``
To skip the hosts SSL certificate verification, you can pass ``--verify=no``
(default is ``yes``):
.. code-block:: bash
$ http --verify=no https://example.org
$ http --verify=no https://httpbin.org/get
Custom CA bundle
@ -1009,7 +1126,7 @@ documentation examples:
$ http --verbose PUT httpbin.org/put hello=world
PUT /put HTTP/1.1
Accept: application/json, */*
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Host: httpbin.org
@ -1071,7 +1188,7 @@ authentication is used (``--auth=digest``), etc.
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 youd like to change
that, use the ``--history-print, -P`` option. It takes the same
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
only if it's part of the output. This is similar to performing a ``HEAD``
only if its part of the output. This is similar to performing a ``HEAD``
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
Lets 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
status code after an update:
.. 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
is closed as soon as all the response headers have been received.
Therefore, bandwidth and time isn't wasted downloading the body
which you don't care about. The response headers are downloaded always,
Therefore, bandwidth and time isnt wasted downloading the body
which you dont care about. The response headers are downloaded always,
even if they are not part of the output
@ -1117,28 +1234,28 @@ Redirect from a file:
.. 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:
.. 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:
.. 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*:
.. code-block:: bash
$ http example.com/ <<<'{"name": "John"}'
$ http httpbin.org/post <<<'{"name": "John"}'
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
$ cat | http POST example.com
$ cat | http POST httpbin.org/post
<paste>
^D
.. 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
- call parents
^D
@ -1169,7 +1286,7 @@ On OS X, you can send the contents of the clipboard with ``pbpaste``:
.. 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
@ -1198,7 +1315,7 @@ verbatim contents of that XML file with ``Content-Type: application/xml``:
.. code-block:: bash
$ http PUT httpbin.org/put @/data/file.xml
$ http PUT httpbin.org/put @files/data.xml
Terminal output
@ -1213,8 +1330,16 @@ Colors and formatting
Syntax highlighting is applied to HTTP headers and bodies (where it makes
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
values).
if you dont like the default one. There dozens of styles available, here are just a few special or notable ones:
==================== ========================================================================
``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:
@ -1243,7 +1368,7 @@ that the response body is binary,
.. code-block:: bash
$ http example.org/Movie.mov
$ http httpbin.org/bytes/2000
You will nearly instantly see something like this:
@ -1251,10 +1376,7 @@ You will nearly instantly see something like this:
.. code-block:: http
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Encoding: gzip
Content-Type: video/quicktime
Transfer-Encoding: chunked
Content-Type: application/octet-stream
+-----------------------------------------+
| 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
`terminal output`_. The differences being:
* Formatting and colors aren't applied (unless ``--pretty`` is specified).
* Formatting and colors arent applied (unless ``--pretty`` is specified).
* Only the response body is printed (unless one of the `output options`_ is set).
* Also, binary data isn't suppressed.
* Also, binary data isnt suppressed.
The reason is to make piping HTTPie's output to another programs and
The reason is to make piping HTTPies output to another programs and
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.
@ -1279,7 +1401,7 @@ Download a file:
.. 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:
@ -1294,7 +1416,7 @@ Force colorizing and formatting, and show both the request and the response in
.. 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
@ -1373,7 +1495,7 @@ Resuming downloads
If ``--output, -o`` is specified, you can resume a partial download using the
``--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 doesnt
support that, the whole file will simply be downloaded:
.. code-block:: bash
@ -1386,7 +1508,9 @@ Other notes
* The ``--download`` option only changes how the response body is treated.
* You can still set custom headers, use sessions, ``--verbose, -v``, etc.
* ``--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 hasnt been fully
downloaded.
* ``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'
Streamed output by small chunks alá ``tail -f``:
Streamed output by small chunks à la ``tail -f``:
.. code-block:: bash
@ -1450,11 +1574,19 @@ to the same host.
.. code-block:: bash
# Create a new session
$ http --session=/tmp/session.json example.org API-Token:123
# Create a new session:
$ 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,
@ -1469,31 +1601,39 @@ Named sessions
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
$ 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
use the session again, any previously specified authentication or HTTP headers
From now on, you can refer to the session by its name (``user1``). When you choose
to use the session again, any previously specified authentication or HTTP headers
will automatically be set:
.. 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:
.. 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 sessionss data is stored in JSON files in the the ``sessions``
subdirectory of the `config`_ directory:
``~/.httpie/sessions/<host>/<name>.json``
(``%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
------------------
@ -1503,19 +1643,43 @@ allows for sessions to be re-used across multiple hosts:
.. code-block:: bash
# Create a session:
$ 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
.. 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-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
----------------
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.
.. code-block:: bash
# If the session file doesnt 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
======
@ -1536,7 +1700,7 @@ environment variable:
.. code-block:: bash
$ export HTTPIE_CONFIG_DIR=/tmp/httpie
$ http example.org
$ http httpbin.org/get
To view the exact location run ``http --debug``.
@ -1598,7 +1762,7 @@ respectively.
#!/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!'
else
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.
Therefore, rules for `redirected input`_ apply, i.e., HTTPie starts to read it
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 theres no data nor ``EOF``, it will be stuck. So unless youre
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
@ -1639,14 +1803,15 @@ Interface design
----------------
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 its easy to remember
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
HTTP request:
.. code-block:: http
POST /collection HTTP/1.1
POST /post HTTP/1.1
Host: httpbin.org
X-API-Key: 123
User-Agent: Bacon/1.0
Content-Type: application/x-www-form-urlencoded
@ -1658,7 +1823,7 @@ with the HTTPie command that sends it:
.. code-block:: bash
$ http -f POST example.org/collection \
$ http -f POST httpbin.org/post \
X-API-Key:123 \
User-Agent:Bacon/1.0 \
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,
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``
doesnt directly correspond to any part of the request (here its only ``-f``
asking HTTPie to send a form request).
The two modes, ``--pretty=all`` (default for terminal) and ``--pretty=none``
@ -1793,4 +1958,3 @@ have contributed.
.. |downloads| image:: https://pepy.tech/badge/httpie
:target: https://pepy.tech/project/httpie
:alt: Download count

View File

@ -9,22 +9,23 @@ class Httpie < Formula
desc "User-friendly cURL replacement (command-line HTTP client)"
homepage "https://httpie.org/"
url "https://files.pythonhosted.org/packages/d5/a4/ab61c1dbfdef33c7b7f5f7df0d79eb5cd55a106601a4acc17f983f320b4a/httpie-1.0.3.tar.gz"
sha256 "6d1b6e21da7d3ec030ae95536d4032c1129bdaf9de4adc72c596b87e5f646e80"
url "https://files.pythonhosted.org/packages/35/6c/93da2ebd4eb768c3733437ce01b5fae297522434fdeabeeabdc4f42aabd3/httpie-2.0.0.tar.gz"
sha256 "8c04f9756f1a7eac71a6dfa0834d0f6813dc8a982d8564f3a7418dcd19107c09"
revision 1
head "https://github.com/jakubroztocil/httpie.git"
bottle do
cellar :any_skip_relocation
sha256 "158258be68ac93de13860be2bef02da6fd8b68aa24b2e6609bcff1ec3f93e7a0" => :mojave
sha256 "54352116b6fa2c3bd65f26136fdcb57986dbff8a52de5febf7aea59c126d29e1" => :high_sierra
sha256 "9cce71768fe388808e11b26d651b44a6b54219f5406845b4273b5099f5c1f76f" => :sierra
sha256 "19694b5ec311939a8b73cc329ca49386155ed3a17e4eca691779c725d36286b5" => :catalina
sha256 "8c7d93d55ea3351e25fadfdd3748ca0a3ff7dd62ab9dbf31b7243fba76890c4d" => :mojave
sha256 "e0d5269bb5d03a1797c8612005fa46d6a35f2b84eb76e9607ef1169464b566ea" => :high_sierra
end
depends_on "python"
depends_on "python@3.8"
resource "Pygments" do
url "https://files.pythonhosted.org/packages/7e/ae/26808275fc76bf2832deb10d3a3ed3107bc4de01b85dcccbe525f2cd6d1e/Pygments-2.4.2.tar.gz"
sha256 "881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297"
url "https://files.pythonhosted.org/packages/cb/9f/27d4844ac5bf158a33900dbad7985951e2910397998e85712da03ce125f0/Pygments-2.5.2.tar.gz"
sha256 "98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe"
end
resource "requests" do
@ -33,13 +34,13 @@ class Httpie < Formula
end
resource "certifi" do
url "https://files.pythonhosted.org/packages/c5/67/5d0548226bcc34468e23a0333978f0e23d28d0b3f0c71a151aef9c3f7680/certifi-2019.6.16.tar.gz"
sha256 "945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695"
url "https://files.pythonhosted.org/packages/41/bf/9d214a5af07debc6acf7f3f257265618f1db242a3f8e49a9b516f24523a6/certifi-2019.11.28.tar.gz"
sha256 "25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
end
resource "urllib3" do
url "https://files.pythonhosted.org/packages/4c/13/2386233f7ee40aa8444b47f7463338f3cbdf00c316627558784e3f542f07/urllib3-1.25.3.tar.gz"
sha256 "dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232"
url "https://files.pythonhosted.org/packages/ad/fc/54d62fa4fc6e675678f9519e677dfc29b8964278d75333cf142892caf015/urllib3-1.25.7.tar.gz"
sha256 "f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745"
end
resource "idna" do
@ -53,8 +54,8 @@ class Httpie < Formula
end
resource "PySocks" do
url "https://files.pythonhosted.org/packages/15/ab/35824cfdee1aac662e3298275fa1e6cbedb52126d1785f8977959b769ccf/PySocks-1.7.0.tar.gz"
sha256 "d9031ea45fdfacbe59a99273e9f0448ddb33c1580fe3831c1b09557c5718977c"
url "https://files.pythonhosted.org/packages/bd/11/293dd436aea955d45fc4e8a35b6ae7270f5b8e00b53cf6c024c83b657a11/PySocks-1.7.1.tar.gz"
sha256 "3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"
end
def install

View File

@ -3,6 +3,6 @@ HTTPie - a CLI, cURL-like tool for humans.
"""
__version__ = '2.0.0'
__version__ = '2.1.0'
__author__ = 'Jakub Roztocil'
__licence__ = 'BSD'

View File

@ -78,7 +78,7 @@ class HTTPieArgumentParser(argparse.ArgumentParser):
# Arguments processing and environment setup.
self._apply_no_options(no_options)
self._validate_download_options()
self._process_download_options()
self._setup_standard_streams()
self._process_output_options()
self._process_pretty_options()
@ -243,10 +243,11 @@ class HTTPieArgumentParser(argparse.ArgumentParser):
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 '
'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()
def _guess_method(self):
@ -378,7 +379,11 @@ class HTTPieArgumentParser(argparse.ArgumentParser):
# noinspection PyTypeChecker
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 self.args.download_resume:
self.error('--continue only works with --download')

View File

@ -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

View File

@ -6,6 +6,7 @@ import zlib
from contextlib import contextmanager
from pathlib import Path
from typing import Iterable, Union
from urllib.parse import urlparse, urlunparse
import requests
from requests.adapters import HTTPAdapter
@ -29,7 +30,7 @@ except (ImportError, AttributeError):
FORM_CONTENT_TYPE = 'application/x-www-form-urlencoded; charset=utf-8'
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__}'
@ -77,6 +78,11 @@ def collect_messages(
request = requests.Request(**request_kwargs)
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:
compress_body(prepared_request, always=args.compress > 1)
response_count = 0
@ -278,3 +284,30 @@ def make_request_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

View File

@ -1,7 +1,6 @@
import os
import sys
from pathlib import Path
from typing import Union, IO, Optional
from typing import IO, Optional
try:

View File

@ -90,7 +90,7 @@ def main(
exit_status = ExitStatus.ERROR_TOO_MANY_REDIRECTS
env.log_error(
f'Too many redirects'
f' (--max-redirects=parsed_args.max_redirects).'
f' (--max-redirects={parsed_args.max_redirects}).'
)
except Exception as e:
# TODO: Further distinction between expected and unexpected errors.

View File

@ -196,7 +196,6 @@ class Downloader:
"""
:param resume: Should the download resume if partial download
already exists.
:type resume: bool
:param output_file: The file to store response body in. If not
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
been downloaded and written to the output.
:type chunk: bytes
"""
self.status.chunk_downloaded(len(chunk))

View File

@ -1,5 +1,4 @@
[wheel]
universal = 1
[tool:pytest]

View File

@ -10,8 +10,11 @@ import httpie
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):
TestCommand.finalize_options(self)
self.test_args = [
@ -26,8 +29,6 @@ class PyTest(TestCommand):
tests_require = [
# Pytest needs to come last.
# https://bitbucket.org/pypa/setuptools/issue/196/
'pytest-httpbin',
'pytest',
'mock',
@ -38,28 +39,24 @@ install_requires = [
'requests>=2.22.0',
'Pygments>=2.5.2',
]
install_requires_win_only = [
'colorama>=0.2.4',
]
# Conditional dependencies:
# sdist
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():
# Terminal colors for Windows
install_requires.append('colorama>=0.2.4')
install_requires.extend(install_requires_win_only)
# bdist_wheel
extras_require = {
# 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"': ['colorama>=0.2.4'],
':sys_platform == "win32"': install_requires_win_only,
}
@ -74,7 +71,7 @@ setup(
description=httpie.__doc__.strip(),
long_description=long_description(),
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_email='jakub@roztocil.co',
license=httpie.__licence__,
@ -85,6 +82,7 @@ setup(
'https = httpie.__main__:main',
],
},
python_requires='>=3.6',
extras_require=extras_require,
install_requires=install_requires,
tests_require=tests_require,
@ -92,9 +90,7 @@ setup(
classifiers=[
'Development Status :: 5 - Production/Stable',
'Programming Language :: Python',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3 :: Only',
'Environment :: Console',
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
@ -106,4 +102,11 @@ setup(
'Topic :: Text Processing',
'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',
},
)

View File

@ -22,6 +22,7 @@ def test_default_headers_case_insensitive(httpbin):
assert 'Content-Type' not in r
# noinspection PyPep8Naming
class TestImplicitHTTPMethod:
def test_implicit_GET(self, httpbin):
r = http(httpbin.url + '/get')
@ -51,9 +52,9 @@ class TestImplicitHTTPMethod:
class TestAutoContentTypeAndAcceptHeaders:
"""
Test that Accept and Content-Type correctly defaults to JSON,
but can still be overridden. The same with Content-Type when --form
-f is used.
Test that `Accept` and `Content-Type` correctly default to JSON,
but can still be overridden. The same with Content-Type when `--form`
`-f` is used.
"""
@ -84,7 +85,7 @@ class TestAutoContentTypeAndAcceptHeaders:
assert r.json['headers']['Accept'] == JSON_ACCEPT
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')
assert HTTP_OK in r
assert r.json['headers']['Accept'] == JSON_ACCEPT

View File

@ -55,6 +55,25 @@ def test_GET(httpbin_both):
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):
r = http('DELETE', httpbin_both + '/delete')
assert HTTP_OK in r
@ -98,6 +117,27 @@ def test_POST_file(httpbin_both):
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):
r = http('GET', httpbin_both + '/headers', 'Foo:bar')
assert HTTP_OK in r
@ -141,3 +181,21 @@ def test_json_input_preserve_order(httpbin_both):
assert HTTP_OK in r
assert r.json['data'] == \
'{"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

View File

@ -3,6 +3,7 @@ import os
import pytest
from httpie.cli.exceptions import ParseError
from httpie.status import ExitStatus
from utils import MockEnvironment, http, HTTP_OK
from fixtures import FILE_PATH_ARG, FILE_PATH, FILE_CONTENT
@ -77,4 +78,5 @@ class TestRequestBodyFromFilePath:
env=env,
tolerate_error_exit_status=True,
)
assert r.exit_status == ExitStatus.ERROR
assert 'cannot be mixed' in r.stderr