Compare commits

...

1367 Commits

Author SHA1 Message Date
279e387d86 WIP 2021-10-08 10:45:49 +02:00
50f57f8c82 Add help output for --chunked (#1174) 2021-10-07 17:37:06 +02:00
555afef486 Update README.md 2021-10-07 16:21:36 +02:00
476eb4f0d9 Use HTTPie repository everywhere 2021-10-07 16:15:52 +02:00
3869c3ce99 Remove unused import 2021-10-07 14:41:03 +02:00
17f74f10f3 Add summary to Chocolatey metadata
It is strongly recommended to add a summary.
It will be effective for the next release though.
2021-10-07 14:34:33 +02:00
1e094d0a79 Fix Snapcraft and Spack anchors 2021-10-07 14:06:06 +02:00
bd227c0364 Specify the API key to submit Chocolatey packages 2021-10-07 13:58:02 +02:00
9dda23a322 Add Chocolatey packaging information (#1172)
* Add Chocolatey packaging information

* Fix working directory

* Fix Python dependency

* Update icon URL

* Fix local installation

* Simplify links

* Remove the workflow, it adds no real value and th etime to fix is is not worth
2021-10-07 13:53:11 +02:00
ef4fa20ceb Tweak 2021-10-06 19:31:43 +02:00
7e0bed4e54 Add more types and docs for plugins API II. 2021-10-06 19:28:21 +02:00
e1627803fe Add more types and docs for plugins API 2021-10-06 19:24:10 +02:00
f954c9e2b7 Update CHANGELOG.md 2021-10-06 17:35:07 +02:00
80e83f0463 Ignore more venv folders and VS Code folder 2021-10-06 17:29:03 +02:00
4f1c9441c5 Fix encoding error with non-prettified encoded responses (#1168)
* Fix encoding error with non-prettified encoded responses

Removed `--format-option response.as` an promote `--response-as`: using
the format option would be misleading as it is now also used by non-prettified
responses.

* Encoding refactoring

* split --response-as into --response-mime and --response-charset
* add support for Content-Type charset for requests printed to terminal
* add support charset detection for requests printed to terminal without a Content-Type charset
* etc.

* `test_unicode.py` → `test_encoding.py`

* Drop sequence length check

* Clean-up tests

* [skip ci] Tweaks

* Use the compatible release clause for `charset_normalizer` requirement

Cf. https://www.python.org/dev/peps/pep-0440/#version-specifiers

* Clean-up

* Partially revert d52a4833e4

* Changelog

* Tweak tests

* [skip ci] Better test name

* Cleanup tests and add request body charset detection

* More test suite cleanups

* Cleanup

* Fix code style in test

* Improve detect_encoding() docstring

* Uniformize pytest.mark.parametrize() calls

* [skip ci] Comment out TODOs (will be tackled in a specific PR)

Co-authored-by: Jakub Roztocil <jakub@roztocil.co>
2021-10-06 17:27:07 +02:00
7989e438d2 Add documentation about our release process (#1159)
* Add documentation about our release process

* Fixes

* Add company-related tasks, enable back WIP pages

* Fix WIP links

* Add AOSC OS

* Add WIP for AOSC OS

* Tweak

* Remove maintainers email IDs

* Use GH nicknames

* Remove useless WIP for brew

* Tweaks
2021-10-06 16:45:44 +02:00
93114072c8 Fix looked path for workflow testing packages 2021-10-06 11:21:54 +02:00
08751d3672 Add install/update instructions database (#1160)
* Add install/update instructions database

* Update the database

* Revert README changes

They will be overwritten later.

* Revert

* Tweak

* Tweaks

* Upgrade database

* Complete commands

Still not sure about Spack upgrades.

* Sort

* Doc generation script draft

* Remove OS names from tool names

* Fix Linuxbrew name

* `wheel` already installs `setuptools`

* Gen docs

* Update

* Tweak

* Add a GitHub workflow to check for outdated installation instructions

* Fix return value

* Test

* Delete test

* Rename the script

* Add `make doc-install-inst`

* Add missing dev requirement

* The first tool is the primary we want to display

Then they are simply sorted by `tool.title`.

* Sort OSes by name

* Refactoring, jinja template, etc.

* Add tool title uniqueness `assert`, fix platform list extra `\n`

* Rebuild docs

* Update generate.py

* Update README.md

* Update methods.yml

* Update distros derived, more assertions

* Tweaks

* Add workflow to auto-update the docs

* Do not hide the command

* Tweaks

Co-authored-by: Jakub Roztocil <jakub@roztocil.co>
2021-10-06 11:18:27 +02:00
0c9d701618 Add make install-reqs to install packages without creating env 2021-10-05 21:37:48 +02:00
a3fa016428 Cover on Python 3.10 2021-10-05 21:30:28 +02:00
9c52449344 Add self to paths; same paths for PR and push 2021-10-05 21:28:39 +02:00
e4e4927567 Test on Python 3.10 2021-10-05 21:25:10 +02:00
031b4b89e3 Fix docs formatting 2021-10-05 15:46:10 +02:00
e1c08a3de5 Mention Snapcraft for unstable version installation 2021-10-05 15:45:34 +02:00
033798adc1 Update README.md 2021-10-03 03:20:23 +02:00
6a4e985f71 Remove redundant/inconsistent article 2021-10-03 03:08:05 +02:00
a6c70334cf Expand HTTP method docs
* mention `POST` without a body
* mention `GET` with a body
* mention custom method names
* include examples for default `GET`/`POST`
2021-10-03 03:05:37 +02:00
7388401134 Update setup.py 2021-10-02 16:50:39 +02:00
4ef31ecf71 Update utils.py 2021-10-02 16:43:29 +02:00
2423f893e5 Update config.json 2021-09-30 14:39:32 +02:00
b6a694afbc master/latest docs differ since --response-as 2021-09-30 14:39:18 +02:00
71adcd97d0 Improve handling of prettified responses without correct content-type encoding (#1110)
* Improve handling of responses without correct content-type charset

* [skip ci] Minor tweaks in tests

* [skip ci] Add documentation

Co-authored-by: claudiatd <claudiatd@gmail.com>

* Improve unknown encoding test

[skip ci]

* Review mime and options retrieval

* Add full content-type example in help output

* Simplify decoder

* [skip ci] s/charset/encoding/

* Tweaks

* [skip ci] Fix type annotation

* [skip ci] s/charset/encoding/

* Tweaks

* Fix type annoation

* Improvement

* Introduce `codec.encode()`

* [skip ci] Tweak changelog

Co-authored-by: claudiatd <claudiatd@gmail.com>
2021-09-29 20:22:19 +02:00
b50f9aa7e7 Use PYthon 3 documentation
[skip ci]
2021-09-28 12:54:16 +02:00
fe96b2af20 Use httpie.io/docs everywhere
[skip ci]
2021-09-28 12:53:53 +02:00
727b8a2c05 Sort available style choices (#1166) 2021-09-27 16:55:10 +02:00
9c89c703ae Allow to overwrite the response Content-Type from options (#1134)
* Allow to override the response `Content-Type` from options

* Apply suggestions from code review

Co-authored-by: Jakub Roztocil <jakub@roztocil.co>

* Rename the option from `--response.content-type` to `--response-as`

* Update CHANGELOG.md

Co-authored-by: Jakub Roztocil <jakub@roztocil.co>
2021-09-27 13:58:19 +02:00
8f8851f1db Remove trailing comma in test 2021-09-24 10:37:59 +02:00
bce2b3a98e Sort changelog 2021-09-23 17:17:29 +02:00
474093acdf Include plugin info in --debug output (#1165)
* Include plugin info in `--debug` output

* Adapt issue number

* Fix docs
2021-09-23 17:15:14 +02:00
1535d0c976 Mention XML when explaining formatting 2021-09-23 12:27:03 +02:00
cae83b3f9e Add FreeBSD installation instructions
Closes #761.
2021-09-23 10:46:06 +02:00
507514b795 Add workflow to test with pyOpenSSL active (#1164)
* Add workflow to test with pyOpenSSL active

Original patch by @gmelodie.

* Fix tests on Windows with Python 3.6
2021-09-23 10:37:23 +02:00
d7ed45bbcd Fix duplicate keys preservation of JSON data (#1163)
* Fix duplicate keys preservation of JSON data

* Update issue number

* Fix type annotations

* Changes after review

* Rewording
2021-09-21 19:07:59 +02:00
e6c5cd3e4b Improve JSON output when there is leading data before the actual JSON body (#1130)
In some special cases, to prevent against Cross Site Script Inclusion (XSSI)
attacks, the JSON response body starts with a magic prefix line that must be
stripped before feeding the rest of the response body to the JSON parser.
Such prefix is now simply ignored from the parser but still printed in the
terminal.

* Fix Windows tests
2021-09-21 11:15:43 +02:00
273134123a Bump the version to 2.6.0.dev0 (#1162)
[skip ci]
2021-09-21 10:40:09 +02:00
529aa78ee1 Expand the pytest configuration (#1161)
And rely on it to run tests.
2021-09-20 17:36:03 +02:00
e2ba214ac0 [snap] Improve OS integration (#1157)
Get back read-write access to `$HOME/.config/httpie` and `$HOME/.httpie`.
2021-09-15 16:50:44 +02:00
9dd0203bae Use HTTPie for the documentation build request (#1150)
Co-authored-by: Jakub Roztocil <jakub@roztocil.co>
2021-09-15 14:25:46 +02:00
ba6fd0bc14 Add a blog post link 2021-09-14 01:01:46 +02:00
8f7f4a6ef4 Remove some horizontal lines in the bug report
And add myself to assignees.
2021-09-13 12:36:01 +02:00
9984447f18 Reverse results in bug report temlpate
Ir seems weird to ask for the expected result before knowing the current one.
2021-09-13 12:33:32 +02:00
10081b9fcc Update README.md 2021-09-11 17:17:15 +02:00
4f84362d73 Update config.json 2021-09-10 23:58:33 +02:00
2b5f8f48bf Update update-documentation.yml 2021-09-10 20:06:29 +02:00
a51068a44d Update update-documentation.yml 2021-09-10 20:05:23 +02:00
f06d870012 Update and rename documentations.yml to check-markdown.yml 2021-09-10 20:04:52 +02:00
0115a4a466 Create config.json 2021-09-10 18:50:45 +02:00
7c1d26a8fa Update README.md 2021-09-10 11:17:23 +02:00
7734e47280 Update README.md 2021-09-10 11:17:10 +02:00
30c595b770 [snap] Comment out the problematic interface
It seems it just needs to be present for the snap to be rejected.
2021-09-10 11:04:57 +02:00
b38352858f [snap] Remove personal-files interface
Use of the `personal-files` interface is reserved for vetted publishers.

The interface requires a validation, but we need to publish at least
one package first. So let's skip that part, release a version and ask
for the interface access in a second time.

Also add a workflow to build & test the snap package.
2021-09-10 10:30:44 +02:00
a45b94fda6 Complete CentOS installation instructions 2021-09-09 16:38:36 +02:00
513e5080e4 Add the release workflow
It has to be triggered manually for now.
2021-09-09 16:13:13 +02:00
7c9f415107 Add a workflow to check documentations (#1151)
* Add a workflow to check documentations

* Fix markdown issues

* Install Ruby 2.7

* Finally, handle and fix GitHub templates

* Minor improvement in the feature request template

* Verbose mode to be sure all files are checked
2021-09-09 15:52:24 +02:00
4c8633c6e5 Split the monolithic workflow into specific ones (#1149)
* Split the monolithic workflow into specific ones

* Rename workflows, improve commands

* Update pip from the venv

* Fix Windows setup

* Lowercase macos-latest

* Fix Windows run, again
2021-09-08 16:41:55 +02:00
4d7d6b66cf Trigger official documentation build when documentation is updated here 2021-09-08 15:43:34 +02:00
a586fca246 Update brew formula to 2.5.0 (#1144)
* Update brew formula to 2.5.0

* Can use `idna` 3.2

* Sort requirements to ease reproductible builds

And also to have the same output as `brew bump-formula-pr`.

* Sync `bottles` with official Formula

And keep the `high_sierra` one.

* Add a workflow to check the Formula
2021-09-08 11:01:27 +02:00
978258ec5b Add Alpine Linux installation instructions 2021-09-08 10:04:49 +02:00
84ef9f588c Use lzo compression for snap (#1146) 2021-09-07 16:57:05 +02:00
cf21790411 Add the Snap build file for general Linux packaging
Based on the work of @elopio and @chipaca.

- Added support for the `snapd` protocol URL.
- Packaged Unix socket transport plugin.
2021-09-07 16:45:57 +02:00
1ef127c61d Packit: Get the current Fedora Rawhide specfile
Using the fork is not needed anymore,
since Rawhide was updated to 2.5.0 and no longer has patches.
2021-09-07 11:03:04 +02:00
4eaa4d67c5 v2.5.0 (#1140)
[skip ci]
2021-09-06 20:23:14 +02:00
9764cc74a4 Cleanup 2021-09-06 20:23:00 +02:00
778360cde1 Cleanup 2021-09-06 20:21:49 +02:00
60a7ed4e7b Cleanup 2021-09-06 20:21:09 +02:00
185af7c9f1 Cleanup 2021-09-06 20:20:30 +02:00
7e9e7c783f Readme tweaks (#1141) 2021-09-06 20:17:21 +02:00
6039bd8582 Switch from reStructuredText to Markdown and add docs/ (#1139)
* Convert most of the documentation from the frontend `README.rst` to `docs/REAME.md`

Also converted all reStructuredText files to Markdown.

* Tell `mdformat` to use LF for end on lines

* `--check` is not needed in the help message

* Skip tests on GitHub Windows.

Those tests pass on a real Windows machine.
Let's revisit those failure later, if needed.

* Move `mdoformat` requirement from `test` to `dev` extra

To fix Fedora CI.
2021-09-06 17:36:13 +02:00
e7d8b9cece Spelling and bash completion fixes (#1137)
* Remove hashbang from bash completion

Completion files are not supposed to have a hashbang.
They are sourced, not executed.

* Fix spelling

* Trim excess whitespace
2021-09-03 15:05:03 +02:00
a62391e789 Tiny clean-up in program() (#1135) 2021-09-02 16:47:01 +02:00
41666d897f Update CHANGELOG.rst 2021-09-02 10:37:14 +02:00
71008bbedb Move example URL in a global variable for XML tests 2021-09-01 16:56:23 +02:00
85110643e7 Move example URL in a global variable for tests 2021-09-01 16:52:10 +02:00
fdd486415a Fix XML formatter tests 2021-09-01 10:28:03 +02:00
6c501d23c3 Change default XML indent to 2 spaces 2021-08-31 22:52:16 +02:00
d10e108b5f Added support for XML formatting (#1129)
As a side effect, XHTML responses will be pretty-printed too.
2021-08-31 22:49:53 +02:00
8618f12fce Tweak format options docs 2021-08-24 17:18:45 +02:00
dac0d716c1 Add the formatting options section in the docs (#1131)
It will ease future changes and should improve reading/finding information.
2021-08-24 17:11:40 +02:00
0340f8caf5 Fix missing links in the changelog
[skip ci]
2021-08-17 11:21:04 +02:00
d7caeaf372 Fix handling of session files with Cookie: followed by other headers (#1127)
* Fix the handling of cookies from session files

* Apply suggestions from code review

Co-authored-by: Jakub Roztocil <jakub@roztocil.co>

* Fix test docstring formatting

Co-authored-by: Jakub Roztocil <jakub@roztocil.co>
2021-08-16 14:50:46 +02:00
54c8612452 Remove unused code in BasicConfig (#1123) 2021-08-06 18:04:08 +02:00
4ff22defe4 Rework __main__.py to follow best practices (#1124)
It also simplifies how the `main()` function could be tested.
2021-08-06 16:57:19 +02:00
c50e287c57 CI: Run tests on Python 3.10 RC1 (#1121) 2021-08-06 13:11:21 +02:00
6bd6648545 Simplify get_content_type() (#1125)
We were using the potential `encoding` returned by `mimetypes.guess_type()`
to expand the `Content-Type` header.
According to the RFC-7231 [1] the `Content-Type` should contain a charset
and nothing more. But as stated in the `mimetypes.guess_type()` doc [2],
the `encoding` would be the name of the program used to encode (e.g. compress
or gzip) the payload. The `encoding` is suitable for use as a `Content-Encoding`
header. See [3] for potential `encoding`s, none is a IANA registered one [4], and
so a valid charset to be used by the `Content-Type` header.

[1] https://httpwg.org/specs/rfc7231.html#header.content-type
[2] https://docs.python.org/3/library/mimetypes.html#guess_type
[3] 938e84b4fa/Lib/mimetypes.py (L416-L422)
[4] https://www.iana.org/assignments/character-sets/character-sets.xhtml
2021-08-06 12:35:38 +02:00
6633b5ae9b Use UTF8 constant in FORM_CONTENT_TYPE as well 2021-08-05 21:00:17 +02:00
c6cbc7dfa5 Uniformize UTF-8 naming (#1115)
* Uniformize UTF-8 naming

Replace `utf8` -> `utf-8` everywhere.
It should have no impact, `utf8` is an alias of `utf-8` [1].

[1] ee03bad25e/Lib/encodings/aliases.py (L534)

* Always specify the encoding

Let's be explicit over implicit. And prevent future warnings from PEP-597 [1].

[1] https://www.python.org/dev/peps/pep-0597/#using-the-default-encoding-is-a-common-mistake

* Update `UTF8` constant (`utf-8` -> `utf_8`)

* Remove default argument from `str.encode()` and `bytes.decode()`

* Clean-up
2021-08-05 20:58:43 +02:00
11399dde76 Refine abstract methods and properties (#1118) 2021-08-05 20:57:23 +02:00
da47e37c44 Use builtin open() in setup.py (#1120) 2021-08-05 20:56:59 +02:00
a66af2497a Add converter plugin streaming tests (#1117)
Also fixed minor glitches here and there and re-enabled a unicode test.
2021-08-05 14:37:08 +02:00
a94d6d807c Packit: Enable the Koji repsitory in Copr (#1119)
By default, only updates that are propagated trough the Fedora's update system
will be available in the community Copr build system.
On stable Fedora releases,
updates (including new packages) might be delayed 1+ week.

This adds the latest Koji (that's the name of the official Fedora build system) repo.
That repo contains more recent packages available during the official Fedora builds.

The Koji repo is not mirrored,
so the Copr builds are more likely to encounter a network issue,
but I think it is worth it.
The `/packit build` command may be used in the pull request if this happens.
2021-08-04 20:30:41 +02:00
de13423839 --download: Use time.monotonic() and rework code to prevent ZeroDivisionError specific handling (#1113) 2021-07-29 16:05:56 +02:00
04d05a8abd Minor clean-up (#1112)
* Remove Python 2 clean-up misses

* Remove unused `Environment.devnull` setter

* Simplifies `get_filename_max_length()`
2021-07-26 23:56:38 +02:00
2f8d7f77bd Add more download tests (#1114) 2021-07-26 20:27:36 +02:00
aee77a23af Simplify spinner_pos calculation a little (#1111) 2021-07-20 18:24:49 +02:00
64c31d554a Revert "Use http in the 'hello world' example to be consitent (#1109)"
This reverts commit 41c251ec7c.
2021-07-16 15:49:41 +02:00
41c251ec7c Use http in the 'hello world' example to be consitent (#1109) 2021-07-15 16:17:05 +02:00
147a066dbe Add internal support for file-like object responses to improve adapter plugin support (#1094)
* Support `requests.response.raw` being a file-like object

Previously HTTPie relied on `requests.models.Response.raw` being
`urllib3.HTTPResponse`. The `requests` documentation specifies that
(requests.models.Response.raw)[https://docs.python-requests.org/en/master/api/#requests.Response.raw]
is a file-like object but allows for other types for internal use.

This change introduces graceful handling for scenarios when
`requests.models.Response.raw` is not `urllib3.HTTPResponse`. In such a scenario
HTTPie now falls back to extracting metadata from `requests.models.Response`
directly instead of direct access from protected protected members such as
`response.raw._original_response`. A side effect in this fallback procedure is
that we can no longer determine HTTP protocol version and report it as `1.1`.

This change is necessary to make it possible to implement `TransportPlugins`
without having to also needing to emulate internal behavior of `urlib3` and
`http.client`.

* Load cookies from `response.headers` instead of `response.raw._original_response.msg._headers`

`response.cookies` was not utilized as it not possible to construct original
payload from `http.cookiejar.Cookie`. Data is stored in lossy format. For example
`Cookie.secure` defaults to `False` so we cannot distinguish if `Cookie.secure` was
set to `False` or was not set at all. Same problem applies to other fields also.

* Simpler HTTP envelope data extraction

* Test cookie extraction and make cookie presentment backwards compatible

Co-authored-by: Mickaël Schoentgen <contact@tiger-222.fr>
Co-authored-by: Jakub Roztocil <jakub@roztocil.co>
2021-07-06 21:00:06 +02:00
b7300c1096 Update Chocolatey command in the docs 2021-07-02 17:54:07 +02:00
5d4e7a9a18 Use echo -n in the docs (#1102)
I argue that you most likely don't want/need to send the trailing newline.
2021-07-02 10:31:38 +02:00
5717fb1ad5 Normalize the version (#1101)
To fix that warning:

    setuptools/dist.py:473: UserWarning: Normalizing '2.5.0-dev' to '2.5.0.dev0'
2021-07-01 10:34:51 +02:00
9c38da96b0 Remove snap installation method until package name fixed 2021-06-28 13:46:02 +02:00
e5bda98ee7 Mention snap install http in the docs (#1097) 2021-06-28 12:28:21 +02:00
c8d70e8c0b Simplify return statements in client.py (#1096)
Co-authored-by: Mickaël Schoentgen <contact@tiger-222.fr>
2021-06-28 09:05:24 +02:00
ae6f57dc76 Skip tests that randomly fail on Windows in CI 2021-06-26 14:03:31 +02:00
b4c94e0f26 Mention choco install httpie in the docs 2021-06-26 13:12:05 +02:00
7ceb313ccf Add --follow test for HTTP 308 2021-06-15 17:31:56 +02:00
3228e74df5 Add --follow --verbose test for HTTP 308 2021-06-15 17:24:26 +02:00
dc4309771e Mention 308 Permanent Redirect 2021-06-15 14:59:24 +02:00
07a0359316 Final touches for #1088 (#1091)
* Make sure there’s no trailing \n in test files for easier output inspection

* Refactor output matching test utils

* More robust `test_http_307_allow_redirect_post_verbose()`

* Changelog

* Mention HTTP 307 Temporary Redirect re-post behaviour in README
2021-06-15 14:48:44 +02:00
2d55c01c7e Fix printing redirected prepared request in verbose mode (#1088) 2021-06-15 13:39:46 +02:00
1470ca0c77 CI: Do not fail fast to have a real view of potential failures (#1090) 2021-06-11 20:55:51 +02:00
9857693ebf Use a more modern approach to run tests (#1089)
Running tests through `python setup.py test` is deprecated:

> WARNING: Testing via this command is deprecated and will be removed
> in a future version. Users looking for a generic test entry point
> independent of test runner are encouraged to use tox.

I am not in favor of moving back to `tox`, we should simply run tests
using `python -m pytest` (or `make test`) and that's it.

A new extra was added, `dev`, to install development requirements:

    $ python -m pip install --upgrade --editable '.[dev]'
2021-06-11 20:55:26 +02:00
da03a0656e Add a Packit configuration for Fedora packaging (#1086)
* Add Packit configuration for Fedora packaging

 - all pull requests are build-tested in https://copr.fedorainfracloud.org
 - new releases will create pull requests in https://src.fedoraproject.org/rpms/httpie

Co-authored-by: Mickaël Schoentgen <contact@tiger-222.fr>
2021-06-09 17:18:27 +02:00
61f1ffd0eb Prevent installation of test files (#1087)
(They’re still included in the package as per #182)
2021-06-09 17:14:27 +02:00
9792513c68 Add a reproduction test case for #1082 (#1085)
The fix may actually be slightly more complex than I expected.
We would need, at first sight, to loose the prepared requests + responses streaming.

A potential solution will come in a near future.
2021-06-09 09:43:06 +02:00
350f973f70 Switch from pycodestyle to flake8 for code style checks (#1083) 2021-06-02 11:06:46 +02:00
8d35a12d27 Fix several issues found with flake8 (#1081) 2021-06-01 14:46:58 +02:00
8374a9ed83 Review OSError exceptions handling (#1080)
- Replace obsolete `IOError` (Python 2) with `OSError`,
  cf https://docs.python.org/3/library/exceptions.html#OSError.
- Improve `OSError` catches at different places, simplifying
  the code.
2021-05-31 10:10:41 +02:00
a61f9e1114 Minor clean-up (#1078)
- Remove default arguments to `open()`.
- Make use of `pytest` mechanisms for temporary folders.
2021-05-29 12:06:06 +02:00
611b278b63 Fix --style colors list help indentation (#1077) 2021-05-28 12:45:40 +02:00
175e36da6b Remove Python 3.10 build
Not supported by GitHub actions yet.
2021-05-27 20:19:55 +02:00
19e1e26d97 Add Python 3.10 build 2021-05-27 20:17:14 +02:00
9b5aedb02d updated fish shell completions (#1076) 2021-05-27 20:13:00 +02:00
3865fabf09 Adapt doctest of tests.utils.http to work on Python 3.10 as well (#1075)
https://docs.python.org/3.10/whatsnew/3.10.html#enum

Python 3.10 changed the repr of enum members, and the doctest of tests.utils.http failed.
Exact reprs are unfortunately not considered stable API between Python releases:

    =================================== FAILURES ===================================
    __________________________ [doctest] tests.utils.http __________________________
    209
    210     Example:
    211
    212     $ http --auth=user:password GET pie.dev/basic-auth/user/password
    213
    214         >>> httpbin = getfixture('httpbin')
    215         >>> r = http('-a', 'user:pw', httpbin.url + '/basic-auth/user/pw')
    216         >>> type(r) == StrCLIResponse
    217         True
    218         >>> r.exit_status
    Expected:
        <ExitStatus.SUCCESS: 0>
    Got:
        ExitStatus.SUCCESS

A simple replacement of the expected output however breaks the doctest on Python 3.9.

This is the best solution I could think of
that keeps the docstring readable and doctest working in Pythons both old and new.
2021-05-27 19:54:33 +02:00
355befcbfc Skip http://pie.dev tests when offline (#1072) 2021-05-27 19:30:36 +02:00
fc7a349d36 Declare a [test] extra with test dependencies (#1074)
Since `python setup.py test` is deprecated and `tests_require` is only used by that,
this allows to programmatically read the tests dependencies from the metadata.
2021-05-27 19:21:34 +02:00
06ef27c576 Remove an useless shebang form non-executable file (#1073)
Shebangs have no function in non-executable files.
This file does not need to be directly executed.
2021-05-27 19:17:04 +02:00
0e556ec3a8 pytest: Add hidden files to norecursedirs (#1071)
The default value already contains this,
but when setting a custom one, it was overridden.

In Fedora, we build the package in `.pyproject-builddir` and not ignoring it confuses pytest:

    _pytest.pathlib.ImportPathMismatchError: ('httpie.__main__', '/builddir/build/BUILD/httpie-2.4.0/.pyproject-builddir/pip-req-build-aedma65c/build/lib/httpie/__main__.py', PosixPath('/builddir/build/BUILD/httpie-2.4.0/.pyproject-builddir/pip-req-build-aedma65c/httpie/__main__.py'))
2021-05-27 16:59:57 +02:00
464b5b4c1d Polish Python 2 removal (#1070) 2021-05-27 13:05:41 +02:00
264d45cdf5 Modernize the code base with f-strings in tests (#1069)
Simple concatenations were kept for readability purpose.
2021-05-26 14:09:38 +02:00
0ff0874fa3 Modernize the code base with f-strings (#1068) 2021-05-25 20:49:07 +02:00
39314887c4 README 2021-05-24 15:00:01 +02:00
f9a488d47e README 2021-05-24 14:40:08 +02:00
0001297f41 Add --raw to allow specifying the raw request body as an alternative to stdin (#1062)
* Add --raw to allow specifying the raw request body without extra processing

As an alternative to `stdin`.

Co-authored-by: Elena Lape <elapinskaite@gmail.com>
Co-authored-by: Jakub Roztocil <jakub@roztocil.co>

* Update README.rst

Co-authored-by: Jakub Roztocil <jakub@roztocil.co>

* Update README.rst

Co-authored-by: Jakub Roztocil <jakub@roztocil.co>

* Fix default HTTP method on empty data

Co-authored-by: Elena Lape <elapinskaite@gmail.com>
Co-authored-by: Jakub Roztocil <jakub@roztocil.co>
2021-05-24 14:29:54 +02:00
e2d43c14ce Prefer usage of "python -m pip" instead of "pip" (#1059)
* Prefer usage of "python -m pip" instead of "pip"

It will prevent issues when users think that they are using
the correct `pip` version. It can refers to the one from the OS
Python installation, or even worse to a Python 2 installation.
Let's be clear on how to install stuff.

Also used short version of `pip` arguments, because we are all lazy :)

* Apply suggestions from code review
2021-05-05 14:17:04 +02:00
a3a08a9a22 Use relative imports (#1057)
* Use relative imports in test

* Use relative imports

* Add myself to contributors :)
2021-05-05 14:13:39 +02:00
7cbdf2c608 Prefer usage of pytest rather than py.test (#1058)
`py.test` was chosen over `pytest` but it is not planned for removal yet [1].
Anyway, it is a good thing to ensure we are using the correct Python version
with the right `pytest` installed, so using `python -m pytest` is recommended.

[1] https://github.com/pytest-dev/pytest/issues/1629
2021-05-03 18:40:25 +02:00
1274d869f6 Replace usage of mock with unittest.mock (#1054)
Since Python 3, the mock dependency is no more required as
it is already part of the unittest module.
2021-04-30 15:08:27 +02:00
611bcdaab1 Fail gracefully if multiple request data files are supplied (#1042) 2021-04-15 09:35:50 +02:00
fc45bf0fe3 Explicitly require setuptools, httpie/plugins/manager.py imports pkg_resources (#1049) 2021-03-30 22:54:53 +02:00
56c4ba1794 Warn against non-ascii in setup.cfg (#1041) 2021-02-24 14:56:57 +01:00
8f83bfe767 Replace typography quotes (#1040)
fixes #1039
2021-02-24 14:38:18 +01:00
a32ad344dd Update README.rst 2021-02-23 12:51:06 +01:00
c53fbe5ae3 Typo 2021-02-23 12:22:35 +01:00
070ba9fa5a Tweaks 2021-02-18 13:48:48 +01:00
82ee071362 Tweaks 2021-02-18 13:47:58 +01:00
97dffb35a2 Spacing 2021-02-18 13:46:10 +01:00
18af03ac18 Issue templates tweaks II 2021-02-18 13:44:29 +01:00
904dd4107a Issue templates tweaks 2021-02-18 13:42:59 +01:00
8efabc86e6 Issue templates (#1031)
* add bug report template

* add feature request template

* add other template

* a httpie to an httpie

Co-authored-by: bl-ue <54780737+bl-ue@users.noreply.github.com>

* Update .github/ISSUE_TEMPLATE/bug_report.md

Co-authored-by: bl-ue <54780737+bl-ue@users.noreply.github.com>

* Update .github/ISSUE_TEMPLATE/bug_report.md

Co-authored-by: bl-ue <54780737+bl-ue@users.noreply.github.com>

* Update .github/ISSUE_TEMPLATE/bug_report.md

Co-authored-by: bl-ue <54780737+bl-ue@users.noreply.github.com>

* minor changes

* add discord

Co-authored-by: bl-ue <54780737+bl-ue@users.noreply.github.com>
2021-02-18 12:55:15 +01:00
cc20488f49 Formatting 2021-02-14 13:34:20 +01:00
b918972862 CHANGELOG #1032 2021-02-14 13:33:38 +01:00
84c7327057 Correctly handle single-byte Content-Range (#1032)
HTTPie previously failed if it continued a download with a single byte left.
2021-02-14 13:30:58 +01:00
e944dbd7fa 2.5.0-dev 2021-02-06 13:34:04 +01:00
157f3a1840 2021 2021-02-06 13:29:02 +01:00
61dbadb730 Tests 2021-02-06 13:21:21 +01:00
7be25d0751 Update brew formula to 2.4.0 2021-02-06 11:54:15 +01:00
5d5a8b4091 Typo 2021-02-06 11:26:15 +01:00
bb36897054 2.4.0 2021-02-06 11:17:24 +01:00
173e622567 Update upload command 2021-02-06 11:17:14 +01:00
3426030370 Fix README formatting 2021-02-06 11:13:04 +01:00
d014498713 Changelog entry for cookie expiration based on Set-Cookie: max-age=<n>
#1029
2021-02-06 11:02:26 +01:00
5414d1853e Refactoring
#1029
2021-02-06 10:58:36 +01:00
1ac8f69651 Add more output matching tests 2021-02-06 10:52:30 +01:00
3c07a25326 Add support for max-age=0 cookie expiry (#1029)
Close #998
2021-02-06 10:50:34 +01:00
cf78a12e46 Show --check-status warning with --quiet as well. (#1026)
Fixes #1028
2021-01-31 00:58:56 +01:00
0f1e098cc4 Fix incorrect separators and introduce assert_output_matches() (close #1027) 2021-01-30 22:14:57 +01:00
0401d7b31c fixed typo (#1024) 2021-01-21 22:35:41 +01:00
795627f965 Update chat icon 2021-01-13 22:24:20 +01:00
21cc008cb2 Add Linux Solus install to README (#1018) 2021-01-13 21:52:00 +01:00
77b8c37cb0 Update changelog
#1020
2021-01-13 21:49:53 +01:00
db685d58b5 Decode headers using utf-8 only if they are not str (#1020) 2021-01-13 21:45:56 +01:00
44ae67685d Add HTTPie Discord link to README (#1016)
* add discord link

* update link
2021-01-12 15:27:45 +01:00
6922a0c912 Switch from httpbin.org to pie.dev 2020-12-24 21:34:30 +01:00
2afdc958c6 Update URLs 2020-12-23 22:07:27 +01:00
57b1baf1d1 Add a test to reproduce #1006 2020-12-22 22:56:45 +01:00
1828da6a50 Update --stream example comment 2020-12-21 12:17:04 +01:00
0629f2ff42 Fix --stream example II 2020-12-21 12:14:41 +01:00
d71b7eee81 Fix --stream example
Close #1002
2020-12-21 12:12:11 +01:00
9883a46575 Cleanup (#993) 2020-12-21 12:03:25 +01:00
2409077a6d Clarify 2020-12-21 11:51:19 +01:00
02971b938d Fix documentation on file upload (#1000)
As documented later on in "File upload forms", the correct syntax to set
the mimetype of the upload is `field@file;type=filetype`
2020-12-21 11:47:47 +01:00
f7e77efe4b Test on Python 3.9 (#986) 2020-12-21 11:42:21 +01:00
5d8bd0da7c python -m pip (#1005) 2020-12-21 11:38:00 +01:00
3c6e7c73fe Update setup.py 2020-12-19 14:07:31 +01:00
d64c0ee415 Remove funding request 2020-12-18 17:54:13 +01:00
311a5ede70 Simplify Hello World 2020-10-29 10:07:45 +01:00
f64c90010f Simplify Hello World 2020-10-29 10:06:26 +01:00
8456ddb27c Update brew instructions for dev 2020-10-25 21:48:09 +01:00
cf254680b7 Update homebrew 2020-10-25 21:43:20 +01:00
42c4a7596b 2.4.0-dev 2020-10-25 21:36:24 +01:00
1573058811 v2.3.0 2020-10-25 21:12:38 +01:00
51bc8fb2c6 Update setup.py 2020-10-03 12:01:36 +02:00
a69d6f44fd New Twitter handle — @httpie 2020-10-03 11:01:08 +02:00
507cd6e255 Fix table formatting
reStructuredText is a mess
2020-09-29 21:26:38 +02:00
759e4400d0 Cleanup 2020-09-28 17:02:22 +02:00
8cb1af7376 Cleanup 2020-09-28 16:58:59 +02:00
2f8d330b57 Fix --offline --chunked, add more tests 2020-09-28 16:40:16 +02:00
32d8b481e9 Fix --offline --multipart, add more tests 2020-09-28 16:22:34 +02:00
75f1e02215 README 2020-09-28 12:55:39 +02:00
70ba84dc48 Fix fixture encoding on Windows 2020-09-28 12:53:28 +02:00
5a5b42340f PEP8 2020-09-28 12:50:45 +02:00
299250b3c3 Merge branch 'feature/uploads2020' 2020-09-28 12:43:09 +02:00
6925d930da Add support for streamed uploads, --chunked, finish --multipart, etc.
Close #201
Close #753
Close #684
Close #903
Related: #452
2020-09-28 12:16:57 +02:00
c1948f8340 Update README.rst 2020-09-25 22:27:54 +02:00
b80ba040ac Update README.rst 2020-09-25 22:26:39 +02:00
b7754f92ce Merge branch 'master' into feature/uploads2020
# Conflicts:
#	httpie/cli/argparser.py
#	httpie/uploads.py
2020-09-25 14:46:19 +02:00
e4e40e5b06 Request content type 2020-09-25 14:44:22 +02:00
d12af4a569 WIP 2020-09-25 13:44:28 +02:00
c431ed7728 CHANGELOG
#963
2020-09-20 09:30:18 +02:00
16ef08a159 Gracefully ignore cookie expiry dates in invalid format
Close #963
2020-09-20 09:21:10 +02:00
100872b5cf pep8 2020-08-19 10:39:13 +02:00
664cebfbcc Update README.rst 2020-08-19 10:31:20 +02:00
743f9738a3 Update README.rst 2020-08-19 10:30:40 +02:00
69445c106c Cleanup 2020-08-19 10:25:47 +02:00
1813cf6156 Add --multipart and --boundary 2020-08-19 10:22:50 +02:00
a23b0e39e5 Update README.rst 2020-08-17 13:34:23 +02:00
06dec4e6c6 Update README.rst 2020-08-17 13:31:51 +02:00
ce185bd0fa Update __init__.py 2020-08-17 13:16:57 +02:00
1e1dbfeba0 Update README.rst 2020-08-17 13:14:52 +02:00
5a908aa411 pep8 2020-08-15 17:51:43 +02:00
6cd934d1b8 Add support for multipart upload streaming
Close #684, #201
2020-08-15 17:50:00 +02:00
d32c8cab12 Syntax 2020-08-15 15:34:31 +02:00
5ce7c190e9 Add a --quiet example 2020-08-15 15:33:24 +02:00
1aa1366f99 Finish --quiet 2020-08-15 15:26:29 +02:00
2c7f24e3e5 Added additional tests to verify downloads work properly with quiet flag 2020-08-15 15:26:29 +02:00
c90d039a0b fixed issues related to downloading and using quiet at the same time 2020-08-15 15:26:29 +02:00
ae22d4e754 Additional Aesthetic changes 2020-08-15 15:26:29 +02:00
69e1067a2c Aesthetic changes 2020-08-15 15:26:29 +02:00
7e38f9ccf0 Added additional tests for flag and better documentation 2020-08-15 15:26:29 +02:00
d546081340 Solved issue pertaining to downloads and added additional testing functionality for devnull 2020-08-15 15:26:29 +02:00
6421c145d9 Added changes suggested in the PR review 2020-08-15 15:26:29 +02:00
61e7cd786e Added a documentation entry and modified CHANGELOG 2020-08-15 15:26:29 +02:00
4bd2e622a5 Added tests for --quiet flag 2020-08-15 15:26:29 +02:00
a4a1e8d43b Added a quiet functionality 2020-08-15 15:26:28 +02:00
ebf2139fd5 Introduce CurliPie to convert from cURL to HTTPie (#843) 2020-08-14 15:27:49 +02:00
6c84cebed4 Update build.yml 2020-08-06 22:35:35 +02:00
10246366da Quieten ssl tests (#952)
* Add skip when required TLS version unsupported

Allow tests to skip, rather than fail from SSL errors with unsupported
TLS version, e.g. if Openssl is configured with MinProtocol higher than
the version being tested.

* Regenerate test certificate and key

Regenerate these with more secure settings for the sake of future
proofing, regenerate the key using RSA 4096 and sign the certificate
with SHA512.

This fixes test failures in tests/test_ssl.py when the user's OpenSSL
security level is set to a value greater than 1 and resolves issue #948

* Suppress SSL warnings in no verify tests
2020-08-06 22:24:03 +02:00
a448b0d928 Fix minor typos in the README and CONTRIBUTING docs (#956)
* Fix typo in CONTRIBUTING docs

* Fix minor typo in README (exists --> exits)
2020-07-16 22:47:39 +02:00
0541490dda Add test to test auth plugin reused in session (#938)
* Add test to test auth plugin reused in session

* Remove unnecessary assertion in auth-plugin test

* Fixed auth test to use same session file

* Add test for password prompt behaviour in session

* Edit auth readme for plugin clarity
2020-07-10 12:48:26 +02:00
3704db9b6d Install setuptools & wheel in CI II. 2020-07-07 13:39:02 +02:00
d1665b08d2 Install setuptools & wheel in CI 2020-07-07 13:38:27 +02:00
1a4e0c2646 Add wheel to tests_require
Speculative. Not sure why it’s suddenly needed.

https://github.com/jakubroztocil/httpie/runs/845338452
2020-07-07 13:35:09 +02:00
0d480139e4 Split session JSON serialization and writing to file
To avoid writing invalid JSON in case of presence of unserializable data due to an internal bug.
2020-07-07 13:26:47 +02:00
9931747901 Update CONTRIBUTING.rst 2020-07-07 13:19:42 +02:00
8891afa3b7 Reorganize and expand CONTRIBUTING.rst 2020-06-26 17:48:04 +02:00
4f493d51f8 Add Windows setup instructions (#941)
* Added a sub-section specifically for windows

* Wrote instructions for creating/activating venv

* Split the PS and CMD examples into two separate code blocks

* Specified language for the code blocks

* Added test instructions for windows

* Converted slash to backward
2020-06-26 17:25:26 +02:00
cf937b6b79 Remove tox (#944)
* Removed the instructions of tox testing

* Deleted tox.ini

* removed tox from requirements

* removed tox from setup.cfg

* removed tox from the Makefile

* removed tox from contributing docs

* updated the CHANGELOG

* removed tox from .gitignore
2020-06-26 17:22:06 +02:00
14677bd25d Cleanup inline to-dos
I.
2020-06-25 11:36:09 +02:00
49e71d252f Fixed test_ciphers_none_can_be_selected on OpenBSD
Thanks @juped!
2020-06-19 18:26:08 +02:00
d6f25b1017 Update Brew formula for v2.2.0 2020-06-19 02:23:12 +02:00
a434cddd42 Fix install_requires 2020-06-19 01:13:11 +02:00
55d7af86fd Install requests[socks] by default for out of the box SOCKS support
Close #904
2020-06-19 00:56:30 +02:00
978aace86c Update README.rst (#737) 2020-06-19 00:25:29 +02:00
ecdeffe7c8 CHANGELOG + README 2020-06-18 23:23:10 +02:00
9500ce136a Combine cookies from original request and session file
Close #932
Co-authored-by: kbanc <katherine.bancoft@gmail.com>
Co-authored-by: Gabriel Cruz <gabs.oficial98@gmail.com>
2020-06-18 23:17:33 +02:00
93d07cfe57 v2.3.0-dev 2020-06-18 22:25:07 +02:00
5945845420 v2.2.0 2020-06-18 22:20:12 +02:00
3ee5b49256 Update README.rst 2020-06-18 10:58:13 +02:00
bb024757b6 Clarify config docs 2020-06-16 13:33:14 +02:00
d35864e79d Cleanup 2020-06-16 13:01:48 +02:00
8a106781be Add --sorted
Also add --no-(sorted|unsorted) to allow the documented resetting to default via --no-<option>.
2020-06-16 12:54:50 +02:00
23dd80563f Cleanup 2020-06-16 12:25:46 +02:00
2bab69d9fb Fix default value 2020-06-16 12:24:03 +02:00
826489950d Added --unsorted
It acts as a shortcut for --format-options=json.sort_keys:false,headers.sort:false

#128
2020-06-16 12:20:13 +02:00
b86598886e Added netrc support for auth plugins.
Enabled for --auth-type=basic and digest, 3rd parties may opt in.

This closes #718, closes #719, closes #852, and also closes #934
2020-06-16 11:05:00 +02:00
c240162cab Added a test that verifies .netrc is honored when only --auth-type is passed 2020-06-16 10:07:41 +02:00
26e29612f2 Update CHANGELOG.rst 2020-06-15 23:08:09 +02:00
37200eb055 Cleanup 2020-06-15 23:02:16 +02:00
9c68d7dd87 Remove expired cookies (#929)
* added a test for expiring cookies

* updated tests

* set up util for extracting expired cookies from response header

* Revert "updated tests"

This reverts commit a4eb5c4498.

* Revert "Revert "updated tests""

This reverts commit d242e21bce.

* added more functionality to get-expired-cookies

* add 'clear expired cookies' from session.json files

* refactored get_expired_cookies

* fixed formatting issues

* ensured key exists in cookie_header dict

* fixed linting errors

* removed unused import

* Added tests for get_expired_cookies util

* Added additional test for get_expired_cookies

* added remove_expired_cookies method directly to sessions class

* extracted logic to clear cookies to sessions.py

* refactored utils

* added tests to check expired cookies being removed from session obj

* added type annotations for methods

* Refactored test_sessions

* Seperated out expiry related tests into own class

* Refactored get_expired_cookies in utils

* Refactored remove cookie methods

* fixed linting errors

* fixed indentation and also pluralized test class name

* removed inheritance from SessionTestbase class

* Moved related test to TestExpiredCookies class

Co-authored-by: kbanc <katherine.bancoft@gmail.com>
2020-06-15 22:28:04 +02:00
7ee519ef46 Update CHANGELOG 2020-06-08 18:02:04 +02:00
c4627cc882 Custom file upload MIME type (#927)
* Support curl-like syntax for custom MIME type for files

In order to specify a custom MIME type for file uploads, a syntax
similar to that used by cURL is used so that

http -F test_file@/path/to/file.bin;type=application/zip https://...

forwards the user-provided file type if provided, otherwise falling
back to the usual guesswork out of the file extension.
2020-06-08 17:59:41 +02:00
492687b0da Add stable docs link icon 2020-05-28 14:30:56 +02:00
caeef2fb7c Use : instead of = in `--format-options 2020-05-28 14:24:15 +02:00
aae596d472 Improve --format-options error messages 2020-05-27 16:19:32 +02:00
cb51faec51 pep8 2020-05-27 16:12:31 +02:00
c2a0cef76e Add --format-options to allow disabling sorting, etc.
#128
2020-05-27 16:01:17 +02:00
493e98c833 Update CHANGELOG 2020-05-26 10:15:33 +02:00
ca02e51420 Improve plugin API docs 2020-05-26 10:07:53 +02:00
cd085cbc0d Refactor built-in plugin registry to avoid circular imports
Fix #925
2020-05-26 10:07:34 +02:00
27d57ce773 Cleanup 2020-05-23 20:30:25 +02:00
4c4efff56a Pass cert_reqs to context 2020-05-23 20:19:16 +02:00
a53505f26e Fix SSL context 2020-05-23 15:01:33 +02:00
165dc36f8d Add examples 2020-05-23 13:38:28 +02:00
5df3a91619 Add examples 2020-05-23 13:37:47 +02:00
7dbceafc01 Add docs for the https command alias 2020-05-23 13:34:59 +02:00
d62d6a77d1 Add support for --ciphers (#870) 2020-05-23 13:26:06 +02:00
0a81facccf Str env vars 2020-05-23 12:14:09 +02:00
3e20ade645 Cleanup & refactor XDG_CONFIG_HOME support 2020-05-23 12:12:35 +02:00
0c47094109 Update CHANGELOG.rst 2020-05-22 12:38:42 +02:00
defe4bc76d Fix issue links 2020-05-21 16:03:40 +02:00
afee6a7970 Added changelog entry for $XDG_CONFIG_HOME support 2020-05-21 15:59:03 +02:00
7b676dd583 Update ~/.httpie references to ~/.config/httpie 2020-05-21 15:56:53 +02:00
5af0874ed3 Support (part of) the XDG Base Directory Specification (#920)
On Unix-like systems, the configuration file now lives in
$XDG_CONFIG_HOME/httpie/ by default, not ~/.httpie/ (the behaviour on
Windows is unchanged). The previous location is still checked, in order
to support existing installations.

Searching $XDG_CONFIG_DIRS is still not supported.

Fixes #145; supersedes #436.
2020-05-21 15:50:00 +02:00
e11a2d1346 Update FUNDING.yml 2020-05-13 21:55:24 +02:00
b2044fc18d Update README.rst 2020-04-24 12:15:19 +02:00
d9a2d665ad Fix typo (#898) 2020-04-20 17:46:43 +02:00
e83e275dff Fix spelling of “GitHub” (#899) 2020-04-20 17:45:51 +02:00
4a99495466 Update CHANGELOG.rst 2020-04-18 20:44:40 +02:00
495f67229a Fix brew formula 2020-04-18 13:39:17 +02:00
45b9bae3dc Update brew formula 2020-04-18 13:24:25 +02:00
774ff148cd 2.2.0-dev 2020-04-18 12:57:56 +02:00
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
a7e5228712 Cleanup 2020-01-12 11:06:43 +01:00
5d628756ab Update Python version info 2020-01-12 11:00:25 +01:00
364edc4bd8 Ignore codecov upload failures 2020-01-12 10:57:14 +01:00
ce5ca6c480 Fix version 2020-01-12 10:55:45 +01:00
4b524e6a8c v2.0.0 2020-01-12 10:50:57 +01:00
e4a3ce8b9d Cleanup 2019-12-04 23:31:47 +01:00
348cc7d5c5 Fixes 2019-12-04 18:48:39 +01:00
ab3ea24630 Fixes 2019-12-04 18:34:26 +01:00
cd5116705c Set path in makefile 2019-12-04 18:24:53 +01:00
38bc578744 Fix tests 2019-12-04 18:09:51 +01:00
1bc54d4cb4 Create Python virtual environment (via venv) for tests & development, etc. 2019-12-04 17:49:07 +01:00
fe8b547cc7 Fix make target in CONTRIBUTING.rst (#819) 2019-12-04 13:54:00 +01:00
5aa9ed795e Switch to explicitly listed directories to search in for *.rst #820 2019-12-04 13:51:45 +01:00
c82d9b629f Merge remote-tracking branch 'origin/master' 2019-12-04 13:38:07 +01:00
e8b22d8b51 exclude site-packages from .rst file scanning (#820)
make test fails when finding .rst files from site packages installed
in the virtual environment
2019-12-04 13:37:57 +01:00
585cc0c039 Merge remote-tracking branch 'origin/master' 2019-12-04 13:37:46 +01:00
615d887513 run rst2pseudoxml.py with shell=true (#821)
makes rst2pseudoxml.py work properly on Windows

executes via a shell instead of not working
2019-12-04 13:33:13 +01:00
89faec994a Fix simple typo: downland -> download (#823)
Closes #822
2019-12-04 13:32:08 +01:00
490eeaa650 Cleanup 2019-12-03 19:09:09 +01:00
f1ab816ecd Tweak querystring parameters doc 2019-12-03 12:23:33 +01:00
6e2c31a5a9 Fix build 2019-12-02 20:57:21 +01:00
0608b5869f Upgrade setuptools 2019-12-02 20:47:09 +01:00
fcc3aaf873 Add Python 3.8 build 2019-12-02 20:39:07 +01:00
dcd6b63e45 withing -> within (#795) 2019-12-02 18:12:51 +01:00
ab2bda3ffe Fix typo (#808) 2019-12-02 18:04:52 +01:00
7390869cd6 Skip test_config_file_inaccessible on Windows 2019-12-02 17:59:44 +01:00
0af486d1b7 Ignore test cleanup rmtree errors (Win) 2019-12-02 17:53:29 +01:00
6cb822255d PEP8 2019-12-02 17:46:40 +01:00
f202f338a4 Remove automatic config file creation to avoid concurrency issues.
Close #788
Close #812
2019-12-02 17:43:16 +01:00
f0058eeaee cleanup 2019-12-02 10:42:33 +01:00
a23b636a63 Cleanup 2019-12-02 00:58:10 +01:00
fc497daf7d Update build.yml 2019-09-28 10:36:28 +02:00
b48ba74ce2 Update build.yml 2019-09-28 10:36:12 +02:00
9bae27354e Add main entry point tests 2019-09-18 11:57:27 +02:00
d9b3a16fa6 Make ExitStatus subclass IntEnum to allow direct int comparisons 2019-09-18 11:57:06 +02:00
f031b8cc8b Make codecov fail loudly 2019-09-18 11:17:33 +02:00
2dbafe27ed Fix codecov token 2019-09-18 11:16:19 +02:00
3affc245c4 Fix step order 2019-09-18 11:14:34 +02:00
85da430d16 codecov 2019-09-18 11:09:46 +02:00
a42b275ae2 Typing & cleanup 2019-09-17 09:21:49 +02:00
37fa67cd3c Runnable KeyValueArgType.tokenize doctest 2019-09-17 09:07:12 +02:00
0df4db7bb4 Cleanup 2019-09-16 13:28:01 +02:00
374c371ef1 Add httpie.status 2019-09-16 13:26:18 +02:00
64c81fc2ec Simplify 2019-09-10 14:40:34 +02:00
0252c2642e Build badge 2019-09-10 14:24:55 +02:00
b53ace480a Build on push via GitHub Actions 2019-09-10 14:18:06 +02:00
79b0f65fef Build on push via GitHub Actions 2019-09-10 14:14:39 +02:00
ed6156084f Remove .travis.yml 2019-09-10 14:14:08 +02:00
92fe452f92 worflow 2019-09-10 14:05:40 +02:00
0169151aa3 worflow 2019-09-10 14:02:11 +02:00
525449f044 worflow 2019-09-10 14:01:04 +02:00
3c4a5e7304 worflow 2019-09-10 14:00:28 +02:00
d9aadeef51 worflow 2019-09-10 13:59:43 +02:00
2bb54da368 worflow 2019-09-10 13:58:05 +02:00
3fa583e591 workflow 2019-09-10 13:39:59 +02:00
b7767b3c62 workflow 2019-09-10 13:36:02 +02:00
a5d9a839e5 coveralls token 2019-09-10 13:20:09 +02:00
2ffd8d9d9b workflow 2019-09-10 13:10:29 +02:00
7f80408945 Update pythonpackage.yml 2019-09-10 12:49:46 +02:00
3ec5c4a643 Update pythonpackage.yml 2019-09-10 12:46:34 +02:00
3909a436a9 Update pythonpackage.yml 2019-09-10 12:44:25 +02:00
a77f660ba7 Update pythonpackage.yml 2019-09-10 12:17:03 +02:00
548857f35a Update pythonpackage.yml 2019-09-10 11:56:55 +02:00
8741438484 Update CHANGELOG.rst 2019-09-09 09:36:22 +02:00
3176785a5f Create CODE_OF_CONDUCT.md 2019-09-04 13:38:56 +02:00
c8fd4c2d6e Move compression out of adapter 2019-09-04 00:00:03 +02:00
99f8a8c23d Typos 2019-09-03 22:37:59 +02:00
f866778421 CHANGELOG 2019-09-03 22:37:18 +02:00
5a4392076a Included tests in pypi package #182 2019-09-03 22:34:04 +02:00
bece3c77bb Add one-by-one processing of each HTTP request or response and --offline 2019-09-03 17:14:39 +02:00
c946b3d34f Cleanup 2019-09-02 14:38:23 +02:00
45e8e4e4ea Sessions 2019-09-01 21:15:39 +02:00
bd3208cf24 Refactor get_formatters_grouped 2019-09-01 11:45:47 +02:00
4dffac7a25 Refactor client 2019-09-01 11:38:14 +02:00
a34b3d9d87 Refactor PluginManager 2019-09-01 11:13:45 +02:00
30624e66ec Annotate formatters and processing 2019-08-31 19:13:36 +02:00
d603502960 Fix unregister annotation 2019-08-31 18:35:24 +02:00
09cd85918e CHANGELOG 2019-08-31 18:35:18 +02:00
b947d4826a Annotate plugins 2019-08-31 18:33:54 +02:00
e8ef5a783f Annotate and refactor streams.py 2019-08-31 18:21:10 +02:00
82a224a658 CHANGELOG 2019-08-31 18:00:34 +02:00
9da5c41704 Improve --debug output formatting 2019-08-31 18:00:03 +02:00
224519e0e2 Fix --ssl with --compress; refactor client 2019-08-31 17:52:56 +02:00
aba3b1ec01 Refactoring 2019-08-31 15:17:10 +02:00
466df77b6b CHANGELOG 2019-08-31 12:32:48 +02:00
3ea75a3577 Document $ALL_PROXY support (close #676)
It’s been supported by python-requests since v2.11.0 (2016-08-08)

d79024f246/HISTORY.md (2110-2016-08-08)
2019-08-31 12:31:32 +02:00
3e24827f4d Test that --ignore-netrc doesn't interfere with --auth 2019-08-31 12:14:44 +02:00
1dc67a6a38 Allow bypassing .netrc with --ignore-netrc (close #730) 2019-08-31 12:09:17 +02:00
a5713f7190 pep8 2019-08-30 21:26:51 +02:00
0f654388fc Python 3 annotations, super(), pathlib, etc. 2019-08-30 15:14:51 +02:00
63df735fef Update links to HTTPS 2019-08-30 10:07:01 +02:00
2579827418 Use set literal 2019-08-30 09:56:50 +02:00
9bd8b4e8f7 Don't fail if config dir not writeable (close #738) 2019-08-29 14:05:32 +02:00
d998013655 Merge branch 'mgsloan-allow-closed-stdin' 2019-08-29 13:40:00 +02:00
ced9212c1f Allow stdin to be a closed fd #791 2019-08-29 13:39:42 +02:00
07da8ea852 Merge branch 'allow-closed-stdin' of https://github.com/mgsloan/httpie into mgsloan-allow-closed-stdin 2019-08-29 13:26:28 +02:00
8e04a24b90 Reintroduce $ https command alias with https:// as default scheme
Close #608
2019-08-29 13:08:02 +02:00
8512a630f9 Use exact text from the three-clause BSD license (close #740)
As per https://opensource.org/licenses/BSD-3-Clause
2019-08-29 12:00:41 +02:00
2da2cec83c CHANGELOG 2019-08-29 11:51:49 +02:00
a4d8f1f22e Refactor --compress tests 2019-08-29 11:46:08 +02:00
5ec954c03d Add compressed requests (#739)
* Add optional compression of the request's content

This option allows compression of the files and/or data during uploading,

Examples:

    http --form --compress POST https://localhost/upload csv@./very-big.csv

    http -x -x POST https://localhost/upload foo=bar

    cat /var/log/system.log | http -x POST https://localhost/upload

Signed-off-by: Aleksandr Vinokurov <aleksandr.vin@gmail.com>

* Add tests for compression

Signed-off-by: Aleksandr Vinokurov <aleksandr.vin@gmail.com>

* Fix code style issues

Signed-off-by: Aleksandr Vinokurov <aleksandr.vin@gmail.com>

* Fix zlib compression api missuse in Python3

Signed-off-by: Aleksandr Vinokurov <aleksandr.vin@gmail.com>

* Remove tracing from compression logic

Signed-off-by: Aleksandr Vinokurov <aleksandr.vin@gmail.com>
2019-08-29 10:44:59 +02:00
2deaccf2d1 README 2019-08-29 10:21:13 +02:00
46c4f4e225 README 2019-08-29 10:20:45 +02:00
2d16494845 README 2019-08-29 10:16:39 +02:00
bb4f101c1e pep8 2019-08-29 10:09:56 +02:00
82081c889b Fix `--timeout=0` 2019-08-29 10:06:25 +02:00
05fc9c480a Remove the default 30-second connection timeout limit 2019-08-29 09:57:00 +02:00
e93de1fbe7 Make test_binary_suppresses_* deterministic 2019-08-29 09:46:17 +02:00
a969013bdd Disable default max headers limit and add --max-headers (closes #802) 2019-08-29 09:39:19 +02:00
65601f09b2 pip3 2019-08-29 09:28:57 +02:00
0f439a5dab Changelog 2019-08-29 09:01:27 +02:00
b3d2c1876e Python 2.7 support removal WIP 2019-08-29 08:53:56 +02:00
c297af0012 doc 2019-08-29 08:39:23 +02:00
f27b626a96 fix tests 2019-08-29 08:38:34 +02:00
c1d5a4a109 fix tests 2019-08-29 08:34:55 +02:00
db3016a602 Temporarily disable macOS stock Python Travis build
It's failing with InterpreterNotFound

https://travis-ci.org/jakubroztocil/httpie/jobs/578195789
2019-08-29 08:15:39 +02:00
4dd9dbd314 fix test_ssl_version II 2019-08-29 08:14:19 +02:00
29df4cd4f3 fix test_ssl_version on pypy 2019-08-29 08:05:31 +02:00
4d299a5531 Fix tests (work in progress) (#796)
* Add pyOpenSSL to dev requirements to fix tests on py2

* Add pyOpenSSL to the install requires

* Remove pyOpenSSL from install_requires
2019-08-29 07:59:18 +02:00
add6601009 Update homebrew formula for 1.0.3 (#801)
* Update brew formula for 1.0.3

This updates the Homebrew formula to:

* Install httpie 1.0.3
* Install the most up-to-date dependencies for httpie

* Add myself to AUTHORS
2019-08-29 07:38:46 +02:00
fa96041ec8 Update README.rst 2019-08-28 11:05:07 +02:00
3dccb2e325 Update CHANGELOG.rst 2019-08-26 17:42:47 +02:00
0a0de1755e Fix link 2019-08-26 12:47:31 +02:00
747be30d2e 1.0.3 2019-08-26 12:42:34 +02:00
88a9583f4c Update CHANGELOG.rst 2019-07-20 13:03:30 +02:00
c5ca9d248e Allow stdin to be a closed fd
Before this change, the following invocation would not work

```
$ http http://neverhttps.com <&-
```

The "<&-" at the end closes the stdin fd. Specifically, it would fail with

```
  ...
  File "/home/mgsloan/.local/lib/python3.6/site-packages/httpie/context.py", line 26, in Environment
    stdin_isatty = stdin.isatty()
AttributeError: 'NoneType' object has no attribute 'isatty'
```

This can occur when httpie is being programmatically invoked, and may
as well be supported.
2019-07-17 23:02:49 -06:00
fd6e87914c README 2019-06-24 12:36:08 +02:00
6dee49357d Fix comments 2019-06-24 12:29:42 +02:00
df36d6255d Changed the way the output filename is generated
When ``--download`` without ``--output`` results in a redirect,
now only the initial URL is considered, not the final one.
2019-06-24 12:20:09 +02:00
e92b831e6e Create FUNDING.yml 2019-06-23 12:05:24 +02:00
fd44f1af93 Updated Readme to fix a typo (#767) 2019-04-10 13:21:37 +02:00
b6309547d5 Add a bash here string example 2019-03-11 08:41:24 +01:00
3a46149de1 Fix several ResourceWarning: unclosed file (#741)
Signed-off-by: Mickaël Schoentgen <contact@tiger-222.fr>
2019-02-04 10:00:30 +01:00
b7c8bf0800 Add animation by @loranallensmith 2019-02-03 15:27:17 +01:00
69d010a11b Brew cleanup 2019-02-03 15:08:29 +01:00
42ff243400 Add make brew-test 2019-02-03 14:58:23 +01:00
933b438e5f Bump dependency versions #742 2019-02-03 14:26:05 +01:00
358342d1c9 Update LICENSE 2019-01-09 12:30:44 +01:00
c591a3810d 1.0.3-dev 2018-11-14 16:36:47 +01:00
0eba037037 v1.0.2
Close #729
2018-11-14 16:36:19 +01:00
3898129e9c Changelog 2018-11-14 16:22:00 +01:00
b88e88d2e3 Fix tests for installation with pyOpenSSL #729 2018-11-14 16:10:08 +01:00
d1407baf76 Add make pdf 2018-11-14 13:06:10 +01:00
d5032ca859 Fix changelog 2018-11-14 11:45:57 +01:00
f6a19cf552 Don't call external URLs from tests #729 2018-11-14 11:42:59 +01:00
74979f3b33 Brew 2018-11-06 11:37:33 +01:00
698eb51e60 Update screenshot 2018-11-03 18:08:43 +01:00
ae8030c930 Homebrew formula for v1.0.0 2018-11-02 17:18:04 +01:00
2e96d7ffbb Update CHANGELOG.rst 2018-11-02 16:28:17 +01:00
b5625e3d75 v1.0.0 2018-11-02 16:24:35 +01:00
932d3224f4 Cleanup 2018-11-02 16:23:17 +01:00
b596fedf13 exit 0 constant: OK => SUCCESS to avoid confusion w/ HTTP 200 OK 2018-11-02 16:07:39 +01:00
96444f3345 Changelog 2018-11-02 15:13:53 +01:00
89b66f1608 Merge remote-tracking branch 'origin/master' 2018-11-02 14:58:08 +01:00
a7d570916d #722: Add support for tls1.3 (#724)
* #722: Add support for tls1.3

* #722: Document the potential support for tls1.3
2018-11-02 14:57:53 +01:00
ab5a50cee8 Finish --style=auto for terminal ANSI colors and make it the default.
Previously (only in the development version), this was called 'preset'.
2018-11-02 14:53:05 +01:00
91961c6b51 Fixed some lines (#723) 2018-10-31 19:17:44 +01:00
256ea7d49d Add prog parameter to HTTPieArgumentParser (#715) 2018-10-30 18:41:56 +01:00
2cd6ea3050 Fix some broken documentation links (#703) 2018-09-07 19:10:04 +02:00
37dddf5bf7 Fix for broken Travis builds on macOS with Python 3.7 (#704) (#705) 2018-09-07 19:09:30 +02:00
e508c631f2 Fix Tox using different Python than expected on macOS (#688) (#706) 2018-09-07 19:08:37 +02:00
55530c8c6d fixed output for escaping rules (#700) 2018-09-03 20:04:18 +02:00
eb929cbc04 Travis CI: Add Python 3.7 on linux to the testing (#690)
* Travis CI: Add Python 3.7 on linux to the testing

`sudo: true` and `dist: xenial` are currently required https://github.com/travis-ci/travis-ci/issues/9069

* NEWEST_PYTHON=3.7
2018-07-25 14:02:00 +02:00
2490bb25ca Add v 0.9.9 CHANGELOG link 2018-07-22 17:58:52 +02:00
2038fa02e3 Mention v0.9.9 in CHANGELOG
#620
2018-07-22 17:57:52 +02:00
59d51ad513 Travis 2018-07-12 21:52:01 +02:00
61568f1def Travis 2018-07-12 21:46:00 +02:00
f93f4fa7c7 Travis CI Python versions; install fix 2018-07-12 21:33:12 +02:00
bf73b5701e Fix travis.yml syntax 2018-07-12 21:23:32 +02:00
7917f1b40c Build fixes and clean-up
* reflect Python 3.7 release
* fix `pycodestyle` errors
* update `pycodestyle` config
* move `pytest` and `pycodestyle` config to `setup.cfg`
* add `make pycodestyle`
* add `make coveralls`
* etc.
2018-07-12 21:16:16 +02:00
a50660cc70 Test --timeout with longer delay
test_timeout_exit_status fails on Python 2.7
https://travis-ci.org/jakubroztocil/httpie/jobs/390072675#L325
2018-07-12 00:39:31 +02:00
749b1e2aca Fix pytest configuration 2018-06-09 11:59:34 +02:00
137889a267 Doc improvements 2018-05-30 14:07:52 +02:00
c9c6f0fae5 Formatting 2018-05-30 14:02:46 +02:00
6fd1ea0e5a Section ordering 2018-05-30 13:56:35 +02:00
8f7676a2a9 Add Cookies section to the docs 2018-05-30 13:55:06 +02:00
87e661c5f1 Support using styles from Pygments plugins (#663)
`pygments.styles.STYLE_MAP` contains only styles built directly into
Pygments library. To list all available styles (including styles
registered by plugins), one should use `get_all_styles` generator.

For respective Pygments documentation, see:
http://pygments.org/docs/styles/#getting-a-list-of-available-styles
2018-04-14 15:25:59 -05:00
8ca333dda0 Use parentheses in describing sessions (#664)
It's a little more readable than using em dashes.
2018-04-11 20:04:02 -05:00
0f4dce98c7 Make default HTTP headers case-insensitive
Cloase #644
2018-02-22 12:52:57 +01:00
05547224ce Remove a Python 2.6 mention from extras_require 2017-12-28 18:33:31 +01:00
6301fee3d2 Upgrade to latest requests 2017-12-28 18:32:29 +01:00
a803e845a5 More robust urllib3 import 2017-12-28 18:32:12 +01:00
11be041e06 Rename TestEnvironment to MockEnvironment to avoid pytest warnings
Close #621
2017-12-28 18:17:48 +01:00
7f5fd130c5 Start using dict comprehensions 2017-12-28 18:15:17 +01:00
ec899d70b7 Removed Python 2.6 support
* Travis CI doesn't support it anymore.
* It had EOL more than 4 years ago
2017-12-28 18:03:37 +01:00
4d3b4fa0be Fix rst 2017-12-22 14:48:08 +01:00
27c557e983 Update README.rst
test
2017-12-22 14:40:48 +01:00
7f24f7d34c Delete appveyor.yml 2017-12-22 14:36:13 +01:00
4b61108005 Remove AppVeyor II. 2017-12-22 14:35:23 +01:00
8b189725fd Remove AppVeyor
@appveyor  https://help.appveyor.com/discussions/problems/10507-pip-install-fails-with-access-is-denied-error
2017-12-22 14:34:20 +01:00
1719ebded6 Fix README (#641) 2017-12-22 03:37:04 +01:00
c5d6a4ad8e OS X => macOS
Close #634
2017-12-17 19:45:46 +01:00
91e1fe2d0f appveyor fix attempt II. 2017-12-13 21:32:37 +01:00
ca7f41de53 appveyor fix attempt 2017-12-13 21:29:51 +01:00
46e24dd6b5 Use function as source of styles for Fish completion 2017-12-13 21:22:53 +01:00
803127e8c9 Remove duplicate option from Fish completion list 2017-12-13 21:22:53 +01:00
4c138959ea Merge pull request #633 from darshanime/version_number_fix
fix env version attribute
2017-12-13 21:18:38 +01:00
91a28973bd Merge pull request #631 from CrazyPython/patch-2
Fix Travis Build by removing 2.6
2017-12-13 21:16:05 +01:00
02b28093a8 Merge pull request #630 from CrazyPython/patch-1
Clarify error message
2017-12-13 21:15:43 +01:00
d64e7d8a6a Merge pull request #638 from gtback/update-contributing-rst
Update CONTRIBUTING.rst to include correct Makefile targets.
2017-12-13 21:14:31 +01:00
8841b8bf46 Update CONTRIBUTING.rst to include correct Makefile targets. 2017-12-07 04:39:32 +00:00
6472ca55e1 fix env version attribute 2017-11-18 19:01:26 +05:30
37c3307018 Remove 2.6 2017-11-14 09:18:10 -05:00
0aab796960 Clarify error message 2017-11-13 07:23:52 -05:00
95c33e31a2 Merge pull request #614 from watersalesman/master
List DNF as Fedora package manager in README
2017-10-04 12:09:07 -05:00
9af833da30 List DNF as Fedora package manager in README 2017-10-02 16:55:35 -04:00
dfe6245cd6 Update AppVeyor 2017-09-07 13:57:15 +02:00
555761f3cb Update copyright year 2017-09-06 01:42:16 +02:00
643735ef23 Fix Gitter link
Close #590
2017-09-06 01:14:56 +02:00
7a45f14542 Merge pull request #584 from scorphus/hotfix/new-requests
Support requests>=2.14.0
2017-07-20 07:54:08 +02:00
e993f83355 Merge pull request #589 from alappe/patch-1
Update README.rst, fix typo…
2017-07-20 07:53:30 +02:00
d726a4cd92 Merge pull request #591 from DavidOliver/patch-1
Fix sentence on overriding default timeout in readme
2017-07-20 07:52:57 +02:00
8d3f09497b Fix sentence on overriding default timeout in readme 2017-06-30 14:54:49 +02:00
31c78c2885 Update README.rst 2017-06-26 13:00:46 +02:00
9776a6dea0 Support requests>=2.14.0
From that release onwards, `cert_verify` raises `IOError` [1].

    1: https://github.com/kennethreitz/requests/commit/7d8b87c
2017-05-17 20:31:10 -03:00
f1d4861fae Merge pull request #568 from dsego/dsego/ansi-colors
Follow terminal ANSI color styles

Close #524
2017-03-12 22:44:05 +01:00
d99e1ff492 Fix link 2017-03-12 13:31:03 +01:00
a196d1d451 Travis cache: pip 2017-03-12 13:18:39 +01:00
02209c2db1 Oops, remove semicolons 2017-03-11 18:12:00 +01:00
9886f01f91 New style option that applies the terminal ANSI color scheme 2017-03-11 18:00:35 +01:00
a4f796fe69 Revert "Follow terminal ANSI color styles"
This reverts commit b0fde07cfd.
2017-03-11 16:58:50 +01:00
c948f98b05 Update links 2017-03-10 11:27:38 +01:00
b0fde07cfd Follow terminal ANSI color styles
Removes the default solarized color scheme and custom http lexer class.
2017-03-06 01:05:50 +01:00
f74670fac1 Update README.rst 2017-03-01 12:40:26 +01:00
7321b9fa4e Add --verify true/false tests and CHANGELOG 2017-02-17 00:56:07 +01:00
cf8d5eb3e8 Merge pull request #560 from hangtwenty/dummyproof-cli-param-verify
Add --verify=(true|false) as an alternative to (yes|no) and make the boolean value case-insensitive
2017-02-17 00:43:22 +01:00
64af72eb88 Turn --verify=False/True to --verify=no/yes
One way to address #559 -- https://github.com/jkbrzt/httpie/issues/559
-- instead of warning or throwing an error, just accept "True" and "False"
as synonyms of yes/no

(Updated to reflect feedback given at https://github.com/jkbrzt/httpie/pull/560 )
2017-02-13 18:30:55 -06:00
de38f86730 Merge pull request #558 from RobDesideri/patch-1
Update pip official website url
2017-02-09 21:13:47 +01:00
244ad15c92 Update pip official website url 2017-02-09 15:25:07 +01:00
586f45e634 Merge pull request #494 from keik/patch-1
Fix typo
2017-02-07 20:50:43 +01:00
b1b4743663 Merge pull request #555 from rootulp/patch-1
Gitter Badge: flat-square style
2017-02-07 20:50:01 +01:00
5600b4a2d3 Merge pull request #557 from robertbenjamin/fix-doc-typo
Update README.rst
2017-02-07 20:49:34 +01:00
9261167a1f Fix typo in the docs 2017-02-02 11:45:58 -08:00
519654e21b Gitter Badge: flat-square style
To match the other badges
2017-01-22 20:58:58 +00:00
4840499a43 Merge pull request #552 from duboviy/master
Add Python 3.6 support
2017-01-08 19:57:56 +01:00
ee6cdf4ab3 Update setup.py 2017-01-08 16:20:53 +02:00
98003f545d Update appveyor.yml 2017-01-08 16:19:26 +02:00
0046ed73c6 Update .travis.yml 2017-01-08 16:18:19 +02:00
66a6475064 Update tox.ini 2017-01-08 16:12:31 +02:00
97804802c0 Alternatives 2016-12-17 03:10:52 +01:00
c9296a9a45 Added link to httpcat 2016-12-17 03:06:48 +01:00
64a41c2601 README 2016-12-17 03:04:59 +01:00
0af6ae1be4 Fix PyPi README rendering
Close #540
2016-12-09 00:26:55 +01:00
d0fc10cf1a AWS / Amazon S3 auth plugin link 2016-12-08 21:48:38 +01:00
fe1d0b0a1e Doc 2016-12-08 21:48:18 +01:00
f133dbf22c Update README with new plugin repos location 2016-12-08 21:48:11 +01:00
9d93b07a9d Redme 2016-12-08 05:38:25 +01:00
761cdbf8be Update Homebrew formula 2016-12-08 05:25:50 +01:00
3a3aecca45 0.9.8 2016-12-08 05:22:20 +01:00
fb3a26586a Fix --auth-type help 2016-12-08 05:16:22 +01:00
cc9083f541 Keep the latest submitted Homebrew formula in extras/ for testing 2016-12-08 04:58:49 +01:00
9ae86f3b4f 0.9.7 2016-12-08 04:47:32 +01:00
3a6fd074a1 Added ExitStatus.PLUGIN_ERROR (7) 2016-12-08 04:42:17 +01:00
da59381b0b Fix PyPi link 2016-12-07 18:54:53 +01:00
6de2d6c2cb Docs 2016-12-07 06:20:01 +01:00
b9b033ed0c Docs 2016-12-07 06:00:51 +01:00
64d6363565 Docs 2016-12-07 05:59:27 +01:00
923b7acbe6 Docs 2016-12-07 05:56:53 +01:00
2efc0db8d4 Cleanup 2016-11-24 00:58:41 +01:00
2bf71af286 pep8 2016-11-23 23:36:46 +01:00
0b84180485 Fix Python 2.6 2016-11-23 23:20:52 +01:00
5a1bd4ba83 Cleanup 2016-11-23 23:15:18 +01:00
3f7ed35238 Add more plugin API tests 2016-11-23 23:09:45 +01:00
47fd392c74 Cleanup 2016-11-23 22:33:22 +01:00
54a63a810e Cleanup/docstring 2016-11-23 22:29:36 +01:00
a49774d3ab Extend auth plugin API
This extends the `AuthPlugin` API by the following attributes:

* `auth_require`: set to `False` to make `--auth, -a` optional
* `auth_parse`: set to `False` to disable `username:password` parsing
  (access the raw value passed to `-a` via `self.raw_auth`).
* `prompt_password`: set to`False` to disable password prompt when
   no password provided (only relevant when `auth_parse == True`)

 These changes should be 100% backwards-compatible.

 What needs more testing is auth support in sessions.

Close #433
Close #431
Close #378
Ping teracyhq/httpie-jwt-auth#3
2016-11-23 22:02:12 +01:00
b879d38b07 Test case for Host header removal (unimplemented feature) 2016-11-23 22:02:12 +01:00
0913e8b2ef Merge pull request #533 from kigawas/patch-1
Update README.rst
2016-10-28 18:11:55 +02:00
4fef4b9a75 Update README.rst
Change "you shell" to "your shell"
2016-10-28 12:02:21 +08:00
bfc23b1412 Changelog 2016-10-26 12:18:53 +02:00
6267f21f21 Clean-up 2016-10-26 11:58:47 +02:00
e9aba543b1 Changelog 2016-10-26 11:54:35 +02:00
9b23a4ac9a Exit with status 130 on CTRL-C
http://www.tldp.org/LDP/abs/html/exitcodes.html

 #531
2016-10-26 11:53:01 +02:00
b96eba336d Fixed test 2016-10-26 11:28:17 +02:00
48a6d234cb Need a main()
#531
2016-10-26 11:21:30 +02:00
c6f2b32e36 Stricter KeyboardInterrupt silencing
Relates to #531, but doesn't solve it completely.
2016-10-26 11:16:39 +02:00
64f6f69037 Add Twitter link 2016-09-17 15:58:05 +02:00
6bdfc7a071 Update config and session file help URLs 2016-09-12 10:57:30 +02:00
497a91711a README 2016-09-12 09:13:37 +02:00
f515ef72d0 README 2016-09-12 09:12:07 +02:00
22a2fddc79 README 2016-09-12 08:59:55 +02:00
1847eaa299 Updated config docs 2016-09-11 18:48:56 +02:00
e387c1d43e Updated config docs 2016-09-11 18:46:33 +02:00
fc6d89913f README 2016-09-11 11:39:03 +02:00
d584686744 README 2016-09-11 01:16:07 +02:00
b565be4318 CHANGELOG 2016-09-06 11:53:52 +01:00
87e44ae639 Handle curses-free Pythons 2016-09-06 11:50:56 +01:00
0d08732397 Merge pull request #516 from dongweiming/fix-496
Fix the handling of zero REQUEST_ITEM arguments 

Close  #496
2016-09-06 11:06:45 +01:00
c53a778f60 Fix Issue #496 2016-09-01 17:46:34 +08:00
5efc9010cc Update CHANGELOG.rst 2016-08-14 11:36:21 +02:00
08e883fcfe Merge pull request #503 from zquestz/patch-1
Updated README.rst to add Arch Linux install docs.
2016-08-14 04:09:50 +02:00
c4b309164f Updated README.rst to add Arch Linux install docs. 2016-08-13 19:08:37 -07:00
8e96238323 v0.9.6 2016-08-13 23:01:05 +02:00
8a9206eceb Fixed Makefile 2016-08-13 22:57:44 +02:00
8ac3c5961c Upgrade Pygments version 2016-08-13 22:57:33 +02:00
487c7a9221 v0.9.5 2016-08-13 22:51:42 +02:00
6d65668355 Strip request header values 2016-08-13 22:40:01 +02:00
3e5115e4a2 Merge pull request #501 from ii-v/master
Fixed spelling mistake in the AUTHORS.rst file
2016-08-11 08:37:41 +02:00
2b8b572f22 Merge pull request #1 from ii-v/ii-v-patch-1
Fixed spelling mistake `GitHib` to `GitHub`
2016-08-11 01:44:04 +02:00
af737fd338 Fixed spelling mistage GitHib to GitHub 2016-08-11 01:43:15 +02:00
ee375b6942 Merge pull request #493 from medecau/codestyle_environment
Codestyle environment
2016-07-29 23:17:00 +02:00
6b06d92a59 Fix typo 2016-07-27 09:54:26 +09:00
becb63de9a useful info 2016-07-26 21:59:34 +01:00
86c8abc485 force os to be linux (+1 squashed commit)
Squashed commits:
[444c56d] no vars for you (+1 squashed commit)
Squashed commits:
[c7d1bf9] added pycodestyle environment to travis config
2016-07-26 21:43:13 +01:00
8f6bee9196 codestyle fixes 2016-07-19 17:23:40 +01:00
9c2c058ae5 separate environment to test codestyle as proposed by @sigmavirus24 2016-07-19 17:23:18 +01:00
6238b59e72 Fix formatting 2016-07-08 15:05:43 +02:00
702c21aa91 Added related projects 2016-07-08 15:03:48 +02:00
aab5cd9da0 PEP8. clean-up 2016-07-04 20:30:55 +02:00
8c0f0b578c Clean-up 2016-07-02 18:44:02 +02:00
bb4881a873 Fixed README 2016-07-02 18:30:04 +02:00
3a1726b4ed Fixed README 2016-07-02 15:04:19 +02:00
e1fa57d228 Added -I as a shortcut for --ignore-stdin 2016-07-02 15:01:46 +02:00
bfc64bce21 Upgrade requests to 2.10.0 to enable optional SOCKS support
Closes #86
2016-07-02 14:58:34 +02:00
595dc51b2d Fish shell completion 2016-07-02 14:33:04 +02:00
83fa772247 Merge pull request #459 from dickeyxxx/fish-completion
added completions for fish shell
2016-07-02 14:31:06 +02:00
49a0fb6e0f More liberal default JSON Accept header
Closes #470
2016-07-02 14:18:36 +02:00
41e822ca2f Clean-up 2016-07-02 12:51:35 +02:00
1124d68946 Added --default-scheme <URL_SCHEME>
Closes #289
2016-07-02 12:47:02 +02:00
c3735d0422 Merge pull request #401 from lgarron/default-scheme
Add a --default-scheme argument.
2016-07-02 12:32:07 +02:00
364b91cbc4 Skip pypy3 tests on TravisCI 2016-07-02 12:03:52 +02:00
c8e06b55e1 Fix tests 2016-07-02 12:03:19 +02:00
5acbc904b7 Added the ability to unset headers
Closes #476
2016-07-02 11:50:30 +02:00
0c7c248dce Fix CHANGELOG 2016-07-02 11:17:38 +02:00
caf60cbc65 Typos 2016-07-02 11:11:06 +02:00
2b0e642842 Document preference for Python 3
Also mention that the Homebrew formula depends on Python 3 starting with HTTPie 0.9.4.
2016-07-02 11:07:46 +02:00
e25948f6a0 1.0.0-dev 2016-07-01 19:17:31 +02:00
b565b4628e v0.9.4 2016-07-01 19:02:34 +02:00
65081b2f12 Cleanup 2016-07-01 19:00:06 +02:00
963b2746f5 Be more liberal when detecting JSON in the formatter
Closes #485
2016-07-01 18:57:13 +02:00
098257c0be Rename --print-others to --history-print. 2016-07-01 18:49:27 +02:00
30eb0c2f26 Merge pull request #468 from Natim/master
Update readthedocs links.
2016-04-28 23:14:52 +08:00
9fbe745987 Update readthedocs links. 2016-04-28 12:28:20 +02:00
01a546eedd Merge pull request #463 from KyleAMathews/patch-1
Remove extra backtick.
2016-04-20 11:17:40 +08:00
eba6b63c55 Remove extra backtick. 2016-04-18 15:11:04 -07:00
ec245a1e80 added completions for fish shell 2016-04-06 11:28:03 -07:00
33eb9acd92 Updated README 2016-03-18 09:20:19 +08:00
293295cad6 Removed XML formatter
Closes #443
Closes #389
Closes #415
Closes #384
Closes #394
2016-03-18 09:16:39 +08:00
557911b606 Handle that os.pathconf is posix-only 2016-03-17 16:14:14 +08:00
5300b0b490 Fixed #451 - OSError: [Errno 36] File name too long 2016-03-17 15:58:01 +08:00
001bda1945 README 2016-03-17 15:00:50 +08:00
7c68d87c10 README 2016-03-10 14:27:33 +08:00
35a99fe04b Added test for -F shortcut 2016-03-09 21:58:34 +08:00
76e15b227c Added test_verbose_implies_all 2016-03-09 21:58:11 +08:00
8881ebf033 Changed the version icon label to include to word "stable" 2016-03-09 13:49:00 +08:00
25d1e8e418 Add Accept-Encoding: identity for --download
#423
2016-03-07 11:46:59 +08:00
7ce6eb148e Typo 2016-03-07 07:09:58 +08:00
6e1dbadff9 Replace --show-redirects with --all and add --print-others, -P
With --all, any intermediary requests/responses are shown (such as redirects
 or the initial unauthorized Digest auth request).

 The --print-others, -P option works like --print, -p, but only applies to
 intermediary requests/responses. The default behaviour is to inherit
 the value of -p.
2016-03-07 07:04:23 +08:00
a6ebc44a48 Run tests against both HTTP and HTTPS
Some of the tests now use the `httpbin_both` fixture from pytest-httpbin.
Also, made httpbin's CA trusted by default and added `httpbin_secure_untrusted`
fixture  to allow overriding that for particular tests.
2016-03-06 17:42:35 +08:00
5e03aeceb7 Make fruity default style one Windows
(again)
2016-03-06 08:33:40 +08:00
13ee9389aa Add link to contributors 2016-03-05 19:48:35 +08:00
bb49a1f979 Improved --debug output 2016-03-05 01:42:48 +08:00
4e574e6b8e Cleanup tests 2016-03-03 18:50:18 +08:00
529981af7a Fix CHANGELOG 2016-03-03 18:46:58 +08:00
6731cb881a README 2016-03-03 17:26:47 +08:00
f7d1b739e2 README 2016-03-03 17:24:46 +08:00
5bdf4a3bae Fixed test_rst_file_syntax error message 2016-03-03 17:22:12 +08:00
2d9414d34c Fixed README 2016-03-03 17:21:51 +08:00
20823c1702 Removed the "implicit_content_type" config option
If you used:

    "implicit_content_type": "form"

 You can achieve the the same result with:

     "default_options": ["--form"]

If you used:

    "implicit_content_type": "json"

 Then it's the default behaviour and it can be removed.

 In either case HTTPie will migrate your config file on the next invocation.
2016-03-03 17:14:39 +08:00
5dbd104c3b Nobody ain't got time for that 2016-03-03 17:09:34 +08:00
13a979ad11 Cleanup 2016-03-02 14:20:35 +08:00
4cfa143bfe Fixed coverage 2016-03-02 13:31:40 +08:00
d24f30d0af Cleanup 2016-03-02 13:31:23 +08:00
66e168b2af Improved failed test output 2016-03-02 13:16:41 +08:00
564670566c Fix coveralls integration 2016-03-02 12:25:19 +08:00
ecbbad816a Fix coveralls integration 2016-03-02 12:24:46 +08:00
0432694661 Changel 2016-03-02 12:24:24 +08:00
dc4da527db Added --ssl=<PROTOCOL_VERSION>
Closes #98
2016-03-02 12:12:05 +08:00
38e8ef14ec Run positive tests first
Trying to debug failing SSL tests on Travis - kevin1024/pytest-httpbin#32
2016-03-02 10:35:40 +08:00
c73dcaf63d CI 2016-03-02 10:08:20 +08:00
fb85509e91 CI 2016-03-02 09:58:50 +08:00
a2dca1e3bb CI 2016-03-02 09:44:39 +08:00
c2dae62af0 Appveyor: added Python 3.5 build 2016-03-02 09:37:58 +08:00
ae7008ee96 Appveyor 2016-03-02 09:33:43 +08:00
f6824f7ade Cleanup 2016-03-02 02:53:23 +08:00
7fd46e0b0d Cleanup 2016-03-02 01:02:11 +08:00
d4067fcb6d Added a short timeout for test requests 2016-03-02 00:31:00 +08:00
20f01709ea Mention URL escaping
Closes #311
2016-03-01 23:48:13 +08:00
56afd1adb9 Test suite cleanup 2016-03-01 23:22:50 +08:00
5e87a2d7e5 Cleanup 2016-03-01 23:13:45 +08:00
d30e28c2c7 Test suite improvements 2016-03-01 23:11:06 +08:00
0d2d24eac7 Copy 2016-03-01 21:37:26 +08:00
e2751e5fa3 Fixed args for Python 2.x 2016-03-01 21:28:10 +08:00
2a25d71aa4 Refactored main() into program() + main() 2016-03-01 21:10:54 +08:00
01ca7f0eb2 Ignore redirected stdout with --output, -o
This makes it easier to use HTTPie in cron jobs and scripts.

Closes #259
2016-03-01 20:24:50 +08:00
4f8d6c013b Fixed get_lexer() 2016-03-01 16:55:12 +08:00
e83e554ffb README 2016-03-01 16:50:30 +08:00
345f5a02a2 Fixed json absolute import 2016-03-01 16:39:50 +08:00
f96f0ef9ed JSON detection improvements 2016-03-01 16:22:54 +08:00
74e4d0b678 Added JSON detection when `--json, -j` is set
To correctly format JSON responses even when an incorrect ``Content-Type`` is returned.

Closes #92
Closes #349
Closes #368
2016-03-01 14:57:15 +08:00
0fc1f61f3d Fixed README 2016-03-01 00:45:54 +08:00
c50413a9c1 Added support section 2016-03-01 00:24:52 +08:00
9f8c452e7e Added gitter chat 2016-03-01 00:12:55 +08:00
776328c818 Added gitter chat 2016-03-01 00:08:07 +08:00
9312fabc01 Capitalization II 2016-02-29 22:03:08 +08:00
48ce934dfa Capitalization 2016-02-29 22:01:05 +08:00
3625bb6fa1 Updated travis badge title 2016-02-29 22:00:18 +08:00
a97f0d52f6 Travis 2016-02-29 17:20:50 +08:00
41b0286f37 Travis 2016-02-29 17:19:12 +08:00
fee54b04d8 Travis 2016-02-29 17:09:55 +08:00
73e0455896 Travis 2016-02-29 16:52:33 +08:00
3b217daddc Travis 2016-02-29 16:43:18 +08:00
e5e5d0ce6d Travis 2016-02-29 16:36:25 +08:00
f43e473de1 Travis 2016-02-29 16:35:09 +08:00
0a002ec554 Fix travis 2016-02-29 15:38:59 +08:00
576ee83d82 Fix travis 2016-02-29 15:35:56 +08:00
e42f7b8fc9 OSX build 2016-02-29 15:32:10 +08:00
b44e16ed0f Fix appveyor 2016-02-29 15:14:43 +08:00
ed08ab133e Refactoring 2016-02-29 15:00:17 +08:00
5408fb0fb9 Cleanup 2016-02-29 14:31:27 +08:00
e18b609ef7 Fixed --max-redirects 2016-02-29 14:21:25 +08:00
356e043651 Added --show-redirects and --max-redirects
Closes #157, #183, #188, #246
2016-02-29 14:12:09 +08:00
c6d4f6cdf6 Show redirects WIP 2016-02-29 14:07:08 +08:00
dc1371d4d6 Implemented --max-redirects option
Added argument to argparse, changed client so that it uses a new
requests Session() with the number of redirects and a single test to
show the setting works.
2016-02-29 14:07:08 +08:00
e2235e56dc Update CHANGELOG.rst 2016-02-29 02:38:09 +08:00
763935b77f Update CHANGELOG.rst 2016-02-29 02:37:36 +08:00
6435532f72 Updated CHANGELOG 2016-02-28 21:37:49 +08:00
11a37067e7 Document -A as a short name for --auth-type 2016-02-28 21:01:21 +08:00
25f0156502 Merge pull request #432 from hangtwenty/master
Add `-A` as short arg for `--auth-type`
2016-02-28 20:58:23 +08:00
0f8d04b4df More robust mime type parsing
Closes #344
2016-02-28 20:12:16 +08:00
e385ed6a99 Fix README 2016-02-28 19:32:19 +08:00
01fdab55e9 Explain how to send fieldnames and headers starting with '-'
Closes #355
2016-02-28 19:31:43 +08:00
1127557742 Cleanup 2016-02-28 19:15:35 +08:00
5898879395 Fixed --download with --session
Closes #412
2016-02-28 19:14:10 +08:00
8c33e5e3d3 Parser => HTTPieArgumentParser 2016-02-28 19:01:54 +08:00
10da7b63a3 Mention MacPorts installation method
Closes #395
2016-02-28 16:54:33 +08:00
df193a373f Updated tarball URL 2016-02-28 16:20:19 +08:00
c2f8c36952 Updated download example URLs 2016-02-28 16:19:18 +08:00
56f498c153 Detect Content Type of file uploaded in multipart/form-data request
Closes #271 #285 #398

This adds filename-based detection. It's still not possible to specify the
content type manually, though.
2016-02-28 15:49:01 +08:00
59e22b16b8 When possible, guess the content-type of the file being sent
Refined PR #285 by rasky to pass all tests
2016-02-28 15:47:43 +08:00
d32d6f29a9 Typo 2016-02-17 14:53:00 +08:00
274dddfb45 Changed the default color style back to solarized
Closes #440
2016-02-17 14:46:35 +08:00
deb7b747cc Small fix for Python 2.6 compatibility.
Relates to #430 / #432.
2016-01-22 18:46:36 -06:00
018e1f68de Merge remote-tracking branch 'upstream/master' 2016-01-22 18:40:53 -06:00
ac69d4311b add -A as short arg for --auth-type
Addresses #430
comes with unit test
2016-01-22 18:37:30 -06:00
c75c4fa2a6 Merge pull request #429 from pra85/patch-1
Update license year range to 2016
2016-01-18 11:26:27 -03:00
a6a79e92e4 Update license year range to 2016 2016-01-18 11:20:24 +05:30
ea76542150 Added guardian/httpie-hmac-auth 2016-01-15 14:07:41 -03:00
c6690e0182 Makefile improvements 2016-01-02 14:33:48 -03:00
c82c9f0ae4 Makefile improvements 2016-01-02 14:28:46 -03:00
84b81c00ea Fixed tox.ini and improved tests and CONTRIBUTING.txt 2016-01-02 14:07:00 -03:00
34c6958dc8 1.0.0-dev 2016-01-01 19:38:21 -03:00
4722076335 v0.9.3 2016-01-01 19:27:07 -03:00
f14a0ad37d Fix pytest configuration 2016-01-01 19:11:22 -03:00
4cadc1d4c0 Update pytest configuration
* Move it from tox.ini to pytest.ini
* Ignore tests/fixtures
2016-01-01 19:08:27 -03:00
c3e5456aba Update setuptools on Appveyor 2016-01-01 19:01:39 -03:00
33489c9a91 Update pip on Appveyor 2016-01-01 18:51:17 -03:00
4e2b6b0ccc Update get-pip.py URL 2016-01-01 18:46:01 -03:00
b034c8703a PEP8 2016-01-01 18:41:58 -03:00
ab3d2656af Undo 'Fix "mock requires setuptools>=17.1. Aborting installation" on Win+Py3' 2016-01-01 18:38:06 -03:00
c42bd0051a Merge pull request #396 from pathcl/master
PEP8 errors
2016-01-01 18:37:49 -03:00
288cb4fdeb Fix "mock requires setuptools>=17.1. Aborting installation" on Win+Py3 2016-01-01 18:27:43 -03:00
8771d759fe Merge pull request #382 from konopski/master
[#381] Fixed --auth prompt on Windows
2016-01-01 18:18:23 -03:00
2cdca36960 Merge pull request #386 from honorabrutroll/dev
Fixed --pretty on Windows (closes #372)
2016-01-01 18:15:50 -03:00
8dc4f04fda Merge pull request #419 from hangtwenty/master
Fail gracefully if disable_warnings not available
2016-01-01 17:58:23 -03:00
dadc0cd27c Merge pull request #417 from yansal/patch-1
Fix typo in CONTRIBUTING.rst
2016-01-01 17:57:48 -03:00
59fd42244a Merge pull request #421 from Altreus/patch-1
Aitch already has an official spelling - use it
2016-01-01 17:56:52 -03:00
6afe9c32c4 Merge pull request #424 from t-mart/master
Remove duplicate setup.py test option
2015-12-28 13:56:14 -03:00
cc0ba03290 Remove duplicate setup.py test option 2015-12-28 10:38:07 -06:00
fad84a962e Aitch already has an official spelling - use it
http://www.oxforddictionaries.com/definition/english/aitch
2015-12-15 14:39:26 +00:00
4f755a8bde Fail gracefully if disable_warnings not available
Addresses #418. Rationale explained there.
2015-12-02 11:50:48 -06:00
21ee981fc6 Fix typo in CONTRIBUTING.rst 2015-11-27 15:02:23 +01:00
6259b5dd3b Add a --default-scheme argument. 2015-10-28 15:06:04 -07:00
45df860124 PEP8 errors 2015-10-22 14:32:16 -03:00
277da1ff93 str conversion 2015-10-21 21:57:06 +02:00
1ded5c2a97 Merge pull request #387 from yurimalheiros/patch-1
Update README.rst
2015-10-07 19:41:24 +02:00
69bd72ce95 Update README.rst
Fix a simple typo
2015-10-07 14:17:53 -03:00
8bf6db471b Fixed AUTHORS.rst 2015-10-04 17:16:41 -05:00
b1cc069fce Add Edward Yang to AUTHORS.rst 2015-10-04 17:06:54 -05:00
ed484c278b Change pretty option processor to only raise error when using output file 2015-10-04 17:06:00 -05:00
aec0f04f5d [#381] --auth fails on windows 2015-09-21 16:30:46 +02:00
8eb460a6f3 Disable OSX travis builds for now
OSX/Python support isn't probably not ready on Travis' side yet. 

https://travis-ci.org/jkbrzt/httpie/jobs/78219565#L27

// cc @msabramo — any idea?
2015-09-11 16:24:42 +02:00
5fe5958b06 Update README.rst 2015-09-01 15:11:36 +02:00
0e1c17daa1 Merge pull request #375 from hoatle/jwt-auth-plugin-reference
mention httpie-jwt-auth plugin on README
2015-09-01 15:10:41 +02:00
307517e7ef Merge pull request #377 from mblayman/fix-trasnsport
Fix trasnsport typo in plugin manager.
2015-08-31 06:20:01 +02:00
d60a04da2d Add Matt Layman to AUTHORS. 2015-08-30 21:41:14 -04:00
9ea89ffefe Fix typo in method name of plugin manager. 2015-08-30 21:37:47 -04:00
bebeb2100d mention httpie-jwt-auth plugin on README 2015-08-24 01:58:00 +07:00
2b51cb6687 Updated links II. 2015-07-03 18:55:45 +02:00
fa4bd033ef Updated links. 2015-07-03 03:40:38 +02:00
f8c1104429 Fixed link to httpie-edgegrid 2015-06-30 11:51:40 +02:00
be9d9281b7 Added a link to the httpie-edgegrid plugin. 2015-06-30 11:50:11 +02:00
ced0838598 Converted tabs to spaces. 2015-06-26 16:39:23 +02:00
d8b819b03f Merge pull request #337 from joaodelgado/json-serialization
Only serialize json if data is a dict instance
2015-04-24 15:07:16 +02:00
6fd0f23f39 Only serialize json if data is a dict instance 2015-04-11 02:11:22 +01:00
483546d781 Added mock to tests_require 2015-03-25 22:52:49 +01:00
daf3573908 Update CHANGELOG.rst 2015-03-25 22:37:48 +01:00
62407f781f Update CHANGELOG.rst 2015-03-25 22:35:36 +01:00
cbbaac13ea Merge pull request #300 from msabramo/print_info_about_request_on_error
Print info about request on error
2015-03-25 22:21:18 +01:00
6aad79d71c Merge pull request #319 from fay-jai/license
Update license with up-to-date year
2015-03-25 22:18:42 +01:00
c1f26347fc Merge pull request #330 from mihirvj/bash-completion
Bash auto completion
2015-03-25 22:08:13 +01:00
29a0147dd5 See #326
Adds bash completion to http command line interface.

Installing the script:
You can copy it to /etc/bash_completion.d/ (or something else on your
machine) and source it using following command

	$ source /etc/profile

Now whenever you encounter a "-*" on your CLI, it presents you with the
options specified.

Couple of things that are still under work:
1) Adding this bash script to setup, so that user won't need manual
installation
2) Adding more options for HTTP (GET, PUT and so on) and other
options
2015-03-24 22:26:10 -04:00
ab0d1fd8d0 Added .editorconfig. 2015-03-13 17:17:17 +01:00
35a3dd2855 Merge pull request #321 from ifdattic/patch-1
Fix typos, improve readability
2015-03-10 09:37:40 +01:00
ece85c0f0c Fix typos, improve readability 2015-03-10 10:05:13 +02:00
798cd4f0ec Update license with up-to-date year 2015-03-08 11:29:33 -07:00
1a43c0e5f7 Fixed --debug output 2015-02-28 17:02:05 +01:00
fdabbc6048 Typo 2015-02-24 16:50:02 +01:00
5f3de558cb README 2015-02-24 16:41:34 +01:00
fdae686e12 Clean up compat and fix is_pypy. 2015-02-24 08:18:03 +01:00
1c181a5d25 1.0.0-dev 2015-02-24 07:52:34 +01:00
a228399801 0.9.2 2015-02-24 07:50:15 +01:00
bada3b45f1 Use absolute links to LICENCE, etc. 2015-02-24 07:50:15 +01:00
e4bc363f9e Don't depend on requests.compat
#314
2015-02-24 07:50:15 +01:00
24957e3b61 Update requirements-dev.txt
dd7f1c4
2015-02-16 21:55:40 +01:00
fb437591da Include AUTHORS.rst in dist; metadata cleanup 2015-02-16 21:42:09 +01:00
b7fc89acdc README fixes 2015-02-16 21:29:40 +01:00
2e88aa53cf Extracted changes from README into a proper CHANGELOG file
Inspired by keepachangelog.com
2015-02-16 21:16:39 +01:00
9e62151bec Merge pull request #312 from msabramo/patch-5
tox.ini: Use pytest-httpbin>=0.0.6
2015-02-16 20:27:35 +01:00
ecc59591f1 Disable urllib3's "Unverified HTTPS request is being made" warnings 2015-02-16 19:36:02 +01:00
f855de16c2 Increase test coverage for error handling 2015-02-15 23:22:52 -08:00
7f8adad313 Print info about request on error
This can help in diagnosing certain issues. For example, if I were
trying to use a "http+unix" URL but I don't have #299, then I'll get the
following:

    [marca@marca-mac2 httpie]$ http http+unix://%2Ftmp%2Fprofilesvc.sock/status/pid

    http: error: ConnectionError: ('Connection aborted.', gaierror(8, 'nodename nor servname provided, or not known'))
    while doing GET request to URL: http://http+unix//%2Ftmp%2Fprofilesvc.sock/status/pid

Having the URL in the error message is super useful here so that I know an
extra `http://` is getting prepended and it's not doing what I expected.
2015-02-15 23:22:52 -08:00
51c19cfe10 test_ssl.py: Remove skip failures on PyPy
Revert 985f65e which skipped SSL tests that failed on PyPy because @kevin1024 fixed the problem in pytest-httpbin 0.0.6 (commit f38a312446)
2015-02-15 21:42:34 -08:00
dd7f1c4cce tox.ini: Use pytest-httpbin>=0.0.6
This hopefully fixes SSL timeout errors. 

Fixes #308
2015-02-15 20:33:57 -08:00
45784c7260 Fixed TOC 2015-02-15 12:57:57 +01:00
868baaba4e README 2015-02-15 12:53:57 +01:00
5760b780a0 README 2015-02-15 11:28:53 +01:00
2e5d14238f Tweak badge style 2015-02-15 00:54:49 +01:00
3b3eff01b7 Use shields.io badges 2015-02-15 00:51:58 +01:00
42f454eb6b README 2015-02-15 00:43:24 +01:00
40d95b650c README 2015-02-15 00:42:41 +01:00
bc0d17c04c Added a PyPy incompatibility workaround. 2015-02-15 00:36:55 +01:00
985f65ef52 Temporarily skip SSL tests on PyPy due to #308 2015-02-14 23:14:06 +01:00
dd0a4ab87a Default --style to "monokai"
419ca85
2015-02-14 22:51:31 +01:00
07aaefa232 Updated screenshot 2015-02-14 18:18:43 +01:00
419ca85e62 The default color --style is now "fruity"
It's experimental - please let me know should you dislike this change.

To make Solarized default again, add this to your ~/.config.json:

  "default_options": [
    "--style=solarized"
  ],
2015-02-14 18:18:04 +01:00
596fdc8c7e Update README examples with the new default Accept-Encoding value used by Requests. 2015-02-14 17:55:34 +01:00
6e7e2f2eea Changed the default JSON Content-Type to application/json. 2015-02-14 17:45:15 +01:00
748794257c Merge pull request #306 from msabramo/patch-4
.travis.yml: sudo false for Docker containers
2015-02-10 17:41:32 +01:00
55fa975ae5 .travis.yml: sudo false for Docker containers
Enables new Docker container infrastructure.
2015-02-10 07:41:38 -08:00
e6e94398ae Merge pull request #303 from msabramo/coveralls_only_one
.travis.yml: Only do coveralls on the latest Python version
2015-02-10 16:38:54 +01:00
fbd44640e6 .travis.yml: Only do coveralls on newest python
Testing theory that it has to do with different python version subjobs
completing in different orders and the last one wins.
2015-02-10 07:37:03 -08:00
43915b5fc0 Merge pull request #304 from msabramo/patch-2
compat.py: Add pragma no covers
2015-02-10 16:00:59 +01:00
f1e1299104 Merge pull request #305 from msabramo/patch-3
Conditionally skip test_session_unicode on Py3k
2015-02-10 16:00:24 +01:00
86ebb9b741 compat.py: Add pragma no covers
Cuz this is a lot of version-specific stuff and it can be confusing to have different coverage per version, especially with coveralls.
2015-02-10 06:54:59 -08:00
873102d5eb Mark test_session_unicode as xfail
There are known problems with unicode in headers.
See https://github.com/jakubroztocil/httpie/issues/282
2015-02-10 06:52:51 -08:00
337c05f95c README 2015-02-07 18:06:49 +01:00
a786f17997 1.0.0-dev 2015-02-07 17:04:33 +01:00
753a8d04e4 v0.9.1 2015-02-07 17:04:13 +01:00
3ff03524ff HTTP/2 has no minor versions.
https://github.com/jakubroztocil/httpie-http2/issues/1
2015-02-07 16:31:42 +01:00
a5a83c5b77 Prevent a circular import issue. 2015-02-07 16:29:17 +01:00
9682f955b5 Handle HTTP/2 responses
https://github.com/jakubroztocil/httpie-http2/issues/1#issuecomment-73301801
2015-02-06 21:13:57 +01:00
0d21ff022e Added a link to @pd's httpie-api-auth plugin 2015-02-06 20:06:50 +01:00
996e314482 Cleanup 2015-02-05 15:55:20 +01:00
687a6a734d Added support for transport adapter plugins
#276, #298
2015-02-05 15:25:00 +01:00
b125ce5eae Allow custom URL schemes
Closes #299

See also #276
2015-02-05 14:35:34 +01:00
92a4352f10 Added a coveralls badge. 2015-01-31 17:49:48 +01:00
c0f1fb61ac Merge pull request #297 from msabramo/patch-1
README.rst: suppor => support
2015-01-31 16:15:42 +01:00
17358be1ae README.rst: suppor => support 2015-01-31 07:01:54 -08:00
338d39c841 Fixed version link 2015-01-31 13:23:52 +01:00
530d6c5e27 1.0.0-dev 2015-01-31 13:22:17 +01:00
6c66d91f59 v0.0.9 2015-01-31 13:21:45 +01:00
ed6485498b README 2015-01-24 00:41:22 +01:00
59b6020105 Extended SSL documentation. 2015-01-24 00:22:31 +01:00
12f2d99bfd Added test client SSL certs 2015-01-23 23:56:08 +01:00
5fbafc18bc Added tests for client as well as server SSL certificate handling. 2015-01-23 23:55:03 +01:00
df07927843 --certkey is now --cert-key 2015-01-23 23:54:27 +01:00
d3d78afb6a Pypy3 (2.4.0) curses bug workaround. 2015-01-23 22:19:02 +01:00
25b1be7c8a Work around missing object_pairs_hook in Python 2.6 2015-01-23 22:04:42 +01:00
22c993bab8 Merge branch 'fix-268' of https://github.com/asnelzin/httpie into asnelzin-fix-268 2015-01-23 21:45:09 +01:00
b2ec4f797f Exit with 0 for --version and --help (closes #293). 2015-01-19 15:39:46 +01:00
a2b12f75ea Fixed and added test for JSON properties order. 2014-11-13 23:56:05 +03:00
0481957715 Fixed multiple uploads with the same field name
Closes #267
2014-10-20 14:41:48 +02:00
c301305a59 Cleanup. 2014-10-20 14:41:48 +02:00
2078ece95a Cleanup 2014-10-20 14:41:48 +02:00
43f7b84a1e Merge pull request #260 from brakhane/master
Fallback to JSON highlighting if subtype contains json
2014-09-25 06:27:17 +02:00
f1cd289d51 Fallback to JSON highlighting if subtype contains json
Some JSON based formats like JSON Home Documents[1] don't
use a '+json' suffix, but simply contain json in their
MIME type. Also, some servers might use (outdated)
types like 'application/x-json'.

The JSON formatter can already handle those cases,
but the highlighter was ignoring them.

This commit will let the highlighter choose the JSON
lexer if no other lexer could be found and the MIME subtype
contains 'json'

[1] http://tools.ietf.org/html/draft-nottingham-json-home-03
2014-09-25 00:10:06 +02:00
24f46ff3ef Changelog 2014-09-08 07:50:41 +02:00
afe521ef73 Merge remote-tracking branch 'origin/master' 2014-09-08 07:47:55 +02:00
58b51a8277 Improved terminal color depth detection via curses
Closes #244
2014-09-08 07:46:53 +02:00
6aa711c69f Removed pytest-xdist
The test suite is much less IO-bound now with the local httpbin
instance (via pytest-httpbin). Therefore, paralelization is not
as helpful.
2014-09-08 07:44:25 +02:00
d2d1023921 Merge pull request #249 from frewsxcv/patch-1
Enable testing on PyPy 3
2014-09-07 10:45:29 +02:00
b0effe07d9 Fixed --output=/dev/null on Linux
Closes #252
2014-09-07 10:22:21 +02:00
af873effb6 Changelog typo. 2014-09-05 18:40:28 +02:00
5084f18568 '\' only escapes separator characters in req-items
It makes easier to work with Windows paths.

Closes #253, #254
2014-09-05 18:36:23 +02:00
1035710956 Added RequestItems named tuple for convenience. 2014-09-05 07:51:35 +02:00
5d2b3f5552 Enable testing on PyPy 3 2014-08-15 00:03:27 -07:00
ca36f1de04 Handle empty passwords in URL credentials
Closes #242
2014-07-18 13:39:47 +02:00
0f96348fd1 Cleanup 2014-07-18 13:39:47 +02:00
2fd84ec1da Merge pull request #241 from ametaireau/patch-1
Add the hawk auth plugin
2014-07-17 07:58:08 +02:00
e3c83fca6f Add the hawk plugin 2014-07-17 00:48:56 +02:00
529f3bd9b6 Fixed python setup.py test 2014-06-28 19:52:10 +02:00
2a72ae23d5 Run tests against local httpbin instance via pytest-httpbin. 2014-06-28 16:38:41 +02:00
79329ed1c6 Mention "brew install httpie --HEAD". 2014-06-28 13:26:48 +02:00
040d981f00 Fixed custom Host
Closes #235
2014-06-28 13:24:14 +02:00
8c892edd4f PEP8 2014-06-28 13:09:04 +02:00
a02a1eb562 Fixed README formatting 2014-06-24 17:27:01 +02:00
5e556612d9 Added $ brew install httpie to README
https://twitter.com/jakubroztocil/status/481453834024550400

Thanks @insomniacslk!
2014-06-24 17:25:29 +02:00
f5904d92c3 Merge pull request #225 from rockymeza/docs_grep_fix
Fixed the order of args to grep in README.
2014-06-15 16:35:19 +02:00
541c75ed5c Fixed the order of args to grep in README. 2014-06-15 08:14:37 -06:00
8e170b059c Fixed tests. 2014-06-03 19:45:57 +02:00
b44bc0928f Merge pull request #222 from felixbuenemann/patch-1
Add info about SNI on Python 2.x to README
2014-05-26 15:37:11 +02:00
f283de6968 Add info about SNI on Python 2.x to README
This updates the HTTPS section of the README with instructions on how to get SNI working on Python 2.x.
2014-05-26 15:31:16 +02:00
77955c9837 Fixed --timeout
* Require requests >= 2.3.0
* Updated test_timeout_exit_status

Close #185.
2014-05-17 22:33:16 +02:00
4449da456a Merge pull request #220 from frewsxcv/patch-1
Add supported, relevant Python version classifers
2014-05-14 14:24:30 +02:00
f9b5b3a65d Added OSX to Travis CI config. 2014-05-14 14:00:26 +02:00
10f7fc163b Add supported, relevant Python version classifers 2014-05-12 17:36:09 -07:00
5743363ac9 Merge branch 'master' of github.com:jkbr/httpie 2014-05-12 19:16:15 +02:00
7036ec69ff Enable testing on Python 3.4 2014-05-12 19:16:04 +02:00
02c66e14df Update CONTRIBUTING.rst 2014-05-12 19:16:04 +02:00
ea8132b3d6 Update CONTRIBUTING.rst 2014-05-12 19:16:04 +02:00
e4c68063b9 Converted built-in formatters to formatter plugins.
Still work in progress and the API should be considered private for now.
2014-05-12 19:12:39 +02:00
9c2207844e Merge pull request #219 from frewsxcv/patch-1
Enable testing on Python 3.4
2014-05-12 08:02:17 +02:00
b51775bb06 Enable testing on Python 3.4 2014-05-11 20:09:47 -07:00
f26272f83f Update CONTRIBUTING.rst 2014-05-09 12:48:34 +01:00
81518f9315 Update CONTRIBUTING.rst 2014-05-09 12:46:33 +01:00
858555abb5 Make sure session and default headers play nice
Before: headers = default + args + session
Now:    headers = default + session + args

Fixes #180
2014-05-08 12:27:50 +01:00
3e1b62fb20 Fixed .rst syntax. 2014-05-05 21:17:41 +02:00
d9eca19b8f New URL. 2014-05-05 21:17:23 +02:00
5a989b6075 Fixed Makefile, added setup.cfg. 2014-04-28 13:27:02 +02:00
29a564ef56 Added wheel support
Should make installation via pip work on OSX Mavericks (#148).

Also added a nifty Makefile.
2014-04-28 13:25:47 +02:00
2aa53e4be3 Avoid “__init__.py” files in test directories.
As recommended here:

	https://pytest.org/latest/goodpractises.html
2014-04-28 11:29:41 +02:00
faec00fd99 Improve support for 'type/subtype+suffix' mime types in the colors output formatter.
E.g.:
* application/ld+json
* application/hal+json

Closes #189, #206
2014-04-28 10:08:03 +02:00
76ab8b84be Cleanup 2014-04-28 10:01:56 +02:00
14763e619d Travis coveralls. 2014-04-28 01:05:03 +02:00
0e6875bf83 Handle HTTP 0.9 in response when formatting version.
Closes #170
2014-04-28 00:08:20 +02:00
bd50a6adb1 Moved .directory from BaseConfigDict to Config.
Closes #200
2014-04-27 23:12:48 +02:00
f67a11c165 Debug appveyor 2014-04-27 22:20:23 +02:00
64b9a86c52 Debug appveyor 2014-04-27 22:15:21 +02:00
c8ae697eec Python 3.4 @ appveyor. 2014-04-27 22:14:11 +02:00
82e16c4f27 Debug appveyor 2014-04-27 22:10:24 +02:00
05db75bdb1 Modularized output, refactoring
Making it ready for output formatting plugin API.
2014-04-27 21:58:00 +02:00
c06598a0c4 Cleanup 2014-04-27 18:27:44 +02:00
18f3700b77 Fix appveyor.yml V. 2014-04-27 17:54:30 +02:00
d05063f019 Fix appveyor.yml IV. 2014-04-27 17:52:04 +02:00
7c3f8c021e Fix appveyor.yml III. 2014-04-27 17:50:54 +02:00
a95d8bb42d Fix appveyor.yml 2014-04-27 17:46:19 +02:00
411822d3b2 Fix appveyor.yml 2014-04-27 17:45:23 +02:00
bae8519e29 Python3.3 Windows CI 2014-04-27 17:38:12 +02:00
87806acc56 Cleanup 2014-04-26 23:06:39 +02:00
1169a3eb23 Fixed tests. 2014-04-26 20:14:46 +02:00
43bc6d0c98 Fixed and added tests for --verbose with unicode headers. 2014-04-26 20:10:15 +02:00
eca1ffaedb More unicode. 2014-04-26 19:47:14 +02:00
0bd218eab0 Cleanup 2014-04-26 19:32:08 +02:00
609950f327 Updated Travis icon URL. 2014-04-26 18:48:57 +02:00
bbc820bf2e Fixed fixture loading on Windows. 2014-04-26 18:41:28 +02:00
84a521a827 Added test_unicode_url_query_arg_item. 2014-04-26 18:23:13 +02:00
a3352af1d4 Added support and tests for unicode support in sessions. 2014-04-26 18:16:30 +02:00
e8a1c051f9 Changelog 2014-04-26 17:53:35 +02:00
3478cbd9ff More unicode tests. 2014-04-26 17:53:01 +02:00
77dcd6e919 Added unicode characters to json fixture. 2014-04-26 17:37:56 +02:00
467d126b6c Python 3 unicode fixes. 2014-04-26 17:35:26 +02:00
8ec32fe7f3 Fix tox config. 2014-04-26 16:50:31 +02:00
282cc455e3 Avoid "TypeError: keyword arguments must be strings" on Python 3.3. 2014-04-26 15:18:38 +02:00
56d33a8e51 Fix Windows branch. 2014-04-26 15:10:39 +02:00
15e62ad26d Implemented more robust unicode handling.
* Immediatelly convert all args from `bytes` to `str`.
* Added `Environment.stdin_encoding` and `Environment.stdout_encoding`
* Allow unicode characters in HTTP headers and basic auth credentials
  by encoding them using UTF8 instead of latin1 (#212).
2014-04-26 15:07:31 +02:00
5c29a4e551 Added windows build status icon to README. 2014-04-26 11:32:41 +02:00
0c45c7cb39 Disabled test_windows_colorized_output 2014-04-26 11:06:50 +02:00
8158fa8c45 Run tests in verbose mode. 2014-04-26 11:03:53 +02:00
5065c4f878 Updated appveyor.yml 2014-04-26 11:01:02 +02:00
e3af74da46 Don't used pytest-xdist with setup.py test 2014-04-26 10:59:46 +02:00
5c3d24ec09 Updated appveyor.yml 2014-04-26 10:49:40 +02:00
091a8b2692 Updated appveyor.yml 2014-04-26 10:46:08 +02:00
95a0884f95 Updated appveyor.yml 2014-04-26 10:41:57 +02:00
8fb1e106ee Updated appveyor.yml 2014-04-26 10:36:12 +02:00
78c83da721 Updated appveyor.yml 2014-04-26 10:33:13 +02:00
aeccac5cbd Updated appveyor.yml 2014-04-26 10:28:16 +02:00
e2dabbfaf7 Updated appveyor.yml 2014-04-26 10:26:29 +02:00
272e66bf37 Updated appveyor.yml 2014-04-26 10:22:17 +02:00
4a0d387f86 Updated appveyor.yml 2014-04-26 10:20:45 +02:00
6a86164510 Updated appveyor.yml 2014-04-26 10:14:57 +02:00
e1348da118 Updated appveyor.yml 2014-04-26 10:13:31 +02:00
0e1b651a1c Added appveyor.yml 2014-04-26 10:07:35 +02:00
631e332dad Cleanup 2014-04-25 13:57:33 +02:00
33422312c5 Cleanup 2014-04-25 13:52:43 +02:00
1d987c5b4d Improved session tests. 2014-04-25 13:50:44 +02:00
3c2de34285 Improved auth tests. 2014-04-25 13:10:01 +02:00
b10d973019 Removed unused import. 2014-04-25 12:53:02 +02:00
492ee392bd Cleanup 2014-04-25 12:42:50 +02:00
af4aa3a761 Test improvements. 2014-04-25 12:18:35 +02:00
27faf06327 Removed last dependencies on unittest. All tests are pytest-only. 2014-04-25 11:39:59 +02:00
f658d24c93 Parametrize test_docs.py. 2014-04-25 10:41:04 +02:00
ea42d32f69 Travis doesn't support Python 3.4 yet. 2014-04-25 09:47:35 +02:00
3f63133b7c Parallelized tests using pytest-xdist. 2014-04-24 21:36:03 +02:00
3f8a000847 Python 3.4 2014-04-24 20:08:28 +02:00
f02169ea71 Added Python 2.6 compatible OrderedDict
To preserver ordr of headers, parameters, etc.
2014-04-24 19:57:19 +02:00
e5d758e4ce More tests. 2014-04-24 19:32:55 +02:00
ce2169f4fe Added docstrings for utilities in tests.__init__. 2014-04-24 19:32:55 +02:00
bdea7be456 Added tests for --debug and --help. 2014-04-24 19:32:55 +02:00
887f70f595 Added CONTRIBUTING.rst. 2014-04-24 19:32:55 +02:00
3d079942f4 Finished pytest migration. 2014-04-24 19:32:55 +02:00
3cb124bba7 Cleanup
XX
2014-04-24 19:32:50 +02:00
6f28624134 Switched to @pytest.mark.skipif. 2014-04-24 15:17:23 +02:00
941c0a8c3c Moved fixture constants to tests.fixtures. 2014-04-24 15:17:04 +02:00
b880e996d0 Converted all unittest asserts to plain, pytest-powered asserts. 2014-04-24 14:58:15 +02:00
6071fff4af Refactored tests into smaller modules. 2014-04-24 14:07:31 +02:00
746a1899f3 Skip ExitStatusTest.test_timeout_exit_status until timeout gets fixed in requests. 2014-03-31 13:01:55 +02:00
bbbae3ae25 Fixed SessionTest.test_session_read_only. 2014-03-31 13:01:55 +02:00
e62620d4ad Merge pull request #208 from insyte/master
Update README.rst with pronunciation.
2014-03-25 10:19:32 +01:00
a2918d877d Update README.rst 2014-03-24 18:03:59 -05:00
733771fd9e Merge pull request #172 from unsignedint/master
process XML data before pretty-printing to trim whitespace
2014-03-18 19:44:16 +01:00
76ab6e49d5 Updated installation instructions. 2014-03-04 18:44:31 +01:00
c33775e785 Updated installation instructions. 2014-03-04 18:42:33 +01:00
09810d55ba Updated installation instructions. 2014-03-04 18:36:22 +01:00
29877bc8ad Updated installation instructions. 2014-03-04 18:24:32 +01:00
af6bda11af Removed Bitdeli badge. 2014-02-18 14:09:50 +01:00
b01906a45c Fixed ZeroDivisionError in download summary.
Closes #202
2014-02-18 13:06:18 +01:00
2c885b0981 Merge pull request #197 from matleh/master
add support for client SSL certificate and key
2014-02-12 14:46:59 +01:00
b3a34aba44 added --cert to CHANGELOG and matleh to AUTHORS 2014-02-12 11:23:31 +01:00
dd7197c60b document --cert and --certkey 2014-02-05 12:51:05 +01:00
a3aae12d9c rename -ssl-cert and --ssl-key to --cert and --certkey 2014-02-05 12:50:40 +01:00
d4363a560d rename existing_file to readable_file_arg and move to input 2014-01-29 18:02:06 +01:00
b9d7220b10 check --ssl-cert and --ssl-key to be files 2014-01-29 15:54:19 +01:00
14583a2efa add support for client SSL certificate and key 2014-01-28 16:16:48 +01:00
43cc3e7ddb Fixed changelog link. 2014-01-25 15:15:16 +01:00
f1224da526 v0.8.0 2014-01-25 15:11:38 +01:00
e0cc63c7eb Cleanup 2014-01-25 15:09:28 +01:00
52dd6adaa3 Updated README. 2014-01-25 15:04:15 +01:00
1aa77017d5 Catch UnicodeDecodeError when embedding file via =@ or :=@. 2014-01-25 14:57:19 +01:00
748a0a480d Update README.rst 2014-01-17 08:57:05 +01:00
01df344a07 Update README.rst 2014-01-17 08:56:24 +01:00
b1074ccb4f Merge pull request #191 from solidsnack/wip-no-auth-in-host-header
Expunge user:pass@... from Host header.
2014-01-08 02:28:19 -08:00
7a84163d1c Merge pull request #192 from thomasleveil/patch-1
fix typo
2014-01-08 02:27:29 -08:00
a31d552d1c fix typo 2014-01-07 14:04:13 +01:00
5a037b2e13 Expunge user:pass@... from Host header.
In verbose mode, the basic auth user and password would show up in colored
output reporting the Host header, as reported in
https://github.com/jkbr/httpie/issues/169
2014-01-06 19:12:33 +00:00
6af42b1827 Added Bitdeli badge. 2013-12-08 11:38:26 +01:00
bee10e5eed replace XML processor with ElementTree with custom indentation 2013-10-16 13:07:53 +13:00
bcdf194bae process XML data before pretty-printing to trim whitespace 2013-10-16 12:33:19 +13:00
0e267d8efa Added a link to the httpie-negotiate auth plugin by @ndzou II. 2013-10-09 23:46:55 +02:00
927acc283e Added a link to the httpie-negotiate auth plugin by @ndzou. 2013-10-09 23:44:55 +02:00
817165f5ff Merge pull request #171 from nlf/master
Allow :port style shorthand for localhost.
2013-10-09 13:22:30 -07:00
4fe3deb9d9 add self to authors, update changelog, and mention shorthand in --help output 2013-10-09 13:21:14 -07:00
9034546b80 tweak readme more 2013-10-09 11:37:05 -07:00
2c12fd99f9 tweak readme more 2013-10-09 11:36:01 -07:00
70eb97dece tweak readme to show http requests 2013-10-09 11:34:22 -07:00
8a52bef559 make shorthand parsing more robust, add unit tests and documentation 2013-10-09 11:32:41 -07:00
711168a899 allow :port style shorthand 2013-10-08 22:41:38 -07:00
81c99886fd Update --proxy examples to include URLs to work with Requests v2.0.0.. 2013-09-25 22:02:29 +02:00
2e535d8345 Fixed password prompt. 2013-09-25 00:17:50 +02:00
0bcd4d2fb0 Fixed a bytes/str issue for Python 3. 2013-09-25 00:00:17 +02:00
d5bc564e4f Allow embeding text (=@) and JSON (:=@) files content into request data fields. 2013-09-24 23:41:18 +02:00
54c5c3d82b 0.7.1 2013-09-24 21:57:29 +02:00
2a6514eb5d Update to requests 2.0.0
Closes #140.
2013-09-24 21:49:43 +02:00
22c2cc6465 Removed unused import. 2013-09-24 20:30:54 +02:00
2265edf05e Cleanup 2013-09-24 20:15:19 +02:00
87774acf5c Changelog 2013-09-24 20:09:23 +02:00
9d2ac5d8ad 0.7.0 2013-09-24 20:07:48 +02:00
3e4e1c72a4 Merge branch 'master' of github.com:jkbr/httpie 2013-09-24 19:51:06 +02:00
29f6b6a2a9 Improved Content-Disposition parsing for --download mode
Closes #168.
2013-09-24 19:50:37 +02:00
26b2d408e7 Merge pull request #167 from matt-hickford/master
Fix plugins ImportError
2013-09-23 02:13:14 -07:00
b5f180a5ee Fix plugins ImportError described at https://github.com/jkbr/httpie/issues/166#issuecomment-24905910 2013-09-23 09:54:06 +01:00
354aaa94bd Improved .netrc example formatting. 2013-09-22 15:20:50 +02:00
2ad4059f92 Improved .netrc example formatting. 2013-09-22 15:19:59 +02:00
5a6b65ecc6 Added link to httpie-oauth. 2013-09-22 15:10:50 +02:00
2acb303552 Added support for auth plugins. 2013-09-21 23:46:15 +02:00
f7b703b4bf Added --ignore-stdin
Closes #150
2013-08-23 10:57:17 +02:00
00de49f4c3 Cleanup 2013-08-18 00:59:10 +02:00
67496162fa Improved --help output. 2013-08-10 11:56:19 +02:00
8378ad3624 Try to import argparse before adding it to reqs. 2013-08-01 09:07:33 +02:00
f87884dd8d README 2013-08-01 08:46:37 +02:00
b671ee35e7 Merge pull request #153 from lorin/patch-1
Augment cookie example in README for multiple cookies
2013-07-31 07:52:22 -07:00
69247066dc Augment cookie example in README for multiple cookies
This change updates the README to show how to pass multiple cookies.
2013-07-31 10:29:38 -04:00
383dba524a Print error when download is interrupted by server
Close #147
2013-07-07 17:00:03 +02:00
60f09776a5 httpless outputs also response headers by default 2013-06-03 12:28:04 +02:00
48719aa70e README 2013-06-03 12:22:34 +02:00
809a461a26 v0.6.0 2013-06-03 12:19:43 +02:00
c3d550e930 Fixed headers tests; Require requests>=1.2.3. 2013-06-02 20:47:29 +02:00
172df162b3 Added XML formatting to CHANGELOG. 2013-06-02 20:27:58 +02:00
1bad62ab0e Handle unicode when formatting XML. 2013-06-02 20:25:36 +02:00
8d302f91f9 Merge branch 'master' of git://github.com/jargonjustin/httpie into jargonjustin-master 2013-06-02 20:14:51 +02:00
63b61bc811 Add custom Host example. 2013-05-20 15:31:02 +02:00
5af88756a6 Fixed download ETA for Python 2.6. 2013-05-14 12:49:29 +02:00
7f624e61b5 Use Thread instead of Timer for progress reporting. 2013-05-14 12:49:03 +02:00
6e848b3203 cleanup 2013-05-14 12:14:08 +02:00
8e112a6948 test_download_no_Content_Length 2013-05-13 15:35:12 +02:00
87c59ae561 Added anonymous sessions (--session=/file/path.json). 2013-05-13 14:47:44 +02:00
76eebeac2a 0.6.0-dev 2013-05-13 12:42:16 +02:00
5b9cbcb530 v0.5.1 2013-05-13 12:40:25 +02:00
8ad33d5f6a Changelog 2013-05-13 12:20:54 +02:00
86ac4cdb7b Changelog 2013-05-13 12:20:28 +02:00
e09b74021c Ignore Content-* and If-* request headers.
Those headers are not stored in sessions anymore.

Closes #141.
2013-05-13 11:54:49 +02:00
71e7061014 v0.5.0 2013-04-27 12:03:38 -03:00
bc756cb6a2 Cleanup 2013-04-27 11:57:13 -03:00
63ed4d32a7 Merge remote-tracking branch 'origin/master' 2013-04-17 13:52:02 -03:00
d1b91bfa9c Merge pull request #142 from capncodewash/netrc-example
Added example for .netrc usage (closes #139)
2013-04-17 09:46:50 -07:00
dac79a8efc Added example for .netrc usage (see issue #139 in upstream. 2013-04-17 16:32:55 +01:00
1fc8396c4b Stop the progres reporter thread on error. 2013-04-16 04:55:45 -03:00
6c3b983c18 Tests 2013-04-15 00:56:47 -03:00
cfa7199f0b Added a simple download test. 2013-04-13 15:34:31 -03:00
5a1177d57e Fixed downloads with no Content-Length. 2013-04-13 14:50:46 -03:00
c63a92f9b7 Cleanup 2013-04-12 22:02:34 -03:00
d17e02792b Fixed length progress bar. 2013-04-12 21:49:27 -03:00
fc4f70a900 Colorize stderr on Windows. 2013-04-12 17:15:21 -03:00
1681a4ddd0 TODOs 2013-04-12 15:27:26 -03:00
289e9b844e Fixed Content-Type retrieval for Python 3. 2013-04-12 14:07:21 -03:00
72cf7c2cb7 Fixed tests for Python 2.6. 2013-04-12 13:42:34 -03:00
4d84d77851 Cleanup 2013-04-12 13:09:57 -03:00
1b98505537 Validate download options before setting up streams. 2013-04-12 11:59:23 -03:00
d32acfe2fa Only use Range when already have a partial download. 2013-04-12 11:56:05 -03:00
e8d79c4d8c Docs fix. 2013-04-12 11:37:58 -03:00
38206e9e92 Cleanup 2013-04-12 11:26:42 -03:00
55d5e78324 --download docs (#104). 2013-04-12 11:06:03 -03:00
341272db1e Added support for output redirection with --download (#104). 2013-04-12 11:04:14 -03:00
464b7a36da Tests 2013-04-12 10:20:01 -03:00
9d043eb745 Used Content-Disposition filename (#104). 2013-04-12 10:19:49 -03:00
40bd8f65af Handle KeyboardInterrupt while --download'ing (#104). 2013-04-12 09:08:19 -03:00
347653b369 Performance and progress bar improvements.
#104
2013-04-12 08:59:33 -03:00
ebfce6fb93 Improved progress bar (#104). 2013-04-11 18:51:21 -03:00
674acfe2c2 Cleanup 2013-04-11 16:23:15 -03:00
7ccdece39f Cleanup 2013-04-11 04:00:41 -03:00
e53dcba03e Added Content-Range parsing tests.
#104
2013-04-11 03:49:01 -03:00
486657afa3 Improved Content-Range parsing.
#104
2013-04-11 03:24:59 -03:00
599bc0519f Download resume improvements.
- Set correct Range
- Validate respnse status
- Validate Content-Range

 #104
2013-04-11 02:29:10 -03:00
21613faa5a Progress bar update 2013-04-10 13:07:05 -03:00
36bc64e02f Cleanup. 2013-04-10 12:53:25 -03:00
6e5c696ac9 --json with no data sets Content-Type as well
Closes #137
2013-04-02 11:07:14 -03:00
9b2a293e6e Progress on --download. 2013-03-24 11:23:18 -03:00
b0dd463687 Corrected session info in the README. 2013-03-22 16:26:51 -03:00
bffaee13ff Formatting 2013-03-20 12:07:23 -03:00
30afcea72d Merge pull request #135 from Scorpil/master
Fixed PyPy cookie updating issue

Closes #132
2013-03-20 08:05:23 -07:00
631c54b711 Fixed PyPy cookie updating issue 2013-03-20 11:45:56 +02:00
99f82bbd32 Handle downloads with no Content-Length. 2013-03-07 13:32:48 -03:00
6f64b437b7 Fixed streaming (closes #133) 2013-03-07 12:42:29 -03:00
7774eac3df Fixed unique suffix placement for URLs with a file extension. 2013-03-03 22:35:01 -03:00
8e6c765be2 Initial --download implementation (#104).
Closes #127
2013-03-03 22:17:09 -03:00
f0c42cd089 v0.4.1 2013-02-26 14:37:09 +01:00
5c6cea79a1 Removed a reference to the removed httpie command
Closes #131
2013-02-26 14:31:52 +01:00
2bed81059a Updated README. 2013-02-22 14:04:27 +01:00
be0b2f21d2 v0.4.0 2013-02-22 13:52:50 +01:00
d97a610f7c Added new logo by @claudiatd 2013-02-22 13:51:37 +01:00
5cc5b13555 Removed the management command.
It means that:

    httpie session list
    httpie session edit
    ...

are gone.

It has never been part of a stable release, and since it wasn't
a very useful feature, it's beeing removed now to avoid feature creep.
2013-02-22 13:27:26 +01:00
3043f24733 .gitignore 2013-02-22 13:19:18 +01:00
093dab5896 Multiple headers TODO. 2013-02-22 13:18:18 +01:00
5f42a21cfb Simplified stored session cookie data. 2013-01-22 20:03:28 +01:00
4c45f0d91f Session name escaping. 2013-01-22 20:02:39 +01:00
d7ec7b2217 Fixing tests for Travis. 2013-01-04 03:19:38 +01:00
7817dfbbcc Fixing tests for Travis. 2013-01-04 03:09:21 +01:00
238b2e0441 Fixing tests for Travis. 2013-01-04 03:05:36 +01:00
a93d57b58b Fixed request/response session cookies.
Closes #113.
2013-01-04 02:59:05 +01:00
79c412064a Python 3.3 fixes. 2013-01-03 15:19:21 +01:00
0ae9d7af58 Compatibility with requests v1.0.4 (requests URL params). 2013-01-03 14:42:17 +01:00
80e317fe24 Added Python 3.3 to tox and travis conf. 2013-01-03 14:14:22 +01:00
1481749c22 Use urlsplit instead of urlparse.
Closes #118.
2013-01-03 14:12:27 +01:00
d84d94dd55 Clean up 2013-01-03 13:49:41 +01:00
1913b0d438 Merge branch 'master' of github.com:jkbr/httpie 2012-12-19 12:31:34 +01:00
fe16f425a9 Require Requests v1.0.3. 2012-12-19 12:31:01 +01:00
7ff71a7f10 Revert: Test Python 3.3 on Travis.
3.3 still not supported
2012-12-19 11:56:02 +01:00
4a37d10245 Test Python 3.3 on Travis. 2012-12-19 11:53:26 +01:00
e5edb66ae8 Requests v1.0: Fixed request body access. 2012-12-19 11:37:52 +01:00
2e57c080fd Pretty print XML 2012-12-17 13:21:38 -08:00
1766dd8291 Requests 1.0: session cookies. 2012-12-17 17:18:18 +01:00
675a8b17ad Merge branch 'master' of github.com:jkbr/httpie 2012-12-17 17:14:24 +01:00
69e26b8bc8 Requests 1.0: prefetch; default_headers. 2012-12-17 17:02:27 +01:00
291f520e0c Update README.rst 2012-12-17 12:26:57 +01:00
9ec328ff6f Session commands. 2012-12-11 12:54:34 +01:00
f2d59ba6bd Improved --check-status + HTTP error + stdout redirect warning. 2012-12-05 05:27:11 +01:00
53caf6ae72 Cleanup 2012-12-05 05:06:06 +01:00
8175366f27 PEP8 2012-12-05 04:39:56 +01:00
8190a7c0c6 Fixed httpie session list 2012-12-05 04:36:42 +01:00
4a615e762f Updated session docs. 2012-12-01 18:43:33 +01:00
7426b4b493 RST formatting. 2012-12-01 18:26:15 +01:00
2cdcadd9d5 Added docs for httpie. 2012-12-01 18:25:34 +01:00
18510a9396 Progress on httpie session *. 2012-12-01 18:16:00 +01:00
acf5f063c7 Typo 2012-12-01 16:52:23 +01:00
2cf379df78 Fixed README typo. 2012-12-01 16:20:16 +01:00
dd100c2cc4 Fixed -j & -v & redirected stdout. Closes #109. 2012-12-01 15:55:58 +01:00
444a9fa929 Added httpless to README. 2012-12-01 15:54:36 +01:00
4a24cd25b9 Clean up. 2012-12-01 15:20:14 +01:00
1c5fb89001 Output stream refactoring. 2012-11-09 15:49:23 +01:00
466e1dbedf Updated CHANGELOG (#100). 2012-11-08 22:39:28 +01:00
d87b2aa0e5 Added support for credentials in URL.
Closes #100 🍰
2012-11-08 22:29:54 +01:00
5d969852c7 Added --no-option's and made args more config-friendly. 2012-09-24 06:49:12 +02:00
bbc702fa11 Improved README. 2012-09-24 05:59:52 +02:00
e25d64a610 0.3.0 2012-09-21 05:50:01 +02:00
a41dd7ac6d Allow output redirection on Windows.
Closes #88.
2012-09-21 04:30:59 +02:00
4a6f32a0f4 Documented config.
Also renamed `default_content_type` to `implicit_content_type` .
2012-09-17 03:08:45 +02:00
548bef7dff Added tests for sessions. 2012-09-17 02:15:00 +02:00
6c2001d1f5 Use the HTTPIE_CONFIG_DIR environment variable. 2012-09-17 02:12:16 +02:00
4029dbf309 Added configuration file.
The "default_content_type" option can be set to "form".

Closes #91.
2012-09-17 00:37:36 +02:00
478d654945 Renamed --session-read to --session-read-only. 2012-09-17 00:01:49 +02:00
66bdbc3745 Cleanup. 2012-09-07 12:48:59 +02:00
316e3f45a9 Added --session-read for read-only sessions. 2012-09-07 12:38:52 +02:00
da0eb7db79 Renamed --allow-redirects to --follow. 2012-09-07 11:58:39 +02:00
9338aadd75 Cleanup 2012-09-05 20:22:08 +02:00
dc7d03e6b8 Merge pull request #90 from simonbuchan/898408c20cfab130699cee3bedbae1ad4a1c69b1
Fix --session for Windows (with a Requests patch)
2012-09-04 02:38:34 -07:00
898408c20c Fix sessions for Windows
':' is invalid in a Windows path, and json needs output to support
write(str).
2012-09-04 15:53:27 +12:00
47de4e2c9c Sessions are now host-bound. 2012-08-19 04:58:14 +02:00
f74424ef03 README 2012-08-18 23:11:56 +02:00
8a9cedb16e JSON session data, `httpie' management command. 2012-08-18 23:07:36 +02:00
ff9f23da5b Grouped arguments for a more user-friendly --help. 2012-08-18 06:12:44 +02:00
50810e5bd9 Include data directory location with --debug. 2012-08-18 04:45:29 +02:00
9b586b953b Use %APPDATA% for data on Windows. 2012-08-18 04:36:58 +02:00
149cbc1604 Fixed Solarized style unavailable on Windows.
#87.
2012-08-18 03:54:38 +02:00
d3df59c8af Updated README. 2012-08-17 23:35:36 +02:00
2057e13a1d Updated README. 2012-08-17 23:35:06 +02:00
4957686bcd Updated README. 2012-08-17 23:34:42 +02:00
4c0d7d526f Added initial support for persistent sessions. 2012-08-17 23:30:47 +02:00
0b3bad9c81 Added initial support for persistent sessions. 2012-08-17 23:23:02 +02:00
1ed43c1a1e Semver-compatible versioning. 2012-08-17 21:24:34 +02:00
bf03937f06 Unified output processing options under --pretty.
* --pretty=none instead of --ugly
* --pretty=all instead of --pretty
* --pretty=colors instead of --colors
* --pretty=format instead of --format
2012-08-17 21:15:37 +02:00
4660da949f Fixed colorized output on Windows with Python 3.
Closes #87.
2012-08-17 06:35:18 +02:00
86256af1df Removed non-ASCII characters from README (closes #85). 2012-08-16 18:47:30 +02:00
8bf7f8219c Fixed readme decoding.
Closes #85.
2012-08-16 03:11:15 +02:00
a5522b8233 Revert "Iter body lines to avoid binary false positives."
This reverts commit b92a3a6d95.
2012-08-16 03:06:48 +02:00
b92a3a6d95 Iter body lines to avoid binary false positives.
#84
2012-08-13 23:33:25 +02:00
9098e5b6e8 Updated changelog. 2012-08-12 06:02:13 +02:00
68640a81b3 Use CRLF for headers in the output. 2012-08-10 01:45:07 +02:00
27f08920c4 Improved examples. 2012-08-09 23:36:29 +02:00
c01dd8d64a Added exit status for timed-out requests. 2012-08-09 05:24:58 +02:00
76feea2f68 Added README reStructuredText validation. 2012-08-07 17:20:50 +02:00
22a10aec4a Added --colors and --format.
Closes #59 and #82.
2012-08-07 16:59:49 +02:00
fa334bdf4d Documented --verify. 2012-08-07 15:25:24 +02:00
f6724452cf Skip tests with redirects on Requests 0.13.6. 2012-08-07 15:08:28 +02:00
07de32c406 Version fix. 2012-08-07 15:01:04 +02:00
1fbe7a6121 Improved --debug. 2012-08-07 14:50:51 +02:00
49e44d9b7e Pre-process README.rst so that PyPi renders it. 2012-08-07 14:50:17 +02:00
193683afbb Added proxy docs. 2012-08-07 14:49:43 +02:00
126b1da515 v0.2.8dev 2012-08-07 00:13:27 +02:00
969b310ea9 v0.2.7 2012-08-07 00:12:47 +02:00
dd2c89412c Compatibility with Requests 0.13.6. 2012-08-07 00:07:04 +02:00
381e60f9d8 Extended README. 2012-08-06 23:27:49 +02:00
44e409693b Set JSON Content-Type only with data even with -j. 2012-08-06 22:14:52 +02:00
4e58a3849a Added exit status constants, cleaned up main(). 2012-08-04 19:22:50 +02:00
94c77c9bfc Improved password prompt. 2012-08-04 17:04:36 +02:00
747b87c4e6 Changelog, typos 2012-08-04 16:46:39 +02:00
c7657e3c4b Streamed terminal output
`--stream` can be used to enable streaming also with `--pretty` and to ensure
a more frequent output flushing.
2012-08-04 16:35:31 +02:00
4615011f2e Sort headers by name when prettifying. 2012-08-03 00:58:01 +02:00
4b1a04e5ed Fixed error handling. 2012-08-02 04:33:43 +02:00
e045ca6bd8 Cleanup, CHANGELOG 2012-08-01 23:51:30 +02:00
52e46bedda Take advantage of streaming.
It's now possible to download huge files with HTTPie, and it's often faster than curl and wget!
2012-08-01 23:21:52 +02:00
67ad5980b2 Don't fetch the response body unless needed.
E.g., this will only read the response headers but won't download the
whole file:

    http GET --headers example.org/big-file.avi

The request method is respected (i.e., it doesn't switch to HEAD like
cURL does).
2012-08-01 21:31:06 +02:00
00d85a4b97 Fallback to media subtype if the type is uknown.
Closes #81.
2012-08-01 17:37:23 +02:00
90d34ffd0d Added tests for binary request data. 2012-08-01 00:52:30 +02:00
8905b4fc72 cleanup 2012-07-30 14:23:22 +02:00
a5b98818c8 Syntax-highlighting for examples in the README. 2012-07-30 13:58:13 +02:00
5e7bb1f6dc Syntax-highlighting for examples in the README. 2012-07-30 13:51:28 +02:00
4117d99dd0 Updated screenshot. 2012-07-30 12:37:59 +02:00
49604e7c29 Updated screenshot. 2012-07-30 12:29:56 +02:00
72d371c467 Updated screenshot. 2012-07-30 12:24:11 +02:00
a8c9441f71 Updated screenshot. 2012-07-30 12:11:28 +02:00
e13f65ace1 Updated solarized and switched to Solarized256Style. 2012-07-30 12:11:16 +02:00
a1682d0d2e Added AUTHORS 2012-07-30 12:10:19 +02:00
923a8b71bd Revorked output
Binary now works everywhere. Also added `--output FILE` for Windows.
2012-07-30 10:58:16 +02:00
6eed0d92eb Better error messages. 2012-07-29 07:14:54 +02:00
edf87c3392 Consistent request-response separators. 2012-07-29 06:59:51 +02:00
f73bfea6b8 Validate "file fields (name@/path) require --form / -f". 2012-07-29 06:58:50 +02:00
16635870e3 Removed redundant decode/encode. 2012-07-29 03:52:24 +02:00
f5bc081fda Send filenames with multipart/form-data file uploads. 2012-07-28 13:24:44 +02:00
1efea59a8d Fixed typos. 2012-07-28 06:09:25 +02:00
098e1d3100 Fixed multipart requests output; binary support.
* Bodies of multipart requests are correctly printed (closes #30).
* Binary requests and responses should always work (they are also suppressed
  for terminal output). So things like this work::

     http www.google.com/favicon.ico > favicon.ico
2012-07-28 05:50:12 +02:00
a8ddb8301d Default to https:// if invoked as `https'. 2012-07-27 18:08:33 +02:00
a770d79aef v0.2.7dev 2012-07-26 10:03:34 +02:00
b53d483163 v0.2.6 2012-07-26 09:58:31 +02:00
f45cc0eec0 Added docstrings, refactored input. 2012-07-26 07:23:00 +02:00
f26f2f1438 Mention necessary quoting with :=. #77 2012-07-26 03:24:58 +02:00
851412c698 Improved error messages. 2012-07-26 03:16:42 +02:00
26a76e8243 Clean-up 2012-07-26 00:50:39 +02:00
f5cfd0143b Ensure that full querystring is printent with -v.
The `key==value` parameters weren't included in the Request-Line URL.

Also added tests.
2012-07-25 14:32:57 +02:00
9391c89205 Fixed RST formatting. 2012-07-24 17:22:04 +02:00
76ebe7c6db Short option for --headers is now -h.
-t has been removed, for usage use --help
2012-07-24 17:17:26 +02:00
7af08b6faa Allow multiple fields with the same name.
Applies to form data and URL params:

    http -f url a=1 a=2
    http url a==1 a==2
2012-07-24 17:00:02 +02:00
9944def703 Switched to "==" a the separator for URL params.
Also refactored item escaping.
2012-07-24 14:56:53 +02:00
728a1a195b Updated changelog. 2012-07-24 01:17:07 +02:00
2646ebaaed Replaced --ignore-http-status with --check-status.
The default behaviour now is to exit with 0 on HTTP errors
unless --check-status is set.
2012-07-24 01:09:14 +02:00
fba3912f2e Fixed tests. 2012-07-23 19:49:38 +02:00
0572158ba1 Added exit codes for HTTP 3xx, 4xx, 5xx (3, 4, 5).
Also added `--ignore-http-status` to ensure 0 exit status.

HTTP 3xx result in 0 exit status when `--allow-redirects` is set.
2012-07-23 19:40:50 +02:00
0a673613ef Fixed colorama initialization (#36). 2012-07-21 15:08:28 +02:00
19f760450f Use local httpbin for all tests if available. 2012-07-21 14:37:05 +02:00
35da44309f Undebug 2012-07-21 03:26:48 +02:00
ced6e33230 Fixed tests. 2012-07-21 03:22:47 +02:00
87042f65c9 Added models.Environment().
Refactoring and general cleanup.
2012-07-21 03:14:01 +02:00
c271715a98 Updated flags in README. 2012-07-20 23:51:05 +02:00
57fc606f6b Changed default --print to "b" if stdout piped.
If the output is piped to another program or redirected to a file,
the new default behaviour is to only print the response body.
(It can still be overriden via the ``--print`` flag.)
2012-07-20 23:43:04 +02:00
7d82b853ae Updated installation instructions. 2012-07-20 22:09:53 +02:00
16f23d8147 Improved highlighting of HTTP headers.
Closes #60.
2012-07-20 21:58:41 +02:00
ab7915d9e0 Updated changelog; added stable version README link. 2012-07-19 13:31:02 +03:00
1d6fcfff73 Merge pull request #72 from jakebasile/issue-61
Added Query String Parameters (param=:value).
2012-07-19 03:12:32 -07:00
76a3125153 Updated documentation for query string params. 2012-07-18 21:16:33 -05:00
24d6331d15 Added a bit of testing for the new query string parameters. 2012-07-18 21:16:08 -05:00
06ea36aaa4 Added the ability to pass query string parameters. 2012-07-18 20:44:09 -05:00
c2d70e2bb1 Clean up. 2012-07-17 07:01:30 +02:00
40948dbd2e Updated changelog. 2012-07-17 04:20:37 +02:00
2dba176aa8 Added support for terminal colors under Windows.
Tested on Python 2.7 under Windows 7 with PowerShell and cmd.exe.

Closes #36
2012-07-17 04:06:13 +02:00
54e3e5bca4 README fixes. 2012-07-17 01:55:12 +02:00
533a662651 0.2.6dev 2012-07-17 01:39:30 +02:00
1ce02ebbd5 0.2.5 (bugfixes) 2012-07-17 01:39:02 +02:00
8a7f4c0d6e Fixed tests exist status. 2012-07-17 01:33:18 +02:00
f29c458611 Python 3 fixes. 2012-07-17 01:26:21 +02:00
2d7df0afb4 Fixed AttributeError in Content-Type vendor removal. 2012-07-17 01:11:43 +02:00
16a7d0a719 Fixed accidentally remove __licence__. 2012-07-17 01:11:01 +02:00
0cffda86f6 0.2.5dev 2012-07-17 00:47:42 +02:00
f42ee6da85 0.2.5dev 2012-07-17 00:45:20 +02:00
deeb7cbbac 0.2.4 (bad upload of 0.2.3 to pypi). 2012-07-17 00:44:25 +02:00
12f2fb4a92 Merge branch 'master' of github.com:jkbr/httpie 2012-07-17 00:38:41 +02:00
489bd64295 0.2.4dev 2012-07-17 00:37:53 +02:00
9b8cb42efd 0.2.3 2012-07-17 00:37:13 +02:00
2036337a53 Merge pull request #69 from jokull/master
Prettify vendor+json and vendor+xml Content-Type responses
2012-07-16 15:27:50 -07:00
5ca8bec9ff Add a note on pretty JSON and unicode to changelog
Closes #52
Closes #67
2012-07-17 00:22:39 +02:00
df79792fd9 Added test case to verify unicode output 2012-07-17 00:09:01 +02:00
5a82c79fdf Now non-ascii symbols displayed correctly in the output (not as escape sequences). 2012-07-17 00:08:52 +02:00
05b321d38f Better wording. 2012-07-17 00:06:13 +02:00
681b652bf9 Allow stdin data with password prompt; added tests
Closes #70
2012-07-16 23:41:27 +02:00
85b3a016eb Update README with new --auth behavior. 2012-07-16 04:50:25 -04:00
929ead437a Have --auth prompt for password if omitted. 2012-07-16 04:40:36 -04:00
36de166b28 Simplify vendor extension content-types since they are most likely lexable 2012-07-14 14:27:11 +00:00
7bc2de2f9d Merge pull request #68 from cemaleker/master
Added omitted query string data to request headers.
2012-07-13 17:53:11 -07:00
cb7ead04e2 Added omitted query string data to request headers. 2012-07-14 03:37:24 +03:00
cd2ca41f48 Merge pull request #65 from simono/patch-1
Update README.rst and add links to Ubuntu and Debian Packages.
2012-07-11 06:35:28 -07:00
c71de95505 Update README.rst and add links to Ubuntu and Debian Packages. 2012-07-11 16:32:00 +03:00
6ab03b21b4 Fixed Content-Type for requests with no data.
Closes #62.
2012-07-04 01:39:21 +02:00
50196be0f2 Added support for request payload from a filepath
Content-Type is detected from the filename.

Closes #57.
2012-06-29 00:45:31 +02:00
41d640920c Added more examples. 2012-06-25 14:50:49 +02:00
3179631603 0.2.3dev 2012-06-24 16:45:01 +02:00
2f7921091c 0.2.2 2012-06-24 16:43:03 +02:00
180313d80c Impreved tests. 2012-06-24 04:20:45 +02:00
926d3f5caf Tests, docs, clean-up.
Closes #54.
2012-06-24 03:45:21 +02:00
4613d947a8 Default to POST also when stdin redirected.
+clean up
2012-06-24 01:25:30 +02:00
5a47f00bac Replaced mock.Mock with argparse.Namespace to reduce deps. 2012-06-23 23:54:59 +02:00
0e1affbbc4 Issue #54 Method suggestion proposal 2012-06-17 22:15:07 +04:00
d920f20847 Issue #54 Method suggestion proposal 2012-06-17 22:11:26 +04:00
bca36f0464 Issue #54 Method suggestion proposal 2012-06-17 21:46:56 +04:00
78fff98712 Issue #54 Method suggestion proposal 2012-06-16 20:08:31 +04:00
e06c448a75 README improvements. 2012-06-15 17:32:45 +02:00
9cdbd6b0ec Added a Contribute section to README. 2012-06-15 17:13:40 +02:00
cbc6d02127 Fixed --verbose --form.
Closes #53
2012-06-15 16:47:55 +02:00
284a75fa2f Merge pull request #51 from msabramo/testing
Added support for tox (http://tox.testrun.org/)
2012-06-13 07:48:09 -07:00
b3ea273a21 Add "pypy" to .travis.yml 2012-06-13 07:36:51 -07:00
0d129d5f69 Add tox.ini for tox (http://tox.testrun.org/) 2012-06-13 07:18:12 -07:00
1388206f1a Fix path to tests.py in setup.py to make python setup.py test work 2012-06-13 07:18:11 -07:00
28dbe9f76c Bump version to 0.2.2dev. 2012-06-13 16:02:30 +02:00
a0700c41ad 0.2.1 2012-06-13 16:01:23 +02:00
e175fe9d0e Ensured a new line after the request message in the output. 2012-06-13 15:32:02 +02:00
d544ec3823 Made --verbose work also with requests<0.12.1. 2012-06-13 15:25:05 +02:00
6cf2910de0 Version bump to 0.2.1dev. 2012-06-13 15:24:48 +02:00
f64eb09571 Merge pull request #50 from dair-targ/master
Fixed --verbose flag for newer requests.
2012-06-13 06:14:12 -07:00
126130455e Merge pull request #45 from gandaro/pygments-lexers
Use the Pygments HTTP and JSON lexers
2012-06-13 06:09:11 -07:00
70b3658004 --verbose flag was not working. Here is bugfix. 2012-06-02 23:14:21 +04:00
d89eeb0796 PEP-8 2012-04-28 14:18:59 +02:00
bced559496 use PrettyHttp class; working --headers and --body 2012-04-28 14:16:47 +02:00
4aa86cb438 Use the full capability of HttpLexer 2012-04-26 14:48:38 +02:00
2d7f2c65a2 Use the Pygments HTTP and JSON lexers 2012-04-26 13:05:59 +02:00
200 changed files with 19761 additions and 1259 deletions

17
.editorconfig Normal file
View File

@ -0,0 +1,17 @@
# https://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.yml]
indent_size = 2
[Makefile]
indent_style = tab
indent_size = 8

44
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,44 @@
---
name: Bug report
about: Report a possible bug in HTTPie
title: ''
labels: "new, bug"
assignees: 'BoboTiG'
---
## Checklist
- [ ] I've searched for similar issues.
- [ ] I'm using the latest version of HTTPie.
---
## Minimal reproduction code and steps
1.
2.
3.
## Current result
## Expected result
---
## Debug output
Please re-run the command with `--debug`, then copy the entire command & output and paste both below:
```bash
$ http --debug <COMPLETE ARGUMENT LIST THAT TRIGGERS THE ERROR>
<COMPLETE OUTPUT>
```
## Additional information, screenshots, or code examples

View File

@ -0,0 +1,30 @@
---
name: Feature request
about: Suggest an enhancement for HTTPie
title: ''
labels: "new, enhancement"
assignees: ''
---
## Checklist
- [ ] I've searched for similar feature requests.
---
## Enhancement request
---
## Problem it solves
E.g. “I'm always frustrated when […]”, “Im trying to do […] so that […]”.
---
## Additional information, screenshots, or code examples

10
.github/ISSUE_TEMPLATE/other.md vendored Normal file
View File

@ -0,0 +1,10 @@
---
name: Other
about: Anything else that isn't a feature or a bug
title: ''
labels: "new"
assignees: ''
---
If you have a general question, please consider asking on Discord: https://httpie.io/chat

9
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,9 @@
version: 2
updates:
# GitHub Actions
- package-ecosystem: github-actions
directory: /
schedule:
interval: daily
assignees:
- BoboTiG

19
.github/workflows/code-style.yml vendored Normal file
View File

@ -0,0 +1,19 @@
on:
pull_request:
paths:
- .github/workflows/code-style.yml
- extras/*.py
- httpie/**/*.py
- setup.py
- tests/**/*.py
jobs:
code-style:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.9
- run: make venv
- run: make codestyle

22
.github/workflows/coverage.yml vendored Normal file
View File

@ -0,0 +1,22 @@
on:
pull_request:
paths:
- .github/workflows/coverage.yml
- httpie/**/*.py
- setup.*
- tests/**/*.py
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: "3.10"
- run: make install
- run: make test-cover
- run: make codecov-upload
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_REPO_TOKEN }}
- run: make test-dist

View File

@ -0,0 +1,19 @@
on:
pull_request:
paths:
- "*.md"
- "**/*.md"
jobs:
doc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7
- name: Install the linter
run: sudo gem install mdl
- name: Check files
run: make doc-check

20
.github/workflows/docs-deploy.yml vendored Normal file
View File

@ -0,0 +1,20 @@
on:
push:
branches:
- master
paths:
- docs/README.md
- docs/config.json
release:
types:
- published
- unpublished
- deleted
jobs:
trigger-doc-build:
runs-on: ubuntu-latest
steps:
- name: Install HTTPie
run: sudo snap install --edge httpie
- name: Trigger new documentation build
run: http --ignore-stdin POST ${{ secrets.DOCS_UPDATE_VERCEL_HOOK }}

View File

@ -0,0 +1,26 @@
on:
push:
branches:
- master
paths:
- docs/installation/*
# Allow to call the workflow manually
workflow_dispatch:
jobs:
doc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.9
- run: make install
- run: make doc-update-install
- uses: Automattic/action-commit-to-branch@master
with:
branch: master
commit_message: Auto-update installation instructions in the docs
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

26
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,26 @@
on:
# Add a "Trigger" button to manually start the workflow.
workflow_dispatch:
inputs:
branch:
description: "The branch, tag or SHA to release from"
required: true
default: "master"
# It could be fully automated by uncommenting following lines.
# Let's see later if we are confident enough to try it :)
# release:
# types:
# - published
jobs:
new-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.9
- run: make publish
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}

View File

@ -0,0 +1,23 @@
on:
pull_request:
paths:
- .github/workflows/test-package-linux-snap.yml
- snapcraft.yaml
jobs:
snap:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
uses: snapcore/action-build@v1
id: snapcraft
- name: Install
run: sudo snap install --dangerous ${{ steps.snapcraft.outputs.snap }}
- name: Test
run: |
httpie.http --version
httpie.https --version
# Auto-aliases cannot be tested when installing a snap outside the store.
# http --version
# https --version

View File

@ -0,0 +1,17 @@
on:
pull_request:
paths:
- .github/workflows/test-package-mac-brew.yml
- docs/packaging/brew/httpie.rb
jobs:
brew:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: Setup brew
run: |
brew developer on
brew update
- name: Build and test the formula
run: make brew-test

45
.github/workflows/tests.yml vendored Normal file
View File

@ -0,0 +1,45 @@
on:
push:
branches:
- master
paths:
- .github/workflows/tests.yml
- httpie/**/*.py
- setup.*
- tests/**/*.py
pull_request:
paths:
- .github/workflows/tests.yml
- httpie/**/*.py
- setup.*
- tests/**/*.py
jobs:
test:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: [3.6, 3.7, 3.8, 3.9, "3.10"]
pyopenssl: [0, 1]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Windows setup
if: matrix.os == 'windows-latest'
run: |
python -m pip install --upgrade pip wheel
python -m pip install --upgrade '.[dev]'
python -m pytest --verbose ./httpie ./tests
env:
HTTPIE_TEST_WITH_PYOPENSSL: ${{ matrix.pyopenssl }}
- name: Linux & Mac setup
if: matrix.os != 'windows-latest'
run: |
make install
make test
env:
HTTPIE_TEST_WITH_PYOPENSSL: ${{ matrix.pyopenssl }}

155
.gitignore vendored
View File

@ -1,4 +1,153 @@
dist
httpie.egg-info
build
.DS_Store
.idea/
*.egg-info
.cache/
*.pyc
htmlcov
##############################################################################
# The below is GitHub template for Python project. gitignore.
# <https://github.com/github/gitignore/blob/master/Python.gitignore>
##############################################################################
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
venv*/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# Packit
/httpie.spec
/httpie-*.rpm
/httpie-*.tar.gz
# VS Code
.vscode/
# Windows Chocolatey
*.nupkg

19
.packit.yaml Normal file
View File

@ -0,0 +1,19 @@
# See the documentation for more information:
# https://packit.dev/docs/configuration/
specfile_path: httpie.spec
actions:
# get the current Fedora Rawhide specfile:
post-upstream-clone: "wget https://src.fedoraproject.org/rpms/httpie/raw/rawhide/f/httpie.spec -O httpie.spec"
jobs:
- job: copr_build
trigger: pull_request
metadata:
targets:
- fedora-all
additional_repos:
- "https://kojipkgs.fedoraproject.org/repos/f$releasever-build/latest/$basearch/"
- job: propose_downstream
trigger: release
metadata:
dist_git_branches:
- rawhide

View File

@ -1,11 +0,0 @@
language: python
python:
- 2.6
- 2.7
- 3.1
- 3.2
script: python tests/tests.py
install:
- pip install requests pygments
- "if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]] || [[ $TRAVIS_PYTHON_VERSION == '3.1' ]]; then pip install argparse; fi"

41
AUTHORS.md Normal file
View File

@ -0,0 +1,41 @@
# HTTPie authors
- [Jakub Roztocil](https://github.com/jakubroztocil)
## Patches, features, ideas
[Complete list of contributors on GitHub](https://github.com/httpie/httpie/graphs/contributors)
- [Cláudia T. Delgado](https://github.com/claudiatd)
- [Hank Gay](https://github.com/gthank)
- [Jake Basile](https://github.com/jakebasile)
- [Vladimir Berkutov](https://github.com/dair-targ)
- [Jakob Kramer](https://github.com/gandaro)
- [Chris Faulkner](https://github.com/faulkner)
- [Alen Mujezinovic](https://github.com/flashingpumpkin)
- [Praful Mathur](https://github.com/tictactix)
- [Marc Abramowitz](https://github.com/msabramo)
- [Ismail Badawi](https://github.com/isbadawi)
- [Laurent Bachelier](https://github.com/laurentb)
- [Isman Firmansyah](https://github.com/iromli)
- [Simon Olofsson](https://github.com/simono)
- [Churkin Oleg](https://github.com/Bahus)
- [Jökull Sólberg Auðunsson](https://github.com/jokull)
- [Matthew M. Boedicker](https://github.com/mmb)
- [marblar](https://github.com/marblar)
- [Tomek Wójcik](https://github.com/tomekwojcik)
- [Davey Shafik](https://github.com/dshafik)
- [cido](https://github.com/cido)
- [Justin Bonnar](https://github.com/jargonjustin)
- [Nathan LaFreniere](https://github.com/nlf)
- [Matthias Lehmann](https://github.com/matleh)
- [Dennis Brakhane](https://github.com/brakhane)
- [Matt Layman](https://github.com/mblayman)
- [Edward Yang](https://github.com/honorabrutroll)
- [Aleksandr Vinokurov](https://github.com/aleksandr-vin)
- [Jeff Byrnes](https://github.com/jeffbyrnes)
- [Denis Belavin](https://github.com/LuckyDenis)
- [Mickaël Schoentgen](https://github.com/BoboTiG)
- [Elena Lape](https://github.com/elenalape)
- [Rohit Sehgal](https://github.com/r0hi7)
- [Bartłomiej Jacak](https://github.com/bartekjacak)

378
CHANGELOG.md Normal file
View File

@ -0,0 +1,378 @@
# Change Log
This document records all notable changes to [HTTPie](https://httpie.io).
This project adheres to [Semantic Versioning](https://semver.org/).
## [2.6.0.dev0](https://github.com/httpie/httpie/compare/2.5.0...master) (unreleased)
- Added support for formatting & coloring of JSON bodies preceded by non-JSON data (e.g., an XXSI prefix). ([#1130](https://github.com/httpie/httpie/issues/1130))
- Added `--response-charset` to allow overriding the response encoding for terminal display purposes. ([#1168](https://github.com/httpie/httpie/issues/1168))
- Added `--response-mime` to allow overriding the response mime type for coloring and formatting for the terminal. ([#1168](https://github.com/httpie/httpie/issues/1168))
- Improved handling of responses with incorrect `Content-Type`. ([#1110](https://github.com/httpie/httpie/issues/1110), [#1168](https://github.com/httpie/httpie/issues/1168))
- Installed plugins are now listed in `--debug` output. ([#1165](https://github.com/httpie/httpie/issues/1165))
- Fixed duplicate keys preservation of JSON data. ([#1163](https://github.com/httpie/httpie/issues/1163))
## [2.5.0](https://github.com/httpie/httpie/compare/2.4.0...2.5.0) (2021-09-06)
Blog post: [Whats new in HTTPie 2.5.0](https://httpie.io/blog/httpie-2.5.0)
- Added `--raw` to allow specifying the raw request body without extra processing as
an alternative to `stdin`. ([#534](https://github.com/httpie/httpie/issues/534))
- Added support for XML formatting. ([#1129](https://github.com/httpie/httpie/issues/1129))
- Added internal support for file-like object responses to improve adapter plugin support. ([#1094](https://github.com/httpie/httpie/issues/1094))
- Fixed `--continue --download` with a single byte to be downloaded left. ([#1032](https://github.com/httpie/httpie/issues/1032))
- Fixed `--verbose` HTTP 307 redirects with streamed request body. ([#1088](https://github.com/httpie/httpie/issues/1088))
- Fixed handling of session files with `Cookie:` followed by other headers. ([#1126](https://github.com/httpie/httpie/issues/1126))
## [2.4.0](https://github.com/httpie/httpie/compare/2.3.0...2.4.0) (2021-02-06)
- Added support for `--session` cookie expiration based on `Set-Cookie: max-age=<n>`. ([#1029](https://github.com/httpie/httpie/issues/1029))
- Show a `--check-status` warning with `--quiet` as well, not only when the output is redirected. ([#1026](https://github.com/httpie/httpie/issues/1026))
- Fixed upload with `--session` ([#1020](https://github.com/httpie/httpie/issues/1020)).
- Fixed a missing blank line between request and response ([#1006](https://github.com/httpie/httpie/issues/1006)).
## [2.3.0](https://github.com/httpie/httpie/compare/2.2.0...2.3.0) (2020-10-25)
- Added support for streamed uploads ([#201](https://github.com/httpie/httpie/issues/201)).
- Added support for multipart upload streaming ([#684](https://github.com/httpie/httpie/issues/684)).
- Added support for body-from-file upload streaming (`http pie.dev/post @file`).
- Added `--chunked` to enable chunked transfer encoding ([#753](https://github.com/httpie/httpie/issues/753)).
- Added `--multipart` to allow `multipart/form-data` encoding for non-file `--form` requests as well.
- Added support for preserving field order in multipart requests ([#903](https://github.com/httpie/httpie/issues/903)).
- Added `--boundary` to allow a custom boundary string for `multipart/form-data` requests.
- Added support for combining cookies specified on the CLI and in a session file ([#932](https://github.com/httpie/httpie/issues/932)).
- Added out of the box SOCKS support with no extra installation ([#904](https://github.com/httpie/httpie/issues/904)).
- Added `--quiet, -q` flag to enforce silent behaviour.
- Fixed the handling of invalid `expires` dates in `Set-Cookie` headers ([#963](https://github.com/httpie/httpie/issues/963)).
- Removed Tox testing entirely ([#943](https://github.com/httpie/httpie/issues/943)).
## [2.2.0](https://github.com/httpie/httpie/compare/2.1.0...2.2.0) (2020-06-18)
- Added support for custom content types for uploaded files ([#668](https://github.com/httpie/httpie/issues/668)).
- Added support for `$XDG_CONFIG_HOME` ([#920](https://github.com/httpie/httpie/issues/920)).
- Added support for `Set-Cookie`-triggered cookie expiration ([#853](https://github.com/httpie/httpie/issues/853)).
- Added `--format-options` to allow disabling sorting, etc. ([#128](https://github.com/httpie/httpie/issues/128))
- Added `--sorted` and `--unsorted` shortcuts for (un)setting all sorting-related `--format-options`. ([#128](https://github.com/httpie/httpie/issues/128))
- Added `--ciphers` to allow configuring OpenSSL ciphers ([#870](https://github.com/httpie/httpie/issues/870)).
- Added `netrc` support for auth plugins. Enabled for `--auth-type=basic`
and `digest`, 3rd parties may opt in ([#718](https://github.com/httpie/httpie/issues/718), [#719](https://github.com/httpie/httpie/issues/719), [#852](https://github.com/httpie/httpie/issues/852), [#934](https://github.com/httpie/httpie/issues/934)).
- Fixed built-in plugins-related circular imports ([#925](https://github.com/httpie/httpie/issues/925)).
## [2.1.0](https://github.com/httpie/httpie/compare/2.0.0...2.1.0) (2020-04-18)
- Added `--path-as-is` to bypass dot segment (`/../` or `/./`)
URL squashing ([#895](https://github.com/httpie/httpie/issues/895)).
- Changed the default `Accept` header value for JSON requests from
`application/json, */*` to `application/json, */*;q=0.5`
to clearly indicate preference ([#488](https://github.com/httpie/httpie/issues/488)).
- Fixed `--form` file upload mixed with redirected `stdin` error handling
([#840](https://github.com/httpie/httpie/issues/840)).
## [2.0.0](https://github.com/httpie/httpie/compare/1.0.3...2.0.0) (2020-01-12)
- Removed Python 2.7 support ([EOL Jan 2020](https://www.python.org/doc/sunset-python-2/).
- Added `--offline` to allow building an HTTP request and printing it but not
actually sending it over the network.
- 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 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.
- Added `--max-headers` to allow setting the max header limit.
- Added `--compress` to allow request body compression.
- Added `--ignore-netrc` to allow bypassing credentials from `.netrc`.
- Added `https` alias command with `https://` as the default scheme.
- Added `$ALL_PROXY` documentation.
- Added type annotations throughout the codebase.
- Added `tests/` to the PyPi package for the convenience of
downstream package maintainers.
- Fixed an error when `stdin` was a closed fd.
- Improved `--debug` output formatting.
## [1.0.3](https://github.com/httpie/httpie/compare/1.0.2...1.0.3) (2019-08-26)
- Fixed CVE-2019-10751 — the way the output filename is generated for
`--download` requests without `--output` resulting in a redirect has
been changed to only consider the initial URL as the base for the generated
filename, and not the final one. This fixes a potential security issue under
the following scenario:
1. A `--download` request with no explicit `--output` is made (e.g.,
`$ http -d example.org/file.txt`), instructing httpie to
[generate the output filename](https://httpie.org/doc#downloaded-filename)
from the `Content-Disposition` response header, or from the URL if the header
is not provided.
2. The server handling the request has been modified by an attacker and
instead of the expected response the URL returns a redirect to another
URL, e.g., `attacker.example.org/.bash_profile`, whose response does
not provide a `Content-Disposition` header (i.e., the base for the
generated filename becomes `.bash_profile` instead of `file.txt`).
3. Your current directory doesnt already contain `.bash_profile`
(i.e., no unique suffix is added to the generated filename).
4. You dont notice the potentially unexpected output filename
as reported by httpie in the console output
(e.g., `Downloading 100.00 B to ".bash_profile"`).
Reported by Raul Onitza and Giulio Comi.
## [1.0.2](https://github.com/httpie/httpie/compare/1.0.1...1.0.2) (2018-11-14)
- Fixed tests for installation with pyOpenSSL.
## [1.0.1](https://github.com/httpie/httpie/compare/1.0.0...1.0.1) (2018-11-14)
- Removed external URL calls from tests.
## [1.0.0](https://github.com/httpie/httpie/compare/0.9.9...1.0.0) (2018-11-02)
- Added `--style=auto` which follows the terminal ANSI color styles.
- Added support for selecting TLS 1.3 via `--ssl=tls1.3`
(available once implemented in upstream libraries).
- Added `true`/`false` as valid values for `--verify`
(in addition to `yes`/`no`) and the boolean value is case-insensitive.
- Changed the default `--style` from `solarized` to `auto` (on Windows it stays `fruity`).
- Fixed default headers being incorrectly case-sensitive.
- Removed Python 2.6 support.
## [0.9.9](https://github.com/httpie/httpie/compare/0.9.8...0.9.9) (2016-12-08)
- Fixed README.
## [0.9.8](https://github.com/httpie/httpie/compare/0.9.6...0.9.8) (2016-12-08)
- Extended auth plugin API.
- Added exit status code `7` for plugin errors.
- Added support for `curses`-less Python installations.
- Fixed `REQUEST_ITEM` arg incorrectly being reported as required.
- Improved `CTRL-C` interrupt handling.
- Added the standard exit status code `130` for keyboard interrupts.
## [0.9.6](https://github.com/httpie/httpie/compare/0.9.4...0.9.6) (2016-08-13)
- Added Python 3 as a dependency for Homebrew installations
to ensure some of the newer HTTP features work out of the box
for macOS users (starting with HTTPie 0.9.4.).
- Added the ability to unset a request header with `Header:`, and send an
empty value with `Header;`.
- Added `--default-scheme <URL_SCHEME>` to enable things like
`$ alias https='http --default-scheme=https`.
- Added `-I` as a shortcut for `--ignore-stdin`.
- Added fish shell completion (located in `extras/httpie-completion.fish`
in the GitHub repo).
- Updated `requests` to 2.10.0 so that SOCKS support can be added via
`pip install requests[socks]`.
- Changed the default JSON `Accept` header from `application/json`
to `application/json, */*`.
- Changed the pre-processing of request HTTP headers so that any leading
and trailing whitespace is removed.
## [0.9.4](https://github.com/httpie/httpie/compare/0.9.3...0.9.4) (2016-07-01)
- Added `Content-Type` of files uploaded in `multipart/form-data` requests
- Added `--ssl=<PROTOCOL>` to specify the desired SSL/TLS protocol version
to use for HTTPS requests.
- Added JSON detection with `--json, -j` to work around incorrect
`Content-Type`
- Added `--all` to show intermediate responses such as redirects (with `--follow`)
- Added `--history-print, -P WHAT` to specify formatting of intermediate responses
- Added `--max-redirects=N` (default 30)
- Added `-A` as short name for `--auth-type`
- Added `-F` as short name for `--follow`
- Removed the `implicit_content_type` config option
(use `"default_options": ["--form"]` instead)
- Redirected `stdout` doesn't trigger an error anymore when `--output FILE`
is set
- Changed the default `--style` back to `solarized` for better support
of light and dark terminals
- Improved `--debug` output
- Fixed `--session` when used with `--download`
- Fixed `--download` to trim too long filenames before saving the file
- Fixed the handling of `Content-Type` with multiple `+subtype` parts
- Removed the XML formatter as the implementation suffered from multiple issues
## [0.9.3](https://github.com/httpie/httpie/compare/0.9.2...0.9.3) (2016-01-01)
- Changed the default color `--style` from `solarized` to `monokai`
- Added basic Bash autocomplete support (need to be installed manually)
- Added request details to connection error messages
- Fixed `'requests.packages.urllib3' has no attribute 'disable_warnings'`
errors that occurred in some installations
- Fixed colors and formatting on Windows
- Fixed `--auth` prompt on Windows
## [0.9.2](https://github.com/httpie/httpie/compare/0.9.1...0.9.2) (2015-02-24)
- Fixed compatibility with Requests 2.5.1
- Changed the default JSON `Content-Type` to `application/json` as UTF-8
is the default JSON encoding
## [0.9.1](https://github.com/httpie/httpie/compare/0.9.0...0.9.1) (2015-02-07)
- Added support for Requests transport adapter plugins
(see [httpie-unixsocket](https://github.com/httpie/httpie-unixsocket)
and [httpie-http2](https://github.com/httpie/httpie-http2))
## [0.9.0](https://github.com/httpie/httpie/compare/0.8.0...0.9.0) (2015-01-31)
- Added `--cert` and `--cert-key` parameters to specify a client side
certificate and private key for SSL
- Improved unicode support
- Improved terminal color depth detection via `curses`
- To make it easier to deal with Windows paths in request items, `\`
now only escapes special characters (the ones that are used as key-value
separators by HTTPie)
- Switched from `unittest` to `pytest`
- Added Python `wheel` support
- Various test suite improvements
- Added `CONTRIBUTING`
- Fixed `User-Agent` overwriting when used within a session
- Fixed handling of empty passwords in URL credentials
- Fixed multiple file uploads with the same form field name
- Fixed `--output=/dev/null` on Linux
- Miscellaneous bugfixes
## [0.8.0](https://github.com/httpie/httpie/compare/0.7.1...0.8.0) (2014-01-25)
- Added `field=@file.txt` and `field:=@file.json` for embedding
the contents of text and JSON files into request data
- Added curl-style shorthand for localhost
- Fixed request `Host` header value output so that it doesn't contain
credentials, if included in the URL
## [0.7.1](https://github.com/httpie/httpie/compare/0.6.0...0.7.1) (2013-09-24)
- Added `--ignore-stdin`
- Added support for auth plugins
- Improved `--help` output
- Improved `Content-Disposition` parsing for `--download` mode
- Update to Requests 2.0.0
## [0.6.0](https://github.com/httpie/httpie/compare/0.5.1...0.6.0) (2013-06-03)
- XML data is now formatted
- `--session` and `--session-read-only` now also accept paths to
session files (eg. `http --session=/tmp/session.json example.org`)
## [0.5.1](https://github.com/httpie/httpie/compare/0.5.0...0.5.1) (2013-05-13)
- `Content-*` and `If-*` request headers are not stored in sessions
anymore as they are request-specific
## [0.5.0](https://github.com/httpie/httpie/compare/0.4.1...0.5.0) (2013-04-27)
- Added a download mode via `--download`
- Fixes miscellaneous bugs
## [0.4.1](https://github.com/httpie/httpie/compare/0.4.0...0.4.1) (2013-02-26)
- Fixed `setup.py`
## [0.4.0](https://github.com/httpie/httpie/compare/0.3.0...0.4.0) (2013-02-22)
- Added Python 3.3 compatibility
- Added Requests >= v1.0.4 compatibility
- Added support for credentials in URL
- Added `--no-option` for every `--option` to be config-friendly
- Mutually exclusive arguments can be specified multiple times. The
last value is used
## [0.3.0](https://github.com/httpie/httpie/compare/0.2.7...0.3.0) (2012-09-21)
- Allow output redirection on Windows
- Added configuration file
- Added persistent session support
- Renamed `--allow-redirects` to `--follow`
- Improved the usability of `http --help`
- Fixed installation on Windows with Python 3
- Fixed colorized output on Windows with Python 3
- CRLF HTTP header field separation in the output
- Added exit status code `2` for timed-out requests
- Added the option to separate colorizing and formatting
(`--pretty=all`, `--pretty=colors` and `--pretty=format`)
`--ugly` has bee removed in favor of `--pretty=none`
## [0.2.7](https://github.com/httpie/httpie/compare/0.2.5...0.2.7) (2012-08-07)
- Added compatibility with Requests 0.13.6
- Added streamed terminal output. `--stream, -S` can be used to enable
streaming also with `--pretty` and to ensure a more frequent output
flushing
- Added support for efficient large file downloads
- Sort headers by name (unless `--pretty=none`)
- Response body is fetched only when needed (e.g., not with `--headers`)
- Improved content type matching
- Updated Solarized color scheme
- Windows: Added `--output FILE` to store output into a file
(piping results in corrupted data on Windows)
- Proper handling of binary requests and responses
- Fixed printing of `multipart/form-data` requests
- Renamed `--traceback` to `--debug`
## [0.2.6](https://github.com/httpie/httpie/compare/0.2.5...0.2.6) (2012-07-26)
- The short option for `--headers` is now `-h` (`-t` has been
removed, for usage use `--help`)
- Form data and URL parameters can have multiple fields with the same name
(e.g.,`http -f url a=1 a=2`)
- Added `--check-status` to exit with an error on HTTP 3xx, 4xx and
5xx (3, 4, and 5, respectively)
- If the output is piped to another program or redirected to a file,
the default behaviour is to only print the response body
(It can still be overwritten via the `--print` flag.)
- Improved highlighting of HTTP headers
- Added query string parameters (`param==value`)
- Added support for terminal colors under Windows
## [0.2.5](https://github.com/httpie/httpie/compare/0.2.2...0.2.5) (2012-07-17)
- Unicode characters in prettified JSON now don't get escaped for
improved readability
- --auth now prompts for a password if only a username provided
- Added support for request payloads from a file path with automatic
`Content-Type` (`http URL @/path`)
- Fixed missing query string when displaying the request headers via
`--verbose`
- Fixed Content-Type for requests with no data
## [0.2.2](https://github.com/httpie/httpie/compare/0.2.1...0.2.2) (2012-06-24)
- The `METHOD` positional argument can now be omitted (defaults to
`GET`, or to `POST` with data)
- Fixed --verbose --form
- Added support for Tox
## [0.2.1](https://github.com/httpie/httpie/compare/0.2.0...0.2.1) (2012-06-13)
- Added compatibility with `requests-0.12.1`
- Dropped custom JSON and HTTP lexers in favor of the ones newly included
in `pygments-1.5`
## [0.2.0](https://github.com/httpie/httpie/compare/0.1.6...0.2.0) (2012-04-25)
- Added Python 3 support
- Added the ability to print the HTTP request as well as the response
(see `--print` and `--verbose`)
- Added support for Digest authentication
- Added file upload support
(`http -f POST file_field_name@/path/to/file`)
- Improved syntax highlighting for JSON
- Added support for field name escaping
- Many bug fixes
## [0.1.6](https://github.com/httpie/httpie/compare/0.1.5...0.1.6) (2012-03-04)
- Fixed `setup.py`
## [0.1.5](https://github.com/httpie/httpie/compare/0.1.4...0.1.5) (2012-03-04)
- Many improvements and bug fixes
## [0.1.4](https://github.com/httpie/httpie/compare/b966efa...0.1.4) (2012-02-28)
- Many improvements and bug fixes
## [0.1.0](https://github.com/httpie/httpie/commit/b966efa) (2012-02-25)
- Initial public release

74
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,74 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or
advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic
address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at jakub@roztocil.co. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
version 1.4, available at <https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>
For answers to common questions about this code of conduct, see
<https://www.contributor-covenant.org/faq>

196
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,196 @@
# Contributing to HTTPie
Bug reports and code and documentation patches are welcome. You can
help this project also by using the development version of HTTPie
and by reporting any bugs you might encounter.
## 1. Reporting bugs
**It's important that you provide the full command argument list
as well as the output of the failing command.**
Use the `--debug` flag and copy&paste both the command and its output
to your bug report, e.g.:
```bash
$ http --debug <COMPLETE ARGUMENT LIST THAT TRIGGERS THE ERROR>
<COMPLETE OUTPUT>
```
## 2. Contributing Code and Docs
Before working on a new feature or a bug, please browse [existing issues](https://github.com/httpie/httpie/issues)
to see whether it has previously been discussed.
If your change alters HTTPies behaviour or interface, it's a good idea to
discuss it before you start working on it.
If you are fixing an issue, the first step should be to create a test case that
reproduces the incorrect behaviour. That will also help you to build an
understanding of the issue at hand.
**Pull requests introducing code changes without tests
will generally not get merged. The same goes for PRs changing HTTPies
behaviour and not providing documentation.**
Conversely, PRs consisting of documentation improvements or tests
for existing-yet-previously-untested behavior will very likely be merged.
Therefore, docs and tests improvements are a great candidate for your first
contribution.
Consider also adding a [CHANGELOG](https://github.com/httpie/httpie/blob/master/CHANGELOG.md) entry for your changes.
### Development Environment
#### Getting the code
Go to <https://github.com/httpie/httpie> and fork the project repository.
```bash
# Clone your fork
$ git clone git@github.com:<YOU>/httpie.git
# Enter the project directory
$ cd httpie
# Create a branch for your changes
$ git checkout -b my_topical_branch
```
#### Setup
The [Makefile](https://github.com/httpie/httpie/blob/master/Makefile) contains a bunch of tasks to get you started. Just run
the following command, which:
- Creates an isolated Python virtual environment inside `./venv`
(via the standard library [venv](https://docs.python.org/3/library/venv.html) tool);
- installs all dependencies and also installs HTTPie
(in editable mode so that the `http` command will point to your
working copy).
- and runs tests (It is the same as running `make install test`).
```bash
$ make
```
#### Python virtual environment
Activate the Python virtual environment—created via the `make install`
task during [setup](#setup) for your active shell session using the following command:
```bash
$ source venv/bin/activate
```
(If you use `virtualenvwrapper`, you can also use `workon httpie` to
activate the environment — we have created a symlink for you. Its a bit of
a hack but it works™.)
You should now see `(httpie)` next to your shell prompt, and
the `http` command should point to your development copy:
```bash
(httpie) ~/Code/httpie $ which http
/Users/<user>/Code/httpie/venv/bin/http
(httpie) ~/Code/httpie $ http --version
2.0.0-dev
```
(Btw, you dont need to activate the virtual environment if you just want
run some of the `make` tasks. You can also invoke the development
version of HTTPie directly with `./venv/bin/http` without having to activate
the environment first. The same goes for `./venv/bin/pytest`, etc.).
### Making Changes
Please make sure your changes conform to [Style Guide for Python Code](https://python.org/dev/peps/pep-0008/) (PEP8)
and that `make pycodestyle` passes.
### Testing & CI
Please add tests for any new features and bug fixes.
When you open a Pull Request, [GitHub Actions](https://github.com/httpie/httpie/actions) will automatically run HTTPies [test suite](https://github.com/httpie/httpie/tree/master/tests) against your code, so please make sure all checks pass.
#### Running tests locally
HTTPie uses the [pytest](https://pytest.org/) runner.
```bash
# Run tests on the current Python interpreter with coverage.
$ make test
# Run tests with coverage
$ make test-cover
# Test PEP8 compliance
$ make codestyle
# Run extended tests — for code as well as .md files syntax, packaging, etc.
$ make test-all
```
#### Running specific tests
After you have activated your virtual environment (see [setup](#setup)), you
can run specific tests from the terminal:
```bash
# Run specific tests on the current Python
$ python -m pytest tests/test_uploads.py
$ python -m pytest tests/test_uploads.py::TestMultipartFormDataFileUpload
$ python -m pytest tests/test_uploads.py::TestMultipartFormDataFileUpload::test_upload_ok
```
See [Makefile](https://github.com/httpie/httpie/blob/master/Makefile) for additional development utilities.
#### Windows
If you are on a Windows machine and not able to run `make`,
follow the next steps for a basic setup. As a prerequisite, you need to have
Python 3.6+ installed.
Create a virtual environment and activate it:
```powershell
C:\> python -m venv --prompt httpie venv
C:\> venv\Scripts\activate
```
Install HTTPie in editable mode with all the dependencies:
```powershell
C:\> python -m pip install --upgrade -e . -r requirements-dev.txt
```
You should now see `(httpie)` next to your shell prompt, and
the `http` command should point to your development copy:
```powershell
# In PowerShell:
(httpie) PS C:\Users\ovezovs\httpie> Get-Command http
CommandType Name Version Source
----------- ---- ------- ------
Application http.exe 0.0.0.0 C:\Users\ovezovs\httpie\venv\Scripts\http.exe
```
```bash
# In CMD:
(httpie) C:\Users\ovezovs\httpie> where http
C:\Users\ovezovs\httpie\venv\Scripts\http.exe
C:\Users\ovezovs\AppData\Local\Programs\Python\Python38-32\Scripts\http.exe
(httpie) C:\Users\ovezovs\httpie> http --version
2.3.0-dev
```
Use `pytest` to run tests locally with an active virtual environment:
```bash
# Run all tests
$ python -m pytest
```
______________________________________________________________________
Finally, feel free to add yourself to [AUTHORS](https://github.com/httpie/httpie/blob/master/AUTHORS.md)!

10
LICENSE
View File

@ -1,4 +1,4 @@
Copyright © 2012 Jakub Roztocil <jakub@roztocil.name>
Copyright © 2012-2021 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:
@ -10,14 +10,14 @@ modification, are permitted provided that the following conditions are met:
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of The author nor the names of its contributors may
be used to endorse or promote products derived from this software
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE FOR
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON

View File

@ -1 +1,8 @@
include README.rst LICENSE
include LICENSE
include README.md
include CHANGELOG.md
include AUTHORS.md
include docs/README.md
# <https://github.com/httpie/httpie/issues/182>
recursive-include tests/ *

212
Makefile Normal file
View File

@ -0,0 +1,212 @@
###############################################################################
# See ./CONTRIBUTING.md
###############################################################################
.PHONY: build
ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
VERSION=$(shell grep __version__ httpie/__init__.py)
H1="\n\n\033[0;32m\#\#\# "
H1END=" \#\#\# \033[0m\n"
# Only used to create our venv.
SYSTEM_PYTHON=python3
VENV_ROOT=venv
VENV_BIN=$(VENV_ROOT)/bin
VENV_PIP=$(VENV_BIN)/pip3
VENV_PYTHON=$(VENV_BIN)/python
export PATH := $(VENV_BIN):$(PATH)
all: uninstall-httpie install test
install: venv install-reqs
install-reqs:
@echo $(H1)Updating package tools$(H1END)
$(VENV_PIP) install --upgrade pip wheel
@echo $(H1)Installing dev requirements$(H1END)
$(VENV_PIP) install --upgrade --editable '.[dev]'
@echo $(H1)Installing HTTPie$(H1END)
$(VENV_PIP) install --upgrade --editable .
@echo
clean:
@echo $(H1)Cleaning up$(H1END)
rm -rf $(VENV_ROOT)
# Remove symlink for virtualenvwrapper, if weve created one.
[ -n "$(WORKON_HOME)" -a -L "$(WORKON_HOME)/httpie" -a -f "$(WORKON_HOME)/httpie" ] && rm $(WORKON_HOME)/httpie || true
rm -rf *.egg dist build .coverage .cache .pytest_cache httpie.egg-info
find . -name '__pycache__' -delete -o -name '*.pyc' -delete
@echo
venv:
@echo $(H1)Creating a Python environment $(VENV_ROOT) $(H1END)
$(SYSTEM_PYTHON) -m venv --prompt httpie $(VENV_ROOT)
@echo
@echo done.
@echo
@echo To active it manually, run:
@echo
@echo " source $(VENV_BIN)/activate"
@echo
@echo '(learn more: https://docs.python.org/3/library/venv.html)'
@echo
@if [ -n "$(WORKON_HOME)" ]; then \
echo $(ROOT_DIR) > $(VENV_ROOT)/.project; \
if [ ! -d $(WORKON_HOME)/httpie -a ! -L $(WORKON_HOME)/httpie ]; then \
ln -s $(ROOT_DIR)/$(VENV_ROOT) $(WORKON_HOME)/httpie ; \
echo ''; \
echo 'Since you use virtualenvwrapper, we created a symlink'; \
echo 'so you can also use "workon httpie" to activate the venv.'; \
echo ''; \
fi; \
fi
###############################################################################
# Testing
###############################################################################
test:
@echo $(H1)Running tests$(HEADER_EXTRA)$(H1END)
$(VENV_BIN)/python -m pytest $(COV)
@echo
test-cover: COV=--cov=httpie --cov=tests
test-cover: HEADER_EXTRA=' (with coverage)'
test-cover: test
# test-all is meant to test everything — even this Makefile
test-all: clean install test test-dist codestyle
@echo
test-dist: test-sdist test-bdist-wheel
@echo
test-sdist: clean venv
@echo $(H1)Testing sdist build an installation$(H1END)
$(VENV_PYTHON) setup.py sdist
$(VENV_PIP) install --force-reinstall --upgrade dist/*.gz
$(VENV_BIN)/http --version
@echo
test-bdist-wheel: clean venv
@echo $(H1)Testing wheel build an installation$(H1END)
$(VENV_PIP) install wheel
$(VENV_PYTHON) setup.py bdist_wheel
$(VENV_PIP) install --force-reinstall --upgrade dist/*.whl
$(VENV_BIN)/http --version
@echo
twine-check:
twine check dist/*
# Kept for convenience, "make codestyle" is preferred though
pycodestyle: codestyle
codestyle:
@echo $(H1)Running flake8$(H1END)
@[ -f $(VENV_BIN)/flake8 ] || $(VENV_PIP) install --upgrade --editable '.[dev]'
$(VENV_BIN)/flake8 httpie/ tests/ docs/packaging/brew/ *.py
@echo
codecov-upload:
@echo $(H1)Running codecov$(H1END)
@[ -f $(VENV_BIN)/codecov ] || $(VENV_PIP) install codecov
# $(VENV_BIN)/codecov --required
$(VENV_BIN)/codecov
@echo
doc-check:
@echo $(H1)Running documentations checks$(H1END)
mdl --git-recurse --style docs/markdownlint.rb .
doc-update-install:
@echo $(H1)Updating installation instructions in the docs$(H1END)
$(VENV_PYTHON) docs/installation/generate.py
###############################################################################
# Publishing to PyPi
###############################################################################
build:
rm -rf build/
$(VENV_PYTHON) setup.py sdist bdist_wheel
publish: test-all publish-no-test
publish-no-test:
@echo $(H1)Testing wheel build an installation$(H1END)
@echo "$(VERSION)"
@echo "$(VERSION)" | grep -q "dev" && echo '!!!Not publishing dev version!!!' && exit 1 || echo ok
make build
make twine-check
$(VENV_BIN)/twine upload --repository=httpie dist/*
@echo
###############################################################################
# Uninstalling
###############################################################################
uninstall-httpie:
@echo $(H1)Uninstalling httpie$(H1END)
- $(VENV_PIP) uninstall --yes httpie &2>/dev/null
@echo "Verifying…"
cd .. && ! $(VENV_PYTHON) -m httpie --version &2>/dev/null
@echo "Done"
@echo
###############################################################################
# Homebrew
###############################################################################
brew-deps:
docs/packaging/brew/brew-deps.py
brew-test:
@echo $(H1)Uninstalling httpie$(H1END)
- brew uninstall httpie
@echo $(H1)Building from source…$(H1END)
- brew install --build-from-source ./docs/packaging/brew/httpie.rb
@echo $(H1)Verifying…$(H1END)
brew test httpie
@echo $(H1)Auditing…$(H1END)
brew audit --strict httpie

84
README.md Normal file
View File

@ -0,0 +1,84 @@
<br/>
<a href="https://httpie.io" target="blank_">
<img height="100" alt="HTTPie" src="https://raw.githubusercontent.com/httpie/httpie/master/docs/httpie-logo.svg" />
</a>
<br/>
# HTTPie: human-friendly CLI HTTP client for the API era
HTTPie (pronounced _aitch-tee-tee-pie_) is a command-line HTTP client.
Its goal is to make CLI interaction with web services as human-friendly as possible.
HTTPie is designed for testing, debugging, and generally interacting with APIs & HTTP servers.
The `http` & `https` commands allow for creating and sending arbitrary HTTP requests.
They use simple and natural syntax and provide formatted and colorized output.
[![Docs](https://img.shields.io/badge/stable%20docs-httpie.io%2Fdocs-brightgreen?style=flat&color=%2373DC8C&label=Docs)](https://httpie.org/docs)
[![Latest version](https://img.shields.io/pypi/v/httpie.svg?style=flat&label=Latest&color=%234B78E6&logo=&logoColor=white)](https://pypi.python.org/pypi/httpie)
[![Build](https://img.shields.io/github/workflow/status/httpie/httpie/Build?color=%23FA9BFA&label=Build)](https://github.com/httpie/httpie/actions)
[![Coverage](https://img.shields.io/codecov/c/github/httpie/httpie?style=flat&label=Coverage&color=%2373DC8C)](https://codecov.io/gh/httpie/httpie)
[![Twitter](https://img.shields.io/twitter/follow/httpie?style=flat&color=%234B78E6&logoColor=%234B78E6)](https://twitter.com/httpie)
[![Chat](https://img.shields.io/badge/chat-Discord-brightgreen?style=flat&label=Chat%20on&color=%23FA9BFA)](https://httpie.io/discord)
<img src="https://raw.githubusercontent.com/httpie/httpie/master/docs/httpie-animation.gif" alt="HTTPie in action" width="100%"/>
## Getting started
- [Installation instructions →](https://httpie.io/docs#installation)
- [Full documentation →](https://httpie.io/docs)
## Features
- Expressive and intuitive syntax
- Formatted and colorized terminal output
- Built-in JSON support
- Forms and file uploads
- HTTPS, proxies, and authentication
- Arbitrary request data
- Custom headers
- Persistent sessions
- `wget`-like downloads
[See all features →](https://httpie.io/docs)
## Examples
Hello World:
```bash
$ https httpie.io/hello
```
Custom [HTTP method](https://httpie.io/docs#http-method), [HTTP headers](https://httpie.io/docs#http-headers) and [JSON](https://httpie.io/docs#json) data:
```bash
$ http PUT pie.dev/put X-API-Token:123 name=John
```
Build and print a request without sending it using [offline mode](https://httpie.io/docs#offline-mode):
```bash
$ http --offline pie.dev/post hello=offline
```
Use [GitHub API](https://developer.github.com/v3/issues/comments/#create-a-comment) to post a comment on an [Issue](https://github.com/httpie/httpie/issues/83) with [authentication](https://httpie.io/docs#authentication):
```bash
$ http -a USERNAME POST https://api.github.com/repos/httpie/httpie/issues/83/comments body='HTTPie is awesome! :heart:'
```
[See more examples →](https://httpie.io/docs#examples)
## Community & support
- Visit the [HTTPie website](https://httpie.io) for full documentation and useful links.
- Join our [Discord server](https://httpie.io/discord) is to ask questions, discuss features, and for general API chat.
- Tweet at [@httpie](https://twitter.com/httpie) on Twitter.
- Use [StackOverflow](https://stackoverflow.com/questions/tagged/httpie) to ask questions and include a `httpie` tag.
- Create [GitHub Issues](https://github.com/httpie/httpie/issues) for bug reports and feature requests.
- Subscribe to the [HTTPie newsletter](https://httpie.io) for occasional updates.
## Contributing
Have a look through existing [Issues](https://github.com/httpie/httpie/issues) and [Pull Requests](https://github.com/httpie/httpie/pulls) that you could help with. If you'd like to request a feature or report a bug, please [create a GitHub Issue](https://github.com/httpie/httpie/issues) using one of the templates provided.
[See contribution guide →](https://github.com/httpie/httpie/blob/master/CONTRIBUTING.md)

View File

@ -1,202 +0,0 @@
HTTPie: cURL for humans
=======================
**HTTPie is a CLI HTTP utility** built out of frustration with existing tools. The goal is to make CLI interaction with HTTP-based services as human-friendly as possible.
HTTPie does so by providing an ``http`` command that allows for issuing arbitrary HTTP requests using a **simple and natural syntax** and displaying **colorized responses**:
.. image:: https://github.com/jkbr/httpie/raw/master/httpie.png
:alt: HTTPie compared to cURL
Under the hood, HTTPie uses the excellent `Requests <http://python-requests.org>`_ and `Pygments <http://pygments.org/>`_ Python libraries. Python 2.6+ is supported (including 3.x).
Installation
------------
The latest **stable version** of HTTPie can always be installed (or updated to) via `pip <http://www.pip-installer.org/en/latest/index.html>`_::
pip install -U httpie
Or, you can install the **development version** directly from GitHub:
.. image:: https://secure.travis-ci.org/jkbr/httpie.png
:target: http://travis-ci.org/jkbr/httpie
:alt: Build Status of the master branch
::
pip install -U https://github.com/jkbr/httpie/tarball/master
Usage
-----
Hello world::
http GET httpie.org
Synopsis::
http [flags] METHOD URL [items]
There are four types of key-value pair items available:
Headers (``Name:Value``)
Arbitrary HTTP headers. The ``:`` character is used to separate a header's name from its value, e.g., ``X-API-Token:123``.
Simple data fields (``field=value``)
Data items are included in the request body. Depending on the ``Content-Type``, they are automatically serialized as a JSON ``Object`` (default) or ``application/x-www-form-urlencoded`` (the ``-f`` flag). Data items use ``=`` as the separator, e.g., ``hello=world``.
Raw JSON fields (``field:=value``)
This item type is needed when ``Content-Type`` is JSON and a field's value is a ``Boolean``, ``Number``, nested ``Object`` or an ``Array``, because simple data items are always serialized as ``String``. E.g. ``pies:=[1,2,3]``.
File fields (``field@/path/to/file``)
Only available with ``-f`` / ``--form``. Use ``@`` as the separator, e.g., ``screenshot@/path/to/file.png``. The presence of a file field results into a ``multipart/form-data`` request.
Examples
^^^^^^^^
::
http PATCH api.example.com/person/1 X-API-Token:123 name=John email=john@example.org age:=29
The following request is issued::
PATCH /person/1 HTTP/1.1
User-Agent: HTTPie/0.1
X-API-Token: 123
Content-Type: application/json; charset=utf-8
{"name": "John", "email": "john@example.org", "age": 29}
It can easily be changed to a 'form' request using the ``-f`` (or ``--form``) flag, which produces::
PATCH /person/1 HTTP/1.1
User-Agent: HTTPie/0.1
X-API-Token: 123
Content-Type: application/x-www-form-urlencoded; charset=utf-8
age=29&name=John&email=john%40example.org
It is also possible to send ``multipart/form-data`` requests, i.e., to simulate a file upload form submission. It is done using the ``--form`` / ``-f`` flag and passing one or more file fields::
http -f POST example.com/jobs name=John cv@~/Documents/cv.pdf
The above will send the same request as if the following HTML form were submitted::
<form enctype="multipart/form-data" method="post" action="http://example.com/jobs">
<input type="text" name="name" />
<input type="file" name="cv" />
</form>
A whole request body can be passed in via ``stdin`` instead::
echo '{"name": "John"}' | http PATCH example.com/person/1 X-API-Token:123
# Or:
http POST example.com/person/1 X-API-Token:123 < person.json
Flags
^^^^^
Most of the flags mirror the arguments understood by ``requests.request``. See ``http -h`` for more details::
usage: http [-h] [--version] [--json | --form] [--traceback]
[--pretty | --ugly]
[--print OUTPUT_OPTIONS | --verbose | --headers | --body]
[--style STYLE] [--auth AUTH] [--auth-type {basic,digest}]
[--verify VERIFY] [--proxy PROXY] [--allow-redirects]
[--timeout TIMEOUT]
METHOD URL [ITEM [ITEM ...]]
HTTPie - cURL for humans. <http://httpie.org>
positional arguments:
METHOD The HTTP method to be used for the request (GET, POST,
PUT, DELETE, PATCH, ...).
URL The protocol defaults to http:// if the URL does not
include one.
ITEM A key-value pair whose type is defined by the
separator used. It can be an HTTP header
(header:value), a data field to be used in the request
body (field_name=value), a raw JSON data field
(field_name:=value) or a file field
(field_name@/path/to/file). You can use a backslash to
escape a colliding separator in the field name.
optional arguments:
-h, --help show this help message and exit
--version show program's version number and exit
--json, -j (default) Data items are serialized as a JSON object.
The Content-Type and Accept headers are set to
application/json (if not set via the command line).
--form, -f Data items are serialized as form fields. The Content-
Type is set to application/x-www-form-urlencoded (if
not specifid). The presence of any file fields results
into a multipart/form-data request.
--traceback Print exception traceback should one occur.
--pretty If stdout is a terminal, the response is prettified by
default (colorized and indented if it is JSON). This
flag ensures prettifying even when stdout is
redirected.
--ugly, -u Do not prettify the response.
--print OUTPUT_OPTIONS, -p OUTPUT_OPTIONS
String specifying what should the output contain. "H"
stands for the request headers and "B" for the request
body. "h" stands for the response headers and "b" for
response the body. Defaults to "hb" which means that
the whole response (headers and body) is printed.
--verbose, -v Print the whole request as well as the response.
Shortcut for --print=HBhb.
--headers, -t Print only the response headers. Shortcut for
--print=h.
--body, -b Print only the response body. Shortcut for --print=b.
--style STYLE, -s STYLE
Output coloring style, one of autumn, borland, bw,
colorful, default, emacs, friendly, fruity, manni,
monokai, murphy, native, pastie, perldoc, solarized,
tango, trac, vim, vs. Defaults to solarized. For this
option to work properly, please make sure that the
$TERM environment variable is set to "xterm-256color"
or similar (e.g., via `export TERM=xterm-256color' in
your ~/.bashrc).
--auth AUTH, -a AUTH username:password
--auth-type {basic,digest}
The authentication mechanism to be used. Defaults to
"basic".
--verify VERIFY Set to "no" to skip checking the host's SSL
certificate. You can also pass the path to a CA_BUNDLE
file for private certs. You can also set the
REQUESTS_CA_BUNDLE environment variable. Defaults to
"yes".
--proxy PROXY String mapping protocol to the URL of the proxy (e.g.
http:foo.bar:3128).
--allow-redirects Set this flag if full redirects are allowed (e.g. re-
POST-ing of data at new ``Location``)
--timeout TIMEOUT Float describes the timeout of the request (Use
socket.setdefaulttimeout() as fallback).
Contributors
------------
`View contributors on GitHub <https://github.com/jkbr/httpie/contributors>`_.
Changelog
---------
* `New in development version <https://github.com/jkbr/httpie/compare/0.2.0...master>`_
* 0.2.0 (2012-04-25)
* Added Python 3 support.
* Added the ability to print the HTTP request as well as the response (see ``--print`` and ``--verbose``).
* Added support for Digest authentication.
* Added file upload support (``http -f POST file_field_name@/path/to/file``).
* Improved syntax highlighting for JSON.
* Added support for field name escaping.
* Many bug fixes.
* `Complete changelog <https://github.com/jkbr/httpie/compare/0.1.6...0.2.0>`_
* `0.1.6 <https://github.com/jkbr/httpie/compare/0.1.4...0.1.6>`_ (2012-03-04)

1979
docs/README.md Normal file

File diff suppressed because it is too large Load Diff

5
docs/config.json Normal file
View File

@ -0,0 +1,5 @@
{
"website": {
"master_and_released_docs_differ_after": "8f8851f1dbd511d3bc0ea0f6da7459045610afce"
}
}

BIN
docs/httpie-animation.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1019 KiB

1
docs/httpie-logo.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1635.31 470"><defs><style>.cls-1{fill:#4b78e6;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M1322.19,73.91h0a36.56,36.56,0,0,1,36.56-36.29h3.41a36.56,36.56,0,0,1,36.56,36.83h0a36.56,36.56,0,0,1-36.56,36.29h-3.41A36.56,36.56,0,0,1,1322.19,73.91Zm6.16,276.93V142.35a7.94,7.94,0,0,1,8-7.94h48.32a7.93,7.93,0,0,1,7.94,7.94V350.84a7.94,7.94,0,0,1-7.94,7.94H1336.3A8,8,0,0,1,1328.35,350.84Z"/><path class="cls-1" d="M1635.31,233.34c0-61.06-33.28-105.09-101.71-105.09-72.17,0-114.82,45.45-114.82,123.08,0,74.79,46.86,113.6,113.89,113.6,56.83,0,85.93-27.17,98.33-63.86a8,8,0,0,0-5.34-10.28l-40.32-11.39a8,8,0,0,0-9.54,4.73c-5.77,14.37-16.57,25.42-42.2,25.42-29.32,0-46.06-13.62-50.74-44.29a7.17,7.17,0,0,0,.81.08h143.7a8,8,0,0,0,7.94-7.94V242.23c0-.09,0-.18,0-.28C1635.31,239.17,1635.31,236.36,1635.31,233.34Zm-103.58-51.6c28.59,0,43.12,15.15,45,45H1483C1487.21,195,1503.61,181.74,1531.73,181.74Z"/><path class="cls-1" d="M581.91,358.75H533.56a7.93,7.93,0,0,1-7.94-7.94V76.39a7.93,7.93,0,0,1,7.94-7.94h48.35a7.93,7.93,0,0,1,7.94,7.94v84.66a6,6,0,0,0,11.22,2.77c13.45-25.56,34.68-35.33,60.42-35.69,38.66-.55,70,31.45,70,70.12V350.81a7.94,7.94,0,0,1-7.94,7.94H675.63a7.94,7.94,0,0,1-7.94-7.94V227.1c0-23.21-10.32-40.73-37-40.73-25.79,0-40.8,15.15-40.8,40.73V350.81A7.93,7.93,0,0,1,581.91,358.75Z"/><path class="cls-1" d="M1052.84,306.12a7.94,7.94,0,0,0-9.77-6.78c-6.47,1.55-13.73,3.05-20.35,3.05-19.23,0-25.79-8.52-25.79-26.52V188.26h50.67a7.94,7.94,0,0,0,7.94-7.94v-38.1a8,8,0,0,0-7.94-7.95H996.93V85.86A7.94,7.94,0,0,0,989,77.92H941.1a7.93,7.93,0,0,0-7.94,7.94v48.41H842.67V85.86a7.94,7.94,0,0,0-7.94-7.94H786.84a7.93,7.93,0,0,0-7.94,7.94v48.41H761.05a7.94,7.94,0,0,0-7.94,7.95v38.1a7.93,7.93,0,0,0,7.94,7.94H778.9v99.93c0,42.62,21.57,77.19,73.15,77.19,21.16,0,32.43-2.5,46.08-6.56a8,8,0,0,0,5.65-8.56l-5.2-44.14a7.94,7.94,0,0,0-9.77-6.78c-6.47,1.55-13.73,3.05-20.35,3.05-19.23,0-25.79-8.52-25.79-26.52V188.26h90.49v99.93c0,42.62,21.57,77.19,73.14,77.19,21.17,0,32.44-2.5,46.09-6.56a8,8,0,0,0,5.65-8.56Z"/><path class="cls-1" d="M1219.14,365.27c-28.49,0-49.51-10.92-62.87-35.86a6,6,0,0,0-11.19,2.84v82.83a7.93,7.93,0,0,1-7.94,7.94h-48.32a7.94,7.94,0,0,1-8-7.94V142.21a8,8,0,0,1,8-7.94h48.32a7.94,7.94,0,0,1,7.94,7.94v18.95c0,6.13,8.21,8.3,11.15,2.92,13.74-25.16,35.63-36,64.31-36,53.43,0,81.08,44,81.08,116.92C1301.62,320.78,1273,365.27,1219.14,365.27Zm19.21-119.76c0-37.39-14.06-59.17-46.4-59.17-29.53,0-46.87,20.35-46.87,57.28v4.26c0,36.45,17.34,59.17,46.87,59.17C1223.82,307.05,1238.35,284.33,1238.35,245.51Z"/><path class="cls-1" d="M394.41,102.12C394,45.31,346.61,0,289.8,0H104.69C48.31,0,1.09,44.6,0,101A103.07,103.07,0,0,0,103,205.92h82.7a6,6,0,0,1,2.39,11.42L61.31,272.91A103.09,103.09,0,0,0,0,367.83C.43,424.65,47.79,470,104.62,470H148c57.23,0,104.88-45.9,104.79-103.13a103.1,103.1,0,0,0-64.49-95.31,5.94,5.94,0,0,1-.1-10.94l145-63.58A103.08,103.08,0,0,0,394.41,102.12Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,5 @@
Here we maintain a database of installation methods, from which we generate
the installation section in docs. If youd like add or update an installation method,
edit [methods.yml](./methods.yml), do not edit the main docs directly.
For HTTPie installation instructions see: <https://httpie.io/docs#installation>.

View File

@ -0,0 +1,85 @@
import re
import sys
from pathlib import Path
from typing import Dict
import yaml
from jinja2 import Template
Database = Dict[str, dict]
# Files
HERE = Path(__file__).parent
DB_FILE = HERE / 'methods.yml'
DOC_FILE = HERE.parent / 'README.md'
TPL_FILE = HERE / 'installation.jinja2'
# Database keys
KEY_DOC_STRUCTURE = 'docs-structure'
KEY_TOOLS = 'tools'
# Markers in-between content will be put.
MARKER_START = '<div data-installation-instructions>'
MARKER_END = '</div>'
def generate_documentation() -> str:
database = load_database()
structure = build_docs_structure(database)
template = Template(source=TPL_FILE.read_text(encoding='utf-8'))
output = template.render(structure=structure)
output = clean_template_output(output)
return output
def save_doc_file(content: str) -> None:
current_doc = load_doc_file()
marker_start = current_doc.find(MARKER_START) + len(MARKER_START)
assert marker_start > 0, 'cannot find the start marker'
marker_end = current_doc.find(MARKER_END, marker_start)
assert marker_start < marker_end, f'{marker_end=} < {marker_start=}'
updated_doc = (
current_doc[:marker_start]
+ '\n\n'
+ content
+ '\n\n'
+ current_doc[marker_end:]
)
if current_doc != updated_doc:
DOC_FILE.write_text(updated_doc, encoding='utf-8')
def build_docs_structure(database: Database):
tools = database[KEY_TOOLS]
assert len(tools) == len({tool['title'] for tool in tools.values()}), 'tool titles need to be unique'
tree = database[KEY_DOC_STRUCTURE]
structure = []
for platform, tools_ids in tree.items():
assert platform.isalnum(), f'{platform=} must be alpha-numeric for generated links to work'
platform_tools = [tools[tool_id] for tool_id in tools_ids]
structure.append((platform, platform_tools))
return structure
def clean_template_output(output):
output = '\n'.join(line.strip() for line in output.strip().splitlines())
output = re.sub('\n{3,}', '\n\n', output)
return output
def load_database() -> Database:
return yaml.safe_load(DB_FILE.read_text(encoding='utf-8'))
def load_doc_file() -> str:
return DOC_FILE.read_text(encoding='utf-8')
def main() -> int:
content = generate_documentation()
save_doc_file(content)
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@ -0,0 +1,37 @@
<!--
THE INSTALLATION SECTION IS GENERATED
Do not edit here, but in docs/installation/.
-->
{% for platform, tools in structure %}
- [{{ platform }}](#{{ platform.lower() }}){% endfor %} {# <= keep `endfor` here to prevent unwanted `\n` #}
{% for platform, tools in structure %}
### {{ platform }}
{% for tool in tools %}
#### {{ tool.title }}
{% if tool.note %}
{{ tool.note }}
{% endif %}
{% if tool.links.setup %}
To install [{{ tool.name }}]({{ tool.links.homepage }}) follow [installation instructions]({{ tool.links.setup }}).
{% endif %}
```bash
# Install
$ {{ tool.commands.install|join('\n$ ') }}
```
```bash
# Upgrade
$ {{ tool.commands.upgrade|join('\n$ ') }}
```
{% endfor %}
{% endfor %}
<!-- /GENERATED SECTION -->

View File

@ -0,0 +1,269 @@
# Database of HTTPie installation methods. Used to build the docs.
#
# We currently only include here methods for popular systems where we take care of the package,
# or have a good relationship with the maintainers.
#
# Each tool name should be unique (it becomes a linkable header).
# If a tools have `links.setup`, it also needs `links.homepage`.
# Some tools are available on multiple platforms, take into account when editing.
#
docs-structure:
Universal:
- pypi
macOS:
- brew-mac
- port
- snap-mac
- spack-mac
Windows:
- chocolatey
Linux:
- snap-linux
- brew-linux
- apt
- dnf
- yum
- apk
- emerge
- pacman
- xbps-install
- spack-linux
FreeBSD:
- pkg
tools:
apk:
title: Alpine Linux
name: apk
links:
homepage: https://wiki.alpinelinux.org/wiki/Alpine_Linux_package_management
package: https://pkgs.alpinelinux.org/package/edge/community/x86/httpie
commands:
install:
- apk update
- apk add httpie
upgrade:
- apk update
- apk add --upgrade httpie
apt:
title: Debian and Ubuntu
note: Also works for other Debian-derived distributions like MX Linux, Linux Mint, deepin, Pop!_OS, KDE neon, Zorin OS, elementary OS, Kubuntu, Devuan, Linux Lite, Peppermint OS, Lubuntu, antiX, Xubuntu, etc.
name: APT
links:
homepage: https://en.wikipedia.org/wiki/APT_(software)
package: https://packages.debian.org/sid/web/httpie
commands:
install:
- apt update
- apt install httpie
upgrade:
- apt update
- apt upgrade httpie
brew-mac:
title: Homebrew
name: Homebrew
links:
homepage: https://brew.sh/
setup: https://docs.brew.sh/Installation
package: https://formulae.brew.sh/formula/httpie
commands:
install:
- brew update
- brew install httpie
upgrade:
- brew update
- brew upgrade httpie
brew-linux:
title: Linuxbrew
name: Linuxbrew
links:
homepage: https://docs.brew.sh/Homebrew-on-Linux
setup: https://docs.brew.sh/Homebrew-on-Linux#install
package: https://formulae.brew.sh/formula/httpie
commands:
install:
- brew update
- brew install httpie
upgrade:
- brew update
- brew upgrade httpie
chocolatey:
title: Chocolatey
name: Chocolatey
links:
homepage: https://chocolatey.org/
setup: https://chocolatey.org/install
package: https://community.chocolatey.org/packages/httpie/
commands:
install:
- choco install httpie
upgrade:
- choco upgrade httpie
dnf:
title: Fedora
name: DNF
links:
homepage: https://fedoraproject.org/wiki/DNF
package: https://src.fedoraproject.org/rpms/httpie
commands:
install:
- dnf update
- dnf install httpie
upgrade:
- dnf update
- dnf upgrade httpie
emerge:
title: Gentoo
name: Portage
links:
homepage: https://wiki.gentoo.org/wiki/Portage
package: https://packages.gentoo.org/packages/net-misc/httpie
commands:
install:
- emerge --sync
- emerge httpie
upgrade:
- emerge --sync
- emerge --update httpie
pacman:
title: Arch Linux
name: pacman
note: Also works for other Arch-derived distributions like ArcoLinux, EndeavourOS, Artix Linux, etc.
links:
homepage: https://archlinux.org/pacman/
package: https://archlinux.org/packages/community/any/httpie/
commands:
install:
- pacman -Sy httpie
upgrade:
- pacman -Syu httpie
pkg:
title: FreshPorts
name: FreshPorts
links:
homepage: https://www.freebsd.org/cgi/man.cgi?query=pkg&sektion=8&n=1
package: https://www.freshports.org/www/py-httpie/
commands:
install:
- pkg install www/py-httpie
upgrade:
- pkg upgrade www/py-httpie
port:
title: MacPorts
name: MacPorts
links:
homepage: https://www.macports.org/
setup: https://www.macports.org/install.php
package: https://ports.macports.org/port/httpie/
commands:
install:
- port selfupdate
- port install httpie
upgrade:
- port selfupdate
- port upgrade httpie
pypi:
title: PyPi
name: pip
note: Please make sure you have Python 3.6 or newer (`python --version`).
links:
homepage: https://pypi.org/
# setup: https://pip.pypa.io/en/stable/installation/
package: https://pypi.org/project/httpie/
commands:
install:
- python -m pip install --upgrade pip wheel
- python -m pip install httpie
upgrade:
- python -m pip install --upgrade pip wheel
- python -m pip install --upgrade httpie
snap-linux:
title: Snapcraft (Linux)
name: Snapcraft
links:
homepage: https://snapcraft.io/
setup: https://snapcraft.io/docs/installing-snapd
package: https://snapcraft.io/httpie
commands:
install:
- snap install httpie
upgrade:
- snap refresh httpie
snap-mac:
title: Snapcraft (macOS)
name: Snapcraft
links:
homepage: https://snapcraft.io/
setup: https://snapcraft.io/docs/installing-snapd
package: https://snapcraft.io/httpie
commands:
install:
- snap install httpie
upgrade:
- snap refresh httpie
spack-linux:
title: Spack (Linux)
name: Spack
links:
homepage: https://spack.readthedocs.io/en/latest/index.html
setup: https://spack.readthedocs.io/en/latest/getting_started.html#installation
commands:
install:
- spack install httpie
upgrade:
- spack install httpie
spack-mac:
title: Spack (macOS)
name: Spack
links:
homepage: https://spack.readthedocs.io/en/latest/index.html
setup: https://spack.readthedocs.io/en/latest/getting_started.html#installation
commands:
install:
- spack install httpie
upgrade:
- spack install httpie
xbps-install:
title: Void Linux
name: XBPS
links:
homepage: https://docs.voidlinux.org/xbps/index.html
commands:
install:
- xbps-install -Su
- xbps-install -S httpie
upgrade:
- xbps-install -Su
- xbps-install -Su httpie
yum:
title: CentOS and RHEL
name: Yum
note: Also works for other RHEL-derived distributions like ClearOS, Oracle Linux, etc.
links:
homepage: http://yum.baseurl.org/
package: https://src.fedoraproject.org/rpms/httpie
commands:
install:
- yum update
- yum install epel-release
- yum install httpie
upgrade:
- yum update
- yum upgrade httpie

41
docs/markdownlint.rb Normal file
View File

@ -0,0 +1,41 @@
# Rules for <https://github.com/markdownlint/markdownlint>
# Load all rules by default
all
#
# Tweak rules
#
# MD002 First header should be a top level header
# Because we use HTML to hide them on the website.
exclude_rule 'MD002'
# MD013 Line length
exclude_rule 'MD013'
# MD014 Dollar signs used before commands without showing output
exclude_rule 'MD014'
# Tell the linter to use ordered lists:
# 1. Foo
# 2. Bar
# 3. Baz
#
# Instead of:
# 1. Foo
# 1. Bar
# 1. Baz
rule 'MD029', :style => :ordered
# MD033 Inline HTML
# TODO: Tweak elements when https://github.com/markdownlint/markdownlint/issues/118 will be done?
exclude_rule 'MD033'
# MD034 Bare URL used
# TODO: Remove when https://github.com/markdownlint/markdownlint/issues/328 will be fixed.
exclude_rule 'MD034'
# MD041 First line in file should be a top level header
# Because we use HTML to hide them on the website.
exclude_rule 'MD041'

49
docs/packaging/README.md Normal file
View File

@ -0,0 +1,49 @@
# HTTPie release process
Welcome on the documentation part of the **HTTPie release process**.
- If you do not know HTTPie, have a look [here](https://httpie.io/cli).
- If you are looking for HTTPie installation or upgrade instructions, then you can find all you need for your OS on [that page](https://httpie.io/docs#installation). In the case you do not find your OS, [let us know](https://github.com/httpie/httpie/issues/).
- If you are looking for technical information about the HTTPie packaging, then you are at the good place.
## About
You are looking at the HTTPie packaging documentation, where you will find valuable information about how we manage to release HTTPie to lots of OSes, including technical data that may be worth reading if you are a package maintainer.
The overall release process starts simple:
1. Do the [PyPi](https://pypi.org/project/httpie/) publication.
2. Then, handle company-related tasks.
3. Finally, follow OS-specific steps, described in documents below, to send patches downstream.
## First, PyPi
Let's do the release on [PyPi](https://pypi.org/project/httpie/).
That is done quite easily by manually triggering the [release workflow](https://github.com/httpie/httpie/actions/workflows/release.yml).
## Then, company-specific tasks
- Update the HTTPie version bundled into termible ([example](https://github.com/httpie/termible/pull/1)).
## Finally, spread dowstream
Find out how we do release new versions for each and every supported OS in the following table.
A more complete state of deployment can be found on [repology](https://repology.org/project/httpie/versions), including unofficial packages.
| OS | Maintainer |
| -------------------------------------------: | -------------- |
| [Alpine](linux-alpine/) | **HTTPie** |
| [Arch Linux, and derived](linux-arch/) | trusted person |
| :construction: [AOSC OS](linux-aosc/) | **HTTPie** |
| [CentOS, RHEL, and derived](linux-centos/) | trusted person |
| [Debian, Ubuntu, and derived](linux-debian/) | trusted person |
| [Fedora](linux-fedora/) | trusted person |
| [Gentoo](linux-gentoo/) | **HTTPie** |
| :construction: [Homebrew, Linuxbrew](brew/) | **HTTPie** |
| :construction: [MacPorts](mac-ports/) | **HTTPie** |
| [Snapcraft](snapcraft/) | **HTTPie** |
| [Spack](spack/) | **HTTPie** |
| [Void Linux](linux-void/) | **HTTPie** |
| [Windows — Chocolatey](windows-chocolatey/) | **HTTPie** |
:new: You do not find your system or you would like to see HTTPie supported on another OS? Then [let us know](https://github.com/httpie/httpie/issues/).

View File

@ -0,0 +1,33 @@
# HTTPie on Homebrew, and Linuxbrew
Welcome to the documentation about **packaging HTTPie for Homebrew**.
- If you do not know HTTPie, have a look [here](https://httpie.io/cli).
- If you are looking for HTTPie installation or upgrade instructions on Homebrew, then you can find them on [that page](https://httpie.io/docs#homebrew) ([that one](https://httpie.io/docs#linuxbrew) for Linuxbrew).
- If you are looking for technical information about the HTTPie packaging on Homebrew, then you are in a good place.
## About
This document contains technical details, where we describe how to create a patch for the latest HTTPie version for Homebrew. They apply to Linuxbrew as well.
We will discuss setting up the environment, installing development tools, installing and testing changes before submitting a patch downstream.
## Overall process
:construction: Work in progress.
First, update the current Formula:
```bash
make brew-deps
# Copy-paste content into downstream/mac/brew/httpie.rb
git add downstream/mac/brew/httpie.rb
git commit -s -m 'Update brew formula to XXX'
```
That [GitHub workflow](https://github.com/httpie/httpie/actions/workflows/test-package-mac-brew.yml) will test the formula when `downstream/mac/brew/httpie.rb` is changed in a pull request.
Then, open a pull request with those changes to the [downstream file]([ file](https://github.com/Homebrew/homebrew-core/blob/master/Formula/httpie.rb)).
## Hacking
:construction: Work in progress.

View File

@ -0,0 +1,80 @@
#!/usr/bin/env python3
"""
Generate Ruby code with URLs and file hashes for packages from PyPi
(i.e., httpie itself as well as its dependencies) to be included
in the Homebrew formula after a new release of HTTPie has been published
on PyPi.
<https://github.com/Homebrew/homebrew-core/blob/master/Formula/httpie.rb>
"""
import hashlib
import requests
VERSIONS = {
# By default, we use the latest packages. But sometimes Requests has a maximum supported versions.
# Take a look here before making a release: <https://github.com/psf/requests/blob/master/setup.py>
'idna': '3.2',
}
# Note: Keep that list sorted.
PACKAGES = [
'certifi',
'charset-normalizer',
'defusedxml',
'httpie',
'idna',
'Pygments',
'PySocks',
'requests',
'requests-toolbelt',
'urllib3',
]
def get_package_meta(package_name):
api_url = f'https://pypi.org/pypi/{package_name}/json'
resp = requests.get(api_url).json()
hasher = hashlib.sha256()
version = VERSIONS.get(package_name)
if package_name not in VERSIONS:
# Latest version
release_bundle = resp['urls']
else:
release_bundle = resp['releases'][version]
for release in release_bundle:
download_url = release['url']
if download_url.endswith('.tar.gz'):
hasher.update(requests.get(download_url).content)
return {
'name': package_name,
'url': download_url,
'sha256': hasher.hexdigest(),
}
else:
raise RuntimeError(f'{package_name}: download not found: {resp}')
def main():
package_meta_map = {
package_name: get_package_meta(package_name)
for package_name in PACKAGES
}
httpie_meta = package_meta_map.pop('httpie')
print()
print(' url "{url}"'.format(url=httpie_meta['url']))
print(' sha256 "{sha256}"'.format(sha256=httpie_meta['sha256']))
print()
for dep_meta in package_meta_map.values():
print(' resource "{name}" do'.format(name=dep_meta['name']))
print(' url "{url}"'.format(url=dep_meta['url']))
print(' sha256 "{sha256}"'.format(sha256=dep_meta['sha256']))
print(' end')
print('')
if __name__ == '__main__':
main()

View File

@ -0,0 +1,74 @@
class Httpie < Formula
include Language::Python::Virtualenv
desc "User-friendly cURL replacement (command-line HTTP client)"
homepage "https://httpie.io/"
url "https://files.pythonhosted.org/packages/90/64/7ea8066309970f787653bdc8c5328272a5c4d06cbce3a07a6a5c3199c3d7/httpie-2.5.0.tar.gz"
sha256 "fe6a8bc50fb0635a84ebe1296a732e39357c3e1354541bf51a7057b4877e47f9"
license "BSD-3-Clause"
head "https://github.com/httpie/httpie.git"
bottle do
sha256 cellar: :any_skip_relocation, arm64_big_sur: "01115f69aff0399b3f73af09899a42a14343638a4624a35749059cc732c49cdc"
sha256 cellar: :any_skip_relocation, big_sur: "53f07157f00edf8193b7d4f74f247f53e1796fbc3e675cd2fbaa4b9dc2bad62c"
sha256 cellar: :any_skip_relocation, catalina: "7cf216fdee98208856d654060fdcad3968623d7ed27fcdeba27d3120354c9a9f"
sha256 cellar: :any_skip_relocation, mojave: "28adb5aed8c1c2b39c51789f242ff0dffde39073e161deb379c79184d787d063"
sha256 cellar: :any_skip_relocation, x86_64_linux: "91cb8c332c643bd8b1d0a8f3ec0acd4770b407991f6de1fd320d675f2b2e95ec"
end
depends_on "python@3.9"
resource "certifi" do
url "https://files.pythonhosted.org/packages/6d/78/f8db8d57f520a54f0b8a438319c342c61c22759d8f9a1cd2e2180b5e5ea9/certifi-2021.5.30.tar.gz"
sha256 "2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"
end
resource "charset-normalizer" do
url "https://files.pythonhosted.org/packages/e7/4e/2af0238001648ded297fb54ceb425ca26faa15b341b4fac5371d3938666e/charset-normalizer-2.0.4.tar.gz"
sha256 "f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"
end
resource "defusedxml" do
url "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz"
sha256 "1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"
end
resource "idna" do
url "https://files.pythonhosted.org/packages/cb/38/4c4d00ddfa48abe616d7e572e02a04273603db446975ab46bbcd36552005/idna-3.2.tar.gz"
sha256 "467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
end
resource "Pygments" do
url "https://files.pythonhosted.org/packages/b7/b3/5cba26637fe43500d4568d0ee7b7362de1fb29c0e158d50b4b69e9a40422/Pygments-2.10.0.tar.gz"
sha256 "f398865f7eb6874156579fdf36bc840a03cab64d1cde9e93d68f46a425ec52c6"
end
resource "PySocks" do
url "https://files.pythonhosted.org/packages/bd/11/293dd436aea955d45fc4e8a35b6ae7270f5b8e00b53cf6c024c83b657a11/PySocks-1.7.1.tar.gz"
sha256 "3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"
end
resource "requests" do
url "https://files.pythonhosted.org/packages/e7/01/3569e0b535fb2e4a6c384bdbed00c55b9d78b5084e0fb7f4d0bf523d7670/requests-2.26.0.tar.gz"
sha256 "b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"
end
resource "requests-toolbelt" do
url "https://files.pythonhosted.org/packages/28/30/7bf7e5071081f761766d46820e52f4b16c8a08fef02d2eb4682ca7534310/requests-toolbelt-0.9.1.tar.gz"
sha256 "968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0"
end
resource "urllib3" do
url "https://files.pythonhosted.org/packages/4f/5a/597ef5911cb8919efe4d86206aa8b2658616d676a7088f0825ca08bd7cb8/urllib3-1.26.6.tar.gz"
sha256 "f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"
end
def install
virtualenv_install_with_resources
end
test do
raw_url = "https://raw.githubusercontent.com/Homebrew/homebrew-core/HEAD/Formula/httpie.rb"
assert_match "PYTHONPATH", shell_output("#{bin}/http --ignore-stdin #{raw_url}")
end
end

View File

@ -0,0 +1,33 @@
# Contributor: Fabian Affolter <fabian@affolter-engineering.ch>
# Maintainer: Fabian Affolter <fabian@affolter-engineering.ch>
# Contributor: Daniel Isaksen <d@duniel.no>
# Contributor: Mickaël Schoentgen <mickael@apible.io>
pkgname=httpie
pkgver=2.5.0
pkgrel=0
pkgdesc="CLI, cURL-like tool"
url="https://httpie.org/"
arch="noarch"
license="BSD-3-Clause"
depends="python3 py3-setuptools py3-requests py3-pygments py3-requests-toolbelt py3-pysocks py3-defusedxml"
makedepends="py3-setuptools"
checkdepends="py3-pytest py3-pytest-httpbin py3-responses"
source="https://files.pythonhosted.org/packages/source/h/httpie/httpie-$pkgver.tar.gz"
# secfixes:
# 1.0.3-r0:
# - CVE-2019-10751
build() {
python3 setup.py build
}
check() {
python3 -m pytest ./httpie ./tests
}
package() {
python3 setup.py install --prefix=/usr --root="$pkgdir"
}
sha512sums="3bfe572b03bfde87d5a02f9ba238f9493b32e587c33fd30600a4dd6a45082eedcb2b507c7f1e3e75a423cbdcc1ff0556138897dffb7888d191834994eae9a2aa httpie-2.5.0.tar.gz"

View File

@ -0,0 +1,67 @@
# HTTPie on Alpine Linux
Welcome to the documentation about **packaging HTTPie for Alpine Linux**.
- If you do not know HTTPie, have a look [here](https://httpie.io/cli).
- If you are looking for HTTPie installation or upgrade instructions on Alpine Linux, then you can find them on [that page](https://httpie.io/docs#alpine-linux).
- If you are looking for technical information about the HTTPie packaging on Alpine Linux, then you are in a good place.
## About
This document contains technical details, where we describe how to create a patch for the latest HTTPie version for Alpine Linux.
We will discuss setting up the environment, installing development tools, installing and testing changes before submitting a patch downstream.
## Overall process
Open a pull request to update the [downstream file](https://gitlab.alpinelinux.org/alpine/aports/-/blob/master/community/httpie/APKBUILD) ([example](https://gitlab.alpinelinux.org/alpine/aports/-/merge_requests/25075)).
Notes:
- The `pkgrel` value must be set to `0`.
- The commit message must be `community/httpie: upgrade to XXX`.
- The commit must be signed-off (`git commit -s`).
## Hacking
Launch the docker image:
```bash
docker pull alpine
docker run -it --rm alpine
```
From inside the container:
```bash
# Install tools
apk add alpine-sdk sudo
# Add a user (password required)
adduser me
addgroup me abuild
echo "me ALL=(ALL) ALL" >> /etc/sudoers
# Switch user
su - me
# Create a private key (not used but required)
abuild-keygen -a -i
# Clone
git clone --depth=1 https://gitlab.alpinelinux.org/alpine/aports.git
cd aports/community/httpie
# Retrieve the patch of the latest HTTPie version
curl https://raw.githubusercontent.com/httpie/httpie/master/docs/packaging/linux-alpine/APKBUILD \
-o APKBUILD
# Build the package
abuild -r
# Install the package
sudo apk add --repository ~/packages/community httpie
# And test it!
http --version
https --version
```

View File

@ -0,0 +1,24 @@
# HTTPie on AOSC OS
Welcome to the documentation about **packaging HTTPie for AOSC OS**.
- If you do not know HTTPie, have a look [here](https://httpie.io/cli).
- If you are looking for technical information about the HTTPie packaging on AOSC OS, then you are in a good place.
## About
This document contains technical details, where we describe how to create a patch for the latest HTTPie version for AOSC OS.
We will discuss setting up the environment, installing development tools, installing and testing changes before submitting a patch downstream.
## Overall process
Open a pull request to update the [downstream file](https://github.com/AOSC-Dev/aosc-os-abbs/blob/stable/extra-web/httpie/spec) ([example](https://github.com/AOSC-Dev/aosc-os-abbs/commit/d0d3ba0bcea347387bb582a1b0b1b4e518720c80)).
Notes:
- The commit message must be `httpie: update to XXX`.
- The commit must be signed-off (`git commit -s`).
## Hacking
:construction: Work in progress.

View File

@ -0,0 +1,5 @@
VER=2.5.0
SRCS="tbl::https://github.com/httpie/httpie/archive/$VER.tar.gz"
CHKSUMS="sha256::66af56e0efc1ca6237323f1186ba34bca1be24e67a4319fd5df7228ab986faea"
REL=1
CHKUPDATE="anitya::id=1337"

View File

@ -0,0 +1,46 @@
# Maintainer: Jelle van der Waa <jelle@archlinux.org>
# Maintainer: daurnimator <daurnimator@archlinux.org>
# Contributor: Daniel Micay <danielmicay@gmail.com>
# Contributor: Thomas Weißschuh <thomas_weissschuh lavabit com>
pkgname=httpie
pkgver=2.5.0
pkgrel=1
pkgdesc="human-friendly CLI HTTP client for the API era"
url="https://github.com/httpie/httpie"
depends=('python-defusedxml'
'python-pygments'
'python-pysocks'
'python-requests'
'python-requests-toolbelt')
makedepends=('python-setuptools')
checkdepends=('python-pytest'
'python-pytest-httpbin'
'python-responses')
conflicts=(python-httpie)
replaces=(python-httpie python2-httpie)
license=('BSD')
arch=('any')
source=($pkgname-$pkgver.tar.gz::"https://github.com/httpie/httpie/archive/$pkgver.tar.gz")
sha256sums=('66af56e0efc1ca6237323f1186ba34bca1be24e67a4319fd5df7228ab986faea')
build() {
cd $pkgname-$pkgver
python3 setup.py build
}
package() {
cd $pkgname-$pkgver
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/httpie/LICENSE"
python3 setup.py install --root="$pkgdir" --optimize=1
# Fix upstream, include them in MANIFEST.in and use data_files in setup.py to install them automatically
# TODO: add zsh support
install -Dm644 extras/httpie-completion.bash "$pkgdir"/usr/share/bash-completion/completions/http
install -Dm644 extras/httpie-completion.fish "$pkgdir"/usr/share/fish/vendor_completions.d/http.fish
}
check() {
cd $pkgname-$pkgver
PYTHONDONTWRITEBYTECODE=1 python3 setup.py test
}

View File

@ -0,0 +1,22 @@
# HTTPie on Arch Linux, and derived
Welcome to the documentation about **packaging HTTPie for Arch Linux**.
- If you do not know HTTPie, have a look [here](https://httpie.io/cli).
- If you are looking for HTTPie installation or upgrade instructions on Arch Linux, then you can find them on [that page](https://httpie.io/docs#arch-linux).
- If you are looking for technical information about the HTTPie packaging on Arch Linux, then you are in a good place.
## About
This document contains technical details, where we describe how to create a patch for the latest HTTPie version for Arch Linux. They apply to Arch-derived distributions as well, like ArcoLinux, EndeavourOS, Artix Linux, etc.
We will discuss setting up the environment, installing development tools, installing and testing changes before submitting a patch downstream.
## Overall process
Note: Sending patches downstream does not seem easy. We failed to find where is located the package file on <https://gitlab.archlinux.org>. So we are relying on the last maintainer, daurnimator, and it works pretty well so far.
Check <https://archlinux.org/packages/community/any/httpie/> and if the version is outdated, simply [report it](https://archlinux.org/packages/community/any/httpie/flag/).
## Hacking
Left blank on purpose, we will fill that section when we will have access to the downstream repository.

View File

@ -0,0 +1,26 @@
# HTTPie on CentOS, RHEL, and derived
Welcome to the documentation about **packaging HTTPie for CentOS and RHEL**.
- If you do not know HTTPie, have a look [here](https://httpie.io/cli).
- If you are looking for HTTPie installation or upgrade instructions on CentOS, then you can find them on [that page](https://httpie.io/docs#centos-and-rhel).
- If you are looking for technical information about the HTTPie packaging on CentOS, then you are in a good place.
## About
This document contains technical details, where we describe how to create a patch for the latest HTTPie version for CentOS. They apply to RHEL as well, and any RHEL-derived distributions like ClearOS, Oracle Linux, etc.
We will discuss setting up the environment, installing development tools, installing and testing changes before submitting a patch downstream.
The current maintainer is [Mikel Olasagasti](https://github.com/kaxero).
## Overall process
Same as [Fedora](../linux-fedora/README.md#overall-process).
## Q/A with Mikel
Q: What should we do to help seeing a new version on CentOS?
A: When a new release is published Miro and I get notified by [release-monitoring](https://release-monitoring.org/project/1337/), that fills a BugZilla ticket reporting a new version being available.
The system also tries to create a simple patch to update the spec file, but in the case of CentOS it needs some manual revision. For example for 2.5.0 `defuxedxml` dep is required. Maybe with CentOS-9 and some new macros that are available now in Fedora it can be automated same way. But even the bump can be automated, maintainers should check for license changes, new binaries/docs/ and so on.

View File

@ -0,0 +1,29 @@
# HTTPie on Debian, Ubuntu, and derived
Welcome to the documentation about **packaging HTTPie for Debian GNU/Linux**.
- If you do not know HTTPie, have a look [here](https://httpie.io/cli).
- If you are looking for HTTPie installation or upgrade instructions on Debian GNU/Linux, then you can find them on [that page](https://httpie.io/docs#debian-and-ubuntu).
- If you are looking for technical information about the HTTPie packaging on Debian GNU/Linux, then you are in a good place.
## About
This document contains technical details, where we describe how to create a patch for the latest HTTPie version for Debian GNU/Linux. They apply to Ubuntu as well, and any Debian-derived distributions like MX Linux, Linux Mint, deepin, Pop!_OS, KDE neon, Zorin OS, elementary OS, Kubuntu, Devuan, Linux Lite, Peppermint OS, Lubuntu, antiX, Xubuntu, etc.
We will discuss setting up the environment, installing development tools, installing and testing changes before submitting a patch downstream.
The current maintainer is Bartosz Fenski.
## Overall process
Open a new bug on the Debian Bug Tracking System by sending an email:
- To: `Debian Bug Tracking System <submit@bugs.debian.org>`
- Subject: `httpie: Version XXX available`
- Message template ([example](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=993937)):
```email
Package: httpie
Severity: wishlist
<MESSAGE>
```

View File

@ -0,0 +1,48 @@
# HTTPie on Fedora
Welcome to the documentation about **packaging HTTPie for Fedora**.
- If you do not know HTTPie, have a look [here](https://httpie.io/cli).
- If you are looking for HTTPie installation or upgrade instructions on Fedora, then you can find them on [that page](https://httpie.io/docs#fedora).
- If you are looking for technical information about the HTTPie packaging on Fedora, then you are in a good place.
## About
This document contains technical details, where we describe how to create a patch for the latest HTTPie version for Fedora.
We will discuss setting up the environment, installing development tools, installing and testing changes before submitting a patch downstream.
The current maintainer is [Miro Hrončok](https://github.com/hroncok).
## Overall process
We added the [.packit.yaml](https://github.com/httpie/httpie/blob/master/.packit.yaml) local file.
It unlocks real-time Fedora checks on pull requests and new releases.
So there is nothing to do on our side: `Packit` will see the new release and open a pull request [there](https://src.fedoraproject.org/rpms/httpie). Then, the Fedora maintainer will review and merge.
It is also possible to follow [user feedbacks](https://bodhi.fedoraproject.org/updates/?packages=httpie) for all builds.
## Q/A with Miro
Q: What would the command to install the latest stable version look like?
A: Assuming the latest stable version is already propagated to Fedora:
```bash
# Note that yum is an alias to dnf.
$ sudo dnf install httpie
```
Q: Will dnf/yum upgrade then update to the latest?
A: Yes, assuming the same as above.
Q: Are new versions backported automatically?
A: No. The process is:
1. A new HTTPie release is created on Github.
2. A pull request for Fedora `rawhide` (the development version of Fedora, currently Fedora 35) is created.
3. A Fedora packager (usually Miro) sanity checks the pull request and merges, builds. HTTPie is updated in `rawhide` within 24 hours (sometimes more, for unrelated issues).
4. A Fedora packager decides whether the upgrade is suitable for stable Fedora releases (currently 34, 33), if so, merges the changes there.
5. (if the above is yes) The new version of HTTPie lands in `updates-testing` repo where it waits for user feedback and lands within ~1 week for broad availability.

View File

@ -0,0 +1,2 @@
DIST httpie-2.4.0.tar.gz 1772537 BLAKE2B 111451cc7dc353d5b586554f98ac715a3198f03e74d261944a5f021d2dcc948455500800222b323d182a2a067d0549bda7c318ab3a6c934b9a9beec64aff2db2 SHA512 44cc7ff4fe0f3d8c53a7dd750465f6b56c36f5bbac06d22b760579bd60949039e82313845699669a659ec91adc69dbeac22c06ddd63af64e6f2e0edecf3e732a
DIST httpie-2.5.0.tar.gz 1105177 BLAKE2B 6e16868c81522d4e6d2fc0a4e093c190f18ced720b35217930865ae3f8e168193cc33dfecc13c5d310f52647d6e79d17b247f56e56e8586d633a2d9502be66a7 SHA512 f14aa23fea7578181b9bd6ededea04de9ddf0b2f697b23f76d2d96e2c17b95617318c711750bad6af550400dbc03732ab17fdf84e59d577f33f073e600a55330

View File

@ -0,0 +1,78 @@
# HTTPie on Gentoo
Welcome to the documentation about **packaging HTTPie for Gentoo**.
- If you do not know HTTPie, have a look [here](https://httpie.io/cli).
- If you are looking for HTTPie installation or upgrade instructions on Gentoo, then you can find them on [that page](https://httpie.io/docs#gentoo).
- If you are looking for technical information about the HTTPie packaging on Gentoo, then you are in a good place.
## About
This document contains technical details, where we describe how to create a patch for the latest HTTPie version for Gentoo.
We will discuss setting up the environment, installing development tools, installing and testing changes before submitting a patch downstream.
## Overall process
Open a pull request to create `httpie-XXX.ebuild` and update `Manifest`.
- Here is how to calculate the size and checksum (replace `2.5.0` with the correct version):
```bash
# Download
$ wget https://github.com/httpie/httpie/archive/2.5.0.tar.gz
# Size
$ stat --printf="%s\n" 2.5.0.tar.gz
1105177
# Checksum
$ openssl dgst -blake2b512 2.5.0.tar.gz
BLAKE2b512(2.5.0.tar.gz)= 6e16868c81522d4e6d2fc0a4e093c190f18ced720b35217930865ae3f8e168193cc33dfecc13c5d310f52647d6e79d17b247f56e56e8586d633a2d9502be66a7
```
- The commit message must be `net-misc/httpie: version bump to XXX`.
- The commit must be signed-off (`git commit -s`).
## Hacking
Launch the docker image:
```bash
docker pull gentoo/stage3
docker run -it --rm gentoo/stage3
```
From inside the container:
```bash
# Install tools
emerge --sync
emerge pkgcheck repoman
# Go to the package location
cd /var/db/repos/gentoo/net-misc/httpie
# Retrieve the patch of the latest HTTPie version
# (only files that were modified since the previous release)
curl https://raw.githubusercontent.com/httpie/httpie/master/docs/packaging/linux-gentoo/httpie-XXX.ebuild \
-o httpie-XXX.ebuild
curl https://raw.githubusercontent.com/httpie/httpie/master/docs/packaging/linux-gentoo/Manifest \
-o Manifest
curl https://raw.githubusercontent.com/httpie/httpie/master/docs/packaging/linux-gentoo/metadata.xml \
-o metadata.xml
# Basic checks
repoman manifest
repoman full -d -x
pkgcheck scan
# Build and install the package
emerge --with-test-deps httpie-XXX.ebuild
# Run the tests suite
ebuild httpie-XXX.ebuild clean test
# And test it!
http --version
https --version
```

View File

@ -0,0 +1,42 @@
# Copyright 1999-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=7
DISTUTILS_USE_SETUPTOOLS=rdepend
PYTHON_COMPAT=( python3_{8,9,10} )
PYTHON_REQ_USE="ssl(+)"
inherit bash-completion-r1 distutils-r1
DESCRIPTION="Modern command line HTTP client"
HOMEPAGE="https://httpie.io/ https://pypi.org/project/httpie/"
SRC_URI="https://github.com/httpie/httpie/archive/${PV}.tar.gz -> ${P}.tar.gz"
LICENSE="BSD"
SLOT="0"
KEYWORDS="~amd64 ~x86"
RDEPEND="
dev-python/defusedxml[${PYTHON_USEDEP}]
dev-python/pygments[${PYTHON_USEDEP}]
>=dev-python/requests-2.22.0[${PYTHON_USEDEP}]
>=dev-python/requests-toolbelt-0.9.1[${PYTHON_USEDEP}]
"
BDEPEND="
test? (
${RDEPEND}
dev-python/pyopenssl[${PYTHON_USEDEP}]
dev-python/pytest-httpbin[${PYTHON_USEDEP}]
dev-python/responses[${PYTHON_USEDEP}]
)
"
distutils_enable_tests pytest
python_install_all() {
newbashcomp extras/httpie-completion.bash http
insinto /usr/share/fish/vendor_completions.d
newins extras/httpie-completion.fish http.fish
distutils-r1_python_install_all
}

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pkgmetadata SYSTEM "https://www.gentoo.org/dtd/metadata.dtd">
<pkgmetadata>
<maintainer type="person" proxied="yes">
<email>mickael@apible.io</email>
<name>Mickaël Schoentgen</name>
</maintainer>
<maintainer type="project" proxied="proxy">
<email>proxy-maint@gentoo.org</email>
<name>Proxy Maintainers</name>
</maintainer>
<longdescription lang="en">
HTTPie (pronounced aitch-tee-tee-pie) is a command line HTTP
client. Its goal is to make CLI interaction with web services as
human-friendly as possible. It provides a simple http command
that allows for sending arbitrary HTTP requests using a simple
and natural syntax, and displays colorized output. HTTPie can be
used for testing, debugging, and generally interacting with HTTP
servers.
</longdescription>
<upstream>
<bugs-to>https://github.com/httpie/httpie/issues</bugs-to>
<changelog>https://raw.githubusercontent.com/httpie/httpie/master/CHANGELOG.md</changelog>
<doc>https://httpie.io/docs</doc>
<remote-id type="github">httpie/httpie</remote-id>
<remote-id type="pypi">httpie</remote-id>
</upstream>
</pkgmetadata>

View File

@ -0,0 +1,68 @@
# HTTPie on Void Linux
Welcome to the documentation about **packaging HTTPie for Void Linux**.
- If you do not know HTTPie, have a look [here](https://httpie.io/cli).
- If you are looking for HTTPie installation or upgrade instructions on Void Linux, then you can find them on [that page](https://httpie.io/docs#void-linux).
- If you are looking for technical information about the HTTPie packaging on Void Linux, then you are in a good place.
## About
This document contains technical details, where we describe how to create a patch for the latest HTTPie version for Void Linux.
We will discuss setting up the environment, installing development tools, installing and testing changes before submitting a patch downstream.
## Overall process
Open a pull request to update the [downstream file](https://github.com/void-linux/void-packages/blob/master/srcpkgs/httpie/template) ([example](https://github.com/void-linux/void-packages/pull/32905)).
- The commit message must be `httpie: update to XXX.`.
- The commit must be signed-off (`git commit -s`).
## Hacking
Launch the docker image:
```bash
docker pull voidlinux/voidlinux
docker run -it --rm voidlinux/voidlinux
```
From inside the container:
```bash
# Sync and upgrade once, assume error comes from xbps update
xbps-install -Syu
# Install tools
xbps-install -y git xtools file util-linux binutils bsdtar coreutils
# Clone
git clone --depth=1 git://github.com/void-linux/void-packages.git void-packages-src
cd void-packages-src
# Retrieve the patch of the latest HTTPie version
curl https://raw.githubusercontent.com/httpie/httpie/master/docs/packaging/linux-void/template \
-o srcpkgs/httpie/template
# Check the package
xlint srcpkgs/httpie/template
# Link / to /masterdir
ln -s / masterdir
# Enable ethereal chroot-style
export XBPS_ALLOW_CHROOT_BREAKOUT=yes
./xbps-src binary-bootstrap
./xbps-src chroot
# Build the package
cd void-packages
export SOURCE_DATE_EPOCH=0
./xbps-src pkg httpie
# Install the package
xbps-install --repository=hostdir/binpkgs httpie
# And finally test it!
http --version
https --version
```

View File

@ -0,0 +1,28 @@
# Template file for 'httpie'
pkgname=httpie
version=2.5.0
revision=1
build_style=python3-module
hostmakedepends="python3-setuptools"
depends="python3-setuptools python3-requests python3-requests-toolbelt
python3-Pygments python3-pysocks python3-defusedxml"
short_desc="Human-friendly command line HTTP client"
maintainer="Mickaël Schoentgen <mickael@apible.io>"
license="BSD-3-Clause"
homepage="https://httpie.io/"
changelog="https://raw.githubusercontent.com/httpie/httpie/${version}/CHANGELOG.md"
distfiles="https://github.com/httpie/httpie/archive/${version}.tar.gz"
checksum=66af56e0efc1ca6237323f1186ba34bca1be24e67a4319fd5df7228ab986faea
make_check=no # needs pytest_httpbin which is not packaged
post_install() {
vcompletion extras/httpie-completion.bash bash http
vcompletion extras/httpie-completion.fish fish http
vlicense LICENSE
}
python3-httpie_package() {
build_style=meta
short_desc+=" (transitional dummy package)"
depends="httpie>=${version}_${revision}"
}

View File

@ -0,0 +1,49 @@
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8::et:sw=4:ts=4:sts=4
PortSystem 1.0
PortGroup github 1.0
PortGroup python 1.0
github.setup httpie httpie 2.5.0
maintainers {g5pw @g5pw} openmaintainer
categories net
description HTTPie is a command line HTTP client, a user-friendly cURL replacement.
long_description HTTPie (pronounced aych-tee-tee-pie) is a command line HTTP \
client. Its goal is to make CLI interaction with web \
services as human-friendly as possible. It provides a simple \
http command that allows for sending arbitrary HTTP requests \
using a simple and natural syntax, and displays colorized \
responses. HTTPie can be used for testing, debugging, and \
generally interacting with HTTP servers.
platforms darwin
license BSD
homepage https://httpie.io/
variant python36 conflicts python37 python38 python39 description "Use Python 3.6" {}
variant python37 conflicts python36 python38 python39 description "Use Python 3.7" {}
variant python38 conflicts python36 python37 python39 description "Use Python 3.8" {}
variant python39 conflicts python36 python37 python38 description "Use Python 3.9" {}
if {[variant_isset python36]} {
python.default_version 36
} elseif {[variant_isset python37]} {
python.default_version 37
} elseif {[variant_isset python39]} {
python.default_version 39
} else {
default_variants +python38
python.default_version 38
}
depends_lib-append port:py${python.version}-requests \
port:py${python.version}-requests-toolbelt \
port:py${python.version}-pygments \
port:py${python.version}-socks \
port:py${python.version}-defusedxml
checksums rmd160 88d227d52199c232c0ddf704a219d1781b1e77ee \
sha256 00c4b7bbe7f65abe1473f37b39d9d9f8f53f44069a430ad143a404c01c2179fc \
size 1105185
python.link_binaries_suffix

View File

@ -0,0 +1,40 @@
# HTTPie on MacPorts
Welcome to the documentation about **packaging HTTPie for MacPorts**.
- If you do not know HTTPie, have a look [here](https://httpie.io/cli).
- If you are looking for HTTPie installation or upgrade instructions on MacPorts, then you can find them on [that page](https://httpie.io/docs#macports).
- If you are looking for technical information about the HTTPie packaging on MacPorts, then you are in a good place.
## About
This document contains technical details, where we describe how to create a patch for the latest HTTPie version for MacPorts.
We will discuss setting up the environment, installing development tools, installing and testing changes before submitting a patch downstream.
## Overall process
Open a pull request to update the [downstream file](https://github.com/macports/macports-ports/blob/master/net/httpie/Portfile) ([example](https://github.com/macports/macports-ports/pull/12167)).
- Here is how to calculate the size and checksums (replace `2.5.0` with the correct version):
```bash
# Download the archive
$ wget https://api.github.com/repos/httpie/httpie/tarball/2.5.0
# Size
$ stat --printf="%s\n" 2.5.0
1105185
# Checksums
$ openssl dgst -rmd160 2.5.0
RIPEMD160(2.5.0)= 88d227d52199c232c0ddf704a219d1781b1e77ee
$ openssl dgst -sha256 2.5.0
SHA256(2.5.0)= 00c4b7bbe7f65abe1473f37b39d9d9f8f53f44069a430ad143a404c01c2179fc
```
- The commit message must be `httpie: update to XXX`.
- The commit must be signed-off (`git commit -s`).
## Hacking
:construction: Work in progress.

View File

@ -0,0 +1,51 @@
# HTTPie on Snapcraft
Welcome to the documentation about **packaging HTTPie for Snapcraft**.
- If you do not know HTTPie, have a look [here](https://httpie.io/cli).
- If you are looking for HTTPie installation or upgrade instructions on Snapcraft, then you can find them on [that page](https://httpie.io/docs#snapcraft-linux) ([that one](https://httpie.io/docs#snapcraft-macos) for macOS).
- If you are looking for technical information about the HTTPie packaging on Snapcraft, then you are in a good place.
## About
This document contains technical details, where we describe how to create a patch for the latest HTTPie version for Snapcraft. They apply to Snapcraft on Linux, macOS, and Windows.
We will discuss setting up the environment, installing development tools, installing and testing changes before submitting a patch downstream.
## Overall process
Trigger a new [build](https://snapcraft.io/httpie/builds), then [promote it](https://snapcraft.io/httpie/releases). If more management is needed: [revisions supervision](https://dashboard.snapcraft.io/snaps/httpie/revisions/).
## Hacking
Launch the docker image:
```bash
docker pull ubuntu/latest
docker run -it --rm ubuntu/latest
```
From inside the container:
```bash
# Clone
git clone --depth=1 https://github.com/httpie/httpie.git
cd httpie
# Build
export SNAPCRAFT_BUILD_ENVIRONMENT_CPU=8
export SNAPCRAFT_BUILD_ENVIRONMENT_MEMORY=16G
snapcraft --debug
# Install
sudo snap install --dangerous httpie_XXX_amd64.snap
# Test
httpie.http --version
httpie.https --version
# Auto-aliases cannot be tested when installing a snap outside the store.
# http --version
# https --version
# Remove
sudo snap remove httpie
```

View File

@ -0,0 +1,54 @@
# HTTPie on Spack
Welcome to the documentation about **packaging HTTPie for Spack**.
- If you do not know HTTPie, have a look [here](https://httpie.io/cli).
- If you are looking for HTTPie installation or upgrade instructions on Spack, then you can find them on [that page](https://httpie.io/docs#spack-linux) ([that one](https://httpie.io/docs#spack-macos) for macOS).
- If you are looking for technical information about the HTTPie packaging on Spack, then you are in a good place.
## About
This document contains technical details, where we describe how to create a patch for the latest HTTPie version for Spack. They apply to Spack on Linux, and macOS.
We will discuss setting up the environment, installing development tools, installing and testing changes before submitting a patch downstream.
## Overall process
Open a pull request to update the [downstream file](https://github.com/spack/spack/blob/develop/var/spack/repos/builtin/packages/httpie/package.py) ([example](https://github.com/spack/spack/pull/25888)).
- The commit message must be `httpie: add vXXX`.
- The commit must be signed-off (`git commit -s`).
## Hacking
Launch the docker image:
```bash
docker pull spack/centos7
docker run -it --rm spack/centos7
```
From inside the container:
```bash
# Clone
git clone --depth=1 https://github.com/spack/spack.git
cd spack
# Retrieve the patch of the latest HTTPie version
curl https://raw.githubusercontent.com/httpie/httpie/master/docs/packaging/spack/package.py \
-o var/spack/repos/builtin/packages/httpie/package.py
# Check the package
spack spec httpie
# Check available versions (it should show the new version)
spack versions httpie
# Install the package
spack install httpie@XXX
spack load httpie
# And test it!
http --version
https --version
```

View File

@ -0,0 +1,32 @@
# Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
from spack import *
class Httpie(PythonPackage):
"""Modern command line HTTP client."""
homepage = "https://httpie.io/"
pypi = "httpie/httpie-2.5.0.tar.gz"
version('2.5.0', sha256='fe6a8bc50fb0635a84ebe1296a732e39357c3e1354541bf51a7057b4877e47f9')
version('0.9.9', sha256='f1202e6fa60367e2265284a53f35bfa5917119592c2ab08277efc7fffd744fcb')
version('0.9.8', sha256='515870b15231530f56fe2164190581748e8799b66ef0fe36ec9da3396f0df6e1')
variant('socks', default=True,
description='Enable SOCKS proxy support')
depends_on('py-setuptools', type=('build', 'run'))
depends_on('py-defusedxml', type=('build', 'run'))
depends_on('py-pygments', type=('build', 'run'))
depends_on('py-requests', type=('build', 'run'))
depends_on('py-requests-toolbelt', type=('build', 'run'))
depends_on('py-pysocks', type=('build', 'run'), when="+socks")
# Concretization problem breaks this. Unconditional for now...
# https://github.com/spack/spack/issues/3628
# depends_on('py-argparse@1.2.1:', type=('build', 'run'),
# when='^python@:2.6,3.0:3.1')
depends_on('py-argparse@1.2.1:', type=('build', 'run'), when='^python@:2.6')

View File

@ -0,0 +1,45 @@
# HTTPie on Chocolatey
Welcome to the documentation about **packaging HTTPie for Chocolatey**.
- If you do not know HTTPie, have a look [here](https://httpie.io/cli).
- If you are looking for HTTPie installation or upgrade instructions on Chocolatey, then you can find them on [that page](https://httpie.io/docs#chocolatey).
- If you are looking for technical information about the HTTPie packaging on Chocolatey, then you are in a good place.
## About
This document contains technical details, where we describe how to create a patch for the latest HTTPie version for Chocolatey.
We will discuss setting up the environment, installing development tools, installing and testing changes before submitting a patch downstream.
## Overall process
After having successfully [built and tested](#hacking) the package, push it:
```bash
# Replace 2.5.0 with the correct version
choco push httpie.2.5.0.nupkg -s https://push.chocolatey.org/ --api-key=API_KEY
```
## Hacking
```bash
# Clone
git clone --depth=1 https://github.com/httpie/httpie.git
cd httpie/docs/packaging/windows-chocolatey
# Build
choco pack
# Check metadata
choco info httpie -s .
# Install
choco install httpie -y -dv -s "'.;https://community.chocolatey.org/api/v2/'"
# Test
http --version
https --version
# Remove
choco uninstall -y httpie
```

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
<metadata>
<id>httpie</id>
<version>2.5.0</version>
<summary>Modern, user-friendly command-line HTTP client for the API era.</summary>
<description>
HTTPie *aitch-tee-tee-pie* is a user-friendly command-line HTTP client for the API era.
It comes with JSON support, syntax highlighting, persistent sessions, wget-like downloads, plugins, and more.
The project's goal is to make CLI interaction with web services as human-friendly as possible. HTTPie is designed for testing, debugging, and generally interacting with APIs and HTTP servers.
The `http` and `https` commands allow for creating and sending arbitrary HTTP requests. They use simple and natural syntax and provide formatted and colorized output.
Main features:
- Built-in JSON support
- Colorized and formatted terminal output
- Sensible defaults for the API era
- Persistent sessions
- Forms and file uploads
- HTTPS, proxies, and authentication support
- Support for arbitrary request data and headers
- Wget-like downloads
- Extensions API
- Expressive and intuitive syntax
- Linux, macOS, Windows, and FreeBSD support
- All that and more in 2 simple commands: `http` + `https`
</description>
<title>HTTPie</title>
<authors>HTTPie</authors>
<owners>Tiger-222</owners>
<copyright>2012-2021 Jakub Roztocil</copyright>
<licenseUrl>https://raw.githubusercontent.com/httpie/httpie/master/LICENSE</licenseUrl>
<iconUrl>https://pie-assets.s3.eu-central-1.amazonaws.com/LogoIcons/GB.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>See the [changelog](https://github.com/httpie/httpie/blob/2.5.0/CHANGELOG.md).</releaseNotes>
<tags>httpie http https rest api client curl python ssl cli foss oss url</tags>
<projectUrl>https://httpie.io</projectUrl>
<packageSourceUrl>https://github.com/httpie/httpie</packageSourceUrl>
<projectSourceUrl>https://github.com/httpie/httpie</projectSourceUrl>
<docsUrl>https://httpie.io/docs</docsUrl>
<bugTrackerUrl>https://github.com/httpie/httpie/issues</bugTrackerUrl>
<dependencies>
<dependency id="python3" version="3.6" />
</dependencies>
</metadata>
<files>
<file src="tools\**" target="tools" />
</files>
</package>

View File

@ -0,0 +1,6 @@
$ErrorActionPreference = 'Stop';
$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
$nuspecPath = "$(Join-Path (Split-Path -parent $toolsDir) ($env:ChocolateyPackageName + ".nuspec"))"
[XML]$nuspec = Get-Content $nuspecPath
$pipVersion = $nuspec.package.metadata.version
py -m pip install "$($env:ChocolateyPackageName)==$($pipVersion)" --disable-pip-version-check

View File

@ -0,0 +1,2 @@
$ErrorActionPreference = 'Stop';
py -m pip uninstall -y $env:ChocolateyPackageName --disable-pip-version-check

View File

@ -0,0 +1,20 @@
_http_complete() {
local cur_word=${COMP_WORDS[COMP_CWORD]}
local prev_word=${COMP_WORDS[COMP_CWORD - 1]}
if [[ "$cur_word" == -* ]]; then
_http_complete_options "$cur_word"
fi
}
complete -o default -F _http_complete http
_http_complete_options() {
local cur_word=$1
local options="-j --json -f --form --pretty -s --style -p --print
-v --verbose -h --headers -b --body -S --stream -o --output -d --download
-c --continue --session --session-read-only -a --auth --auth-type --proxy
--follow --verify --cert --cert-key --timeout --check-status --ignore-stdin
--help --version --traceback --debug --raw"
COMPREPLY=( $( compgen -W "$options" -- "$cur_word" ) )
}

View File

@ -0,0 +1,137 @@
function __fish_httpie_styles
echo "
abap
algol
algol_nu
arduino
auto
autumn
borland
bw
colorful
default
emacs
friendly
fruity
gruvbox-dark
gruvbox-light
igor
inkpot
lovelace
manni
material
monokai
murphy
native
paraiso-dark
paraiso-light
pastie
perldoc
rainbow_dash
rrt
sas
solarized
solarized-dark
solarized-light
stata
stata-dark
stata-light
tango
trac
vim
vs
xcode
zenburn"
end
function __fish_httpie_auth_types
echo -e "basic\tBasic HTTP auth"
echo -e "digest\tDigest HTTP auth"
end
function __fish_http_verify_options
echo -e "yes\tEnable cert verification"
echo -e "no\tDisable cert verification"
end
# Predefined Content Types
complete -c http -s j -l json -d 'Data items are serialized as a JSON object'
complete -c http -s f -l form -d 'Data items are serialized as form fields'
complete -c http -l multipart -d 'Always sends a multipart/form-data request'
complete -c http -l boundary -x -d 'Custom boundary string for multipart/form-data requests'
complete -c http -l raw -x -d 'Pass raw request data without extra processing'
# Content Processing Options
complete -c http -s x -l compress -d 'Content compressed with Deflate algorithm'
# Output Processing
complete -c http -l pretty -xa "all colors format none" -d 'Controls output processing'
complete -c http -s s -l style -xa "(__fish_httpie_styles)" -d 'Output coloring style'
complete -c http -l unsorted -d 'Disables all sorting while formatting output'
complete -c http -l sorted -d 'Re-enables all sorting options while formatting output'
complete -c http -l format-options -x -d 'Controls output formatting'
# Output Options
complete -c http -s p -l print -x -d 'String specifying what the output should contain'
complete -c http -s h -l headers -d 'Print only the response headers'
complete -c http -s b -l body -d 'Print only the response body'
complete -c http -s v -l verbose -d 'Print the whole request as well as the response'
complete -c http -l all -d 'Show any intermediary requests/responses'
complete -c http -s P -l history-print -x -d 'The same as --print but applies only to intermediary requests/responses'
complete -c http -s S -l stream -d 'Always stream the response body by line'
complete -c http -s o -l output -F -d 'Save output to FILE'
complete -c http -s d -l download -d 'Download a file'
complete -c http -s c -l continue -d 'Resume an interrupted download'
complete -c http -s q -l quiet -d 'Do not print to stdout or stderr'
# Sessions
complete -c http -l session -F -d 'Create, or reuse and update a session'
complete -c http -l session-read-only -F -d 'Create or read a session without updating it'
# Authentication
complete -c http -s a -l auth -x -d 'Username and password for authentication'
complete -c http -s A -l auth-type -xa "(__fish_httpie_auth_types)" -d 'The authentication mechanism to be used'
complete -c http -l ignore-netrc -d 'Ignore credentials from .netrc'
# Network
complete -c http -l offline -d 'Build the request and print it but don\'t actually send it'
complete -c http -l proxy -x -d 'String mapping protocol to the URL of the proxy'
complete -c http -s F -l follow -d 'Follow 30x Location redirects'
complete -c http -l max-redirects -x -d 'Set maximum number of redirects'
complete -c http -l max-headers -x -d 'Maximum number of response headers to be read before giving up'
complete -c http -l timeout -x -d 'Connection timeout in seconds'
complete -c http -l check-status -d 'Error with non-200 HTTP status code'
complete -c http -l path-as-is -d 'Bypass dot segment URL squashing'
complete -c http -l chunked -d ''
# SSL
complete -c http -l verify -xa "(__fish_http_verify_options)" -d 'Enable/disable cert verification'
complete -c http -l ssl -x -d 'Desired protocol version to use'
complete -c http -l ciphers -x -d 'String in the OpenSSL cipher list format'
complete -c http -l cert -F -d 'Client side SSL certificate'
complete -c http -l cert-key -F -d 'Private key to use with SSL'
# Troubleshooting
complete -c http -s I -l ignore-stdin -d 'Do not attempt to read stdin'
complete -c http -l help -d 'Show help'
complete -c http -l version -d 'Show version'
complete -c http -l traceback -d 'Prints exception traceback should one occur'
complete -c http -l default-scheme -x -d 'The default scheme to use'
complete -c http -l debug -d 'Show debugging output'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

View File

@ -1,7 +1,8 @@
"""
HTTPie - cURL for humans.
HTTPie: command-line HTTP client for the API era.
"""
__version__ = '2.6.0.dev0'
__author__ = 'Jakub Roztocil'
__version__ = '0.2.0'
__licence__ = 'BSD'

View File

@ -1,122 +1,19 @@
#!/usr/bin/env python
import sys
import json
import requests
from requests.compat import str
from . import httpmessage
from . import cliparse
from . import cli
from . import pretty
"""The main entry point. Invoke as `http' or `python -m httpie'.
"""
TYPE_FORM = 'application/x-www-form-urlencoded; charset=utf-8'
TYPE_JSON = 'application/json; charset=utf-8'
def _get_response(parser, args, stdin, stdin_isatty):
if not stdin_isatty:
if args.data:
parser.error('Request body (stdin) and request '
'data (key=value) cannot be mixed.')
args.data = stdin.read()
if args.json or (not args.form and args.data):
# JSON
if not args.files and (
'Content-Type' not in args.headers
and (args.data or args.json)):
args.headers['Content-Type'] = TYPE_JSON
if stdin_isatty:
# Serialize the parsed data.
args.data = json.dumps(args.data)
if 'Accept' not in args.headers:
# Default Accept to JSON as well.
args.headers['Accept'] = 'application/json'
elif not args.files and 'Content-Type' not in args.headers:
# Form
args.headers['Content-Type'] = TYPE_FORM
# Fire the request.
def main():
try:
credentials = None
if args.auth:
auth_type = (requests.auth.HTTPDigestAuth
if args.auth_type == 'digest'
else requests.auth.HTTPBasicAuth)
credentials = auth_type(args.auth.key, args.auth.value)
from httpie.core import main
exit_status = main()
except KeyboardInterrupt:
from httpie.status import ExitStatus
exit_status = ExitStatus.ERROR_CTRL_C
return requests.request(
method=args.method.lower(),
url=args.url if '://' in args.url else 'http://%s' % args.url,
headers=args.headers,
data=args.data,
verify={'yes': True, 'no': False}.get(args.verify, args.verify),
timeout=args.timeout,
auth=credentials,
proxies=dict((p.key, p.value) for p in args.proxy),
files=args.files,
allow_redirects=args.allow_redirects,
)
except (KeyboardInterrupt, SystemExit):
sys.stderr.write('\n')
sys.exit(1)
except Exception as e:
if args.traceback:
raise
sys.stderr.write(str(e.message) + '\n')
sys.exit(1)
return exit_status.value
def _get_output(args, stdout_isatty, response):
do_prettify = (args.prettify is True or
(args.prettify == cliparse.PRETTIFY_STDOUT_TTY_ONLY
and stdout_isatty))
do_output_request = (cliparse.OUT_REQ_HEADERS in args.output_options
or cliparse.OUT_REQ_BODY in args.output_options)
do_output_response = (cliparse.OUT_RESP_HEADERS in args.output_options
or cliparse.OUT_RESP_BODY in args.output_options)
prettifier = pretty.PrettyHttp(args.style) if do_prettify else None
output = []
if do_output_request:
output.append(httpmessage.format(
message=httpmessage.from_request(response.request),
prettifier=prettifier,
with_headers=cliparse.OUT_REQ_HEADERS in args.output_options,
with_body=cliparse.OUT_REQ_BODY in args.output_options
))
if do_output_response:
output.append('\n')
if do_output_response:
output.append(httpmessage.format(
message=httpmessage.from_response(response),
prettifier=prettifier,
with_headers=cliparse.OUT_RESP_HEADERS in args.output_options,
with_body=cliparse.OUT_RESP_BODY in args.output_options
))
output.append('\n')
return ''.join(output)
def main(args=None,
stdin=sys.stdin, stdin_isatty=sys.stdin.isatty(),
stdout=sys.stdout, stdout_isatty=sys.stdout.isatty()):
parser = cli.parser
args = parser.parse_args(args if args is not None else sys.argv[1:])
response = _get_response(parser, args, stdin, stdin_isatty)
output = _get_output(args, stdout_isatty, response)
output_bytes = output.encode('utf8')
f = (stdout.buffer if hasattr(stdout, 'buffer') else stdout)
f.write(output_bytes)
if __name__ == '__main__':
main()
if __name__ == '__main__': # pragma: nocover
import sys
sys.exit(main())

View File

@ -1,203 +0,0 @@
"""
CLI definition.
"""
from . import pretty
from . import __doc__
from . import __version__
from . import cliparse
def _(text):
"""Normalize white space."""
return ' '.join(text.strip().split())
desc = '%s <http://httpie.org>'
parser = cliparse.HTTPieArgumentParser(description=desc % __doc__.strip(),)
parser.add_argument('--version', action='version', version=__version__)
# Content type.
#############################################
group_type = parser.add_mutually_exclusive_group(required=False)
group_type.add_argument(
'--json', '-j', action='store_true',
help=_('''
(default) Data items are serialized as a JSON object.
The Content-Type and Accept headers
are set to application/json (if not set via the command line).
''')
)
group_type.add_argument(
'--form', '-f', action='store_true',
help=_('''
Data items are serialized as form fields.
The Content-Type is set to application/x-www-form-urlencoded (if not specifid).
The presence of any file fields results into a multipart/form-data request.
''')
)
# Output options.
#############################################
parser.add_argument(
'--traceback', action='store_true', default=False,
help=_('''
Print exception traceback should one occur.
''')
)
prettify = parser.add_mutually_exclusive_group(required=False)
prettify.add_argument(
'--pretty', dest='prettify', action='store_true',
default=cliparse.PRETTIFY_STDOUT_TTY_ONLY,
help=_('''
If stdout is a terminal, the response is prettified
by default (colorized and indented if it is JSON).
This flag ensures prettifying even when stdout is redirected.
''')
)
prettify.add_argument(
'--ugly', '-u', dest='prettify', action='store_false',
help=_('''
Do not prettify the response.
''')
)
output_options = parser.add_mutually_exclusive_group(required=False)
output_options.add_argument('--print', '-p', dest='output_options',
default=cliparse.OUT_RESP_HEADERS + cliparse.OUT_RESP_BODY,
help=_('''
String specifying what should the output contain.
"{request_headers}" stands for the request headers and
"{request_body}" for the request body.
"{response_headers}" stands for the response headers and
"{response_body}" for response the body.
Defaults to "hb" which means that the whole response
(headers and body) is printed.
'''.format(
request_headers=cliparse.OUT_REQ_HEADERS,
request_body=cliparse.OUT_REQ_BODY,
response_headers=cliparse.OUT_RESP_HEADERS,
response_body=cliparse.OUT_RESP_BODY,
))
)
output_options.add_argument(
'--verbose', '-v', dest='output_options',
action='store_const', const=''.join(cliparse.OUTPUT_OPTIONS),
help=_('''
Print the whole request as well as the response.
Shortcut for --print={0}.
'''.format(''.join(cliparse.OUTPUT_OPTIONS)))
)
output_options.add_argument(
'--headers', '-t', dest='output_options',
action='store_const', const=cliparse.OUT_RESP_HEADERS,
help=_('''
Print only the response headers.
Shortcut for --print={0}.
'''.format(cliparse.OUT_RESP_HEADERS))
)
output_options.add_argument(
'--body', '-b', dest='output_options',
action='store_const', const=cliparse.OUT_RESP_BODY,
help=_('''
Print only the response body.
Shortcut for --print={0}.
'''.format(cliparse.OUT_RESP_BODY))
)
parser.add_argument(
'--style', '-s', dest='style', default='solarized', metavar='STYLE',
choices=pretty.AVAILABLE_STYLES,
help=_('''
Output coloring style, one of %s. Defaults to solarized.
For this option to work properly, please make sure that the
$TERM environment variable is set to "xterm-256color" or similar
(e.g., via `export TERM=xterm-256color' in your ~/.bashrc).
''') % ', '.join(sorted(pretty.AVAILABLE_STYLES))
)
# ``requests.request`` keyword arguments.
parser.add_argument(
'--auth', '-a', help='username:password',
type=cliparse.KeyValueType(cliparse.SEP_COMMON)
)
parser.add_argument(
'--auth-type', choices=['basic', 'digest'],
help=_('The authentication mechanism to be used. Defaults to "basic".')
)
parser.add_argument(
'--verify', default='yes',
help=_('''
Set to "no" to skip checking the host\'s SSL certificate.
You can also pass the path to a CA_BUNDLE
file for private certs. You can also set
the REQUESTS_CA_BUNDLE environment variable.
Defaults to "yes".
''')
)
parser.add_argument(
'--proxy', default=[], action='append',
type=cliparse.KeyValueType(cliparse.SEP_COMMON),
help=_('''
String mapping protocol to the URL of the proxy
(e.g. http:foo.bar:3128).
''')
)
parser.add_argument(
'--allow-redirects', default=False, action='store_true',
help=_('''
Set this flag if full redirects are allowed
(e.g. re-POST-ing of data at new ``Location``)
''')
)
parser.add_argument(
'--timeout', type=float,
help=_('''
Float describes the timeout of the request
(Use socket.setdefaulttimeout() as fallback).
''')
)
# Positional arguments.
#############################################
parser.add_argument(
'method', metavar='METHOD',
help=_('''
The HTTP method to be used for the request
(GET, POST, PUT, DELETE, PATCH, ...).
''')
)
parser.add_argument(
'url', metavar='URL',
help=_('''
The protocol defaults to http:// if the
URL does not include one.
''')
)
parser.add_argument(
'items', nargs='*',
metavar='ITEM',
type=cliparse.KeyValueType(
cliparse.SEP_COMMON,
cliparse.SEP_DATA,
cliparse.SEP_DATA_RAW_JSON,
cliparse.SEP_FILES
),
help=_('''
A key-value pair whose type is defined by the separator used. It can be an
HTTP header (header:value),
a data field to be used in the request body (field_name=value),
a raw JSON data field (field_name:=value)
or a file field (field_name@/path/to/file).
You can use a backslash to escape a colliding separator in the field name.
''')
)

0
httpie/cli/__init__.py Normal file
View File

466
httpie/cli/argparser.py Normal file
View File

@ -0,0 +1,466 @@
import argparse
import errno
import os
import re
import sys
from argparse import RawDescriptionHelpFormatter
from textwrap import dedent
from urllib.parse import urlsplit
from requests.utils import get_netrc_auth
from .argtypes import (
AuthCredentials, KeyValueArgType, PARSED_DEFAULT_FORMAT_OPTIONS,
parse_auth,
parse_format_options,
)
from .constants import (
HTTP_GET, HTTP_POST, OUTPUT_OPTIONS, OUTPUT_OPTIONS_DEFAULT,
OUTPUT_OPTIONS_DEFAULT_OFFLINE, OUTPUT_OPTIONS_DEFAULT_STDOUT_REDIRECTED,
OUT_RESP_BODY, PRETTY_MAP, PRETTY_STDOUT_TTY_ONLY, RequestType,
SEPARATOR_CREDENTIALS,
SEPARATOR_GROUP_ALL_ITEMS, SEPARATOR_GROUP_DATA_ITEMS, URL_SCHEME_RE,
)
from .exceptions import ParseError
from .requestitems import RequestItems
from ..context import Environment
from ..plugins.registry import plugin_manager
from ..utils import ExplicitNullAuth, get_content_type
class HTTPieHelpFormatter(RawDescriptionHelpFormatter):
"""A nicer help formatter.
Help for arguments can be indented and contain new lines.
It will be de-dented and arguments in the help
will be separated by a blank line for better readability.
"""
def __init__(self, max_help_position=6, *args, **kwargs):
# A smaller indent for args help.
kwargs['max_help_position'] = max_help_position
super().__init__(*args, **kwargs)
def _split_lines(self, text, width):
text = dedent(text).strip() + '\n\n'
return text.splitlines()
# TODO: refactor and design type-annotated data structures
# for raw args + parsed args and keep things immutable.
class HTTPieArgumentParser(argparse.ArgumentParser):
"""Adds additional logic to `argparse.ArgumentParser`.
Handles all input (CLI args, file args, stdin), applies defaults,
and performs extra validation.
"""
def __init__(self, *args, formatter_class=HTTPieHelpFormatter, **kwargs):
kwargs['add_help'] = False
super().__init__(*args, formatter_class=formatter_class, **kwargs)
self.env = None
self.args = None
self.has_stdin_data = False
self.has_input_data = False
# noinspection PyMethodOverriding
def parse_args(
self,
env: Environment,
args=None,
namespace=None
) -> argparse.Namespace:
self.env = env
self.args, no_options = super().parse_known_args(args, namespace)
if self.args.prompt:
return self.args
if self.args.debug:
self.args.traceback = True
self.has_stdin_data = (
self.env.stdin
and not self.args.ignore_stdin
and not self.env.stdin_isatty
)
self.has_input_data = self.has_stdin_data or self.args.raw is not None
# Arguments processing and environment setup.
self._apply_no_options(no_options)
self._process_request_type()
self._process_download_options()
self._setup_standard_streams()
self._process_output_options()
self._process_pretty_options()
self._process_format_options()
self._guess_method()
self._parse_items()
self._process_url()
self._process_auth()
if self.args.raw is not None:
self._body_from_input(self.args.raw)
elif self.has_stdin_data:
self._body_from_file(self.env.stdin)
if self.args.compress:
# TODO: allow --compress with --chunked / --multipart
if self.args.chunked:
self.error('cannot combine --compress and --chunked')
if self.args.multipart:
self.error('cannot combine --compress and --multipart')
return self.args
def _process_request_type(self):
request_type = self.args.request_type
self.args.json = request_type is RequestType.JSON
self.args.multipart = request_type is RequestType.MULTIPART
self.args.form = request_type in {
RequestType.FORM,
RequestType.MULTIPART,
}
def _process_url(self):
if not URL_SCHEME_RE.match(self.args.url):
if os.path.basename(self.env.program_name) == 'https':
scheme = 'https://'
else:
scheme = self.args.default_scheme + '://'
# See if we're using curl style shorthand for localhost (:3000/foo)
shorthand = re.match(r'^:(?!:)(\d*)(/?.*)$', self.args.url)
if shorthand:
port = shorthand.group(1)
rest = shorthand.group(2)
self.args.url = scheme + 'localhost'
if port:
self.args.url += ':' + port
self.args.url += rest
else:
self.args.url = scheme + self.args.url
# noinspection PyShadowingBuiltins
def _print_message(self, message, file=None):
# Sneak in our stderr/stdout.
file = {
sys.stdout: self.env.stdout,
sys.stderr: self.env.stderr,
None: self.env.stderr
}.get(file, file)
if not hasattr(file, 'buffer') and isinstance(message, str):
message = message.encode(self.env.stdout_encoding)
super()._print_message(message, file)
def _setup_standard_streams(self):
"""
Modify `env.stdout` and `env.stdout_isatty` based on args, if needed.
"""
self.args.output_file_specified = bool(self.args.output_file)
if self.args.download:
# FIXME: Come up with a cleaner solution.
if not self.args.output_file and not self.env.stdout_isatty:
# Use stdout as the download output file.
self.args.output_file = self.env.stdout
# With `--download`, we write everything that would normally go to
# `stdout` to `stderr` instead. Let's replace the stream so that
# we don't have to use many `if`s throughout the codebase.
# The response body will be treated separately.
self.env.stdout = self.env.stderr
self.env.stdout_isatty = self.env.stderr_isatty
elif self.args.output_file:
# When not `--download`ing, then `--output` simply replaces
# `stdout`. The file is opened for appending, which isn't what
# we want in this case.
self.args.output_file.seek(0)
try:
self.args.output_file.truncate()
except OSError as e:
if e.errno == errno.EINVAL:
# E.g. /dev/null on Linux.
pass
else:
raise
self.env.stdout = self.args.output_file
self.env.stdout_isatty = False
if self.args.quiet:
self.env.stderr = self.env.devnull
if not (self.args.output_file_specified and not self.args.download):
self.env.stdout = self.env.devnull
def _process_auth(self):
# TODO: refactor & simplify this method.
self.args.auth_plugin = None
default_auth_plugin = plugin_manager.get_auth_plugins()[0]
auth_type_set = self.args.auth_type is not None
url = urlsplit(self.args.url)
if self.args.auth is None and not auth_type_set:
if url.username is not None:
# Handle http://username:password@hostname/
username = url.username
password = url.password or ''
self.args.auth = AuthCredentials(
key=username,
value=password,
sep=SEPARATOR_CREDENTIALS,
orig=SEPARATOR_CREDENTIALS.join([username, password])
)
if self.args.auth is not None or auth_type_set:
if not self.args.auth_type:
self.args.auth_type = default_auth_plugin.auth_type
plugin = plugin_manager.get_auth_plugin(self.args.auth_type)()
if (not self.args.ignore_netrc
and self.args.auth is None
and plugin.netrc_parse):
# Only host needed, so its OK URL not finalized.
netrc_credentials = get_netrc_auth(self.args.url)
if netrc_credentials:
self.args.auth = AuthCredentials(
key=netrc_credentials[0],
value=netrc_credentials[1],
sep=SEPARATOR_CREDENTIALS,
orig=SEPARATOR_CREDENTIALS.join(netrc_credentials)
)
if plugin.auth_require and self.args.auth is None:
self.error('--auth required')
plugin.raw_auth = self.args.auth
self.args.auth_plugin = plugin
already_parsed = isinstance(self.args.auth, AuthCredentials)
if self.args.auth is None or not plugin.auth_parse:
self.args.auth = plugin.get_auth()
else:
if already_parsed:
# from the URL
credentials = self.args.auth
else:
credentials = parse_auth(self.args.auth)
if (not credentials.has_password()
and plugin.prompt_password):
if self.args.ignore_stdin:
# Non-tty stdin read by now
self.error(
'Unable to prompt for passwords because'
' --ignore-stdin is set.'
)
credentials.prompt_password(url.netloc)
self.args.auth = plugin.get_auth(
username=credentials.key,
password=credentials.value,
)
if not self.args.auth and self.args.ignore_netrc:
# Set a no-op auth to force requests to ignore .netrc
# <https://github.com/psf/requests/issues/2773#issuecomment-174312831>
self.args.auth = ExplicitNullAuth()
def _apply_no_options(self, no_options):
"""For every `--no-OPTION` in `no_options`, set `args.OPTION` to
its default value. This allows for un-setting of options, e.g.,
specified in config.
"""
invalid = []
for option in no_options:
if not option.startswith('--no-'):
invalid.append(option)
continue
# --no-option => --option
inverted = '--' + option[5:]
for action in self._actions:
if inverted in action.option_strings:
setattr(self.args, action.dest, action.default)
break
else:
invalid.append(option)
if invalid:
self.error(f'unrecognized arguments: {" ".join(invalid)}')
def _body_from_file(self, fd):
"""Read the data from a file-like object.
Bytes are always read.
"""
self._ensure_one_data_source(self.args.data, self.args.files)
self.args.data = getattr(fd, 'buffer', fd)
def _body_from_input(self, data):
"""Read the data from the CLI.
"""
self._ensure_one_data_source(self.has_stdin_data, self.args.data,
self.args.files)
self.args.data = data.encode()
def _ensure_one_data_source(self, *other_sources):
"""There can only be one source of input request data.
"""
if any(other_sources):
self.error('Request body (from stdin, --raw or a file) and request '
'data (key=value) cannot be mixed. Pass '
'--ignore-stdin to let key/value take priority. '
'See https://httpie.io/docs#scripting for details.')
def _guess_method(self):
"""Set `args.method` if not specified to either POST or GET
based on whether the request has data or not.
"""
if self.args.method is None:
# Invoked as `http URL'.
assert not self.args.request_items
if self.has_input_data:
self.args.method = HTTP_POST
else:
self.args.method = HTTP_GET
# FIXME: False positive, e.g., "localhost" matches but is a valid URL.
elif not re.match('^[a-zA-Z]+$', self.args.method):
# Invoked as `http URL item+'. The URL is now in `args.method`
# and the first ITEM is now incorrectly in `args.url`.
try:
# Parse the URL as an ITEM and store it as the first ITEM arg.
self.args.request_items.insert(0, KeyValueArgType(
*SEPARATOR_GROUP_ALL_ITEMS).__call__(self.args.url))
except argparse.ArgumentTypeError as e:
if self.args.traceback:
raise
self.error(e.args[0])
else:
# Set the URL correctly
self.args.url = self.args.method
# Infer the method
has_data = (
self.has_input_data
or any(
item.sep in SEPARATOR_GROUP_DATA_ITEMS
for item in self.args.request_items)
)
self.args.method = HTTP_POST if has_data else HTTP_GET
def _parse_items(self):
"""
Parse `args.request_items` into `args.headers`, `args.data`,
`args.params`, and `args.files`.
"""
try:
request_items = RequestItems.from_args(
request_item_args=self.args.request_items,
as_form=self.args.form,
)
except ParseError as e:
if self.args.traceback:
raise
self.error(e.args[0])
else:
self.args.headers = request_items.headers
self.args.data = request_items.data
self.args.files = request_items.files
self.args.params = request_items.params
self.args.multipart_data = request_items.multipart_data
if self.args.files and not self.args.form:
# `http url @/path/to/file`
request_file = None
for key, file in self.args.files.items():
if key != '':
self.error(
'Invalid file fields (perhaps you meant --form?):'
f' {",".join(self.args.files.keys())}')
if request_file is not None:
self.error("Can't read request from multiple files")
request_file = file
fn, fd, ct = request_file
self.args.files = {}
self._body_from_file(fd)
if 'Content-Type' not in self.args.headers:
content_type = get_content_type(fn)
if content_type:
self.args.headers['Content-Type'] = content_type
def _process_output_options(self):
"""Apply defaults to output options, or validate the provided ones.
The default output options are stdout-type-sensitive.
"""
def check_options(value, option):
unknown = set(value) - OUTPUT_OPTIONS
if unknown:
self.error(f'Unknown output options: {option}={",".join(unknown)}')
if self.args.verbose:
self.args.all = True
if self.args.output_options is None:
if self.args.verbose:
self.args.output_options = ''.join(OUTPUT_OPTIONS)
elif self.args.offline:
self.args.output_options = OUTPUT_OPTIONS_DEFAULT_OFFLINE
elif not self.env.stdout_isatty:
self.args.output_options = OUTPUT_OPTIONS_DEFAULT_STDOUT_REDIRECTED
else:
self.args.output_options = OUTPUT_OPTIONS_DEFAULT
if self.args.output_options_history is None:
self.args.output_options_history = self.args.output_options
check_options(self.args.output_options, '--print')
check_options(self.args.output_options_history, '--history-print')
if self.args.download and OUT_RESP_BODY in self.args.output_options:
# Response body is always downloaded with --download and it goes
# through a different routine, so we remove it.
self.args.output_options = str(
set(self.args.output_options) - set(OUT_RESP_BODY))
def _process_pretty_options(self):
if self.args.prettify == PRETTY_STDOUT_TTY_ONLY:
self.args.prettify = PRETTY_MAP[
'all' if self.env.stdout_isatty else 'none']
elif (self.args.prettify and self.env.is_windows
and self.args.output_file):
self.error('Only terminal output can be colorized on Windows.')
else:
# noinspection PyTypeChecker
self.args.prettify = PRETTY_MAP[self.args.prettify]
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')
if self.args.download_resume and not (
self.args.download and self.args.output_file):
self.error('--continue requires --output to be specified')
def _process_format_options(self):
format_options = self.args.format_options or []
parsed_options = PARSED_DEFAULT_FORMAT_OPTIONS
for options_group in format_options:
parsed_options = parse_format_options(options_group, defaults=parsed_options)
self.args.format_options = parsed_options

260
httpie/cli/argtypes.py Normal file
View File

@ -0,0 +1,260 @@
import argparse
import getpass
import os
import sys
from copy import deepcopy
from typing import List, Optional, Union
from .constants import DEFAULT_FORMAT_OPTIONS, SEPARATOR_CREDENTIALS
from ..sessions import VALID_SESSION_NAME_PATTERN
class KeyValueArg:
"""Base key-value pair parsed from CLI."""
def __init__(self, key: str, value: Optional[str], sep: str, orig: str):
self.key = key
self.value = value
self.sep = sep
self.orig = orig
def __eq__(self, other: 'KeyValueArg'):
return self.__dict__ == other.__dict__
def __repr__(self):
return repr(self.__dict__)
class SessionNameValidator:
def __init__(self, error_message: str):
self.error_message = error_message
def __call__(self, value: str) -> str:
# Session name can be a path or just a name.
if (os.path.sep not in value
and not VALID_SESSION_NAME_PATTERN.search(value)):
raise argparse.ArgumentError(None, self.error_message)
return value
class Escaped(str):
"""Represents an escaped character."""
def __repr__(self):
return f"Escaped({repr(str(self))})"
class KeyValueArgType:
"""A key-value pair argument type used with `argparse`.
Parses a key-value arg and constructs a `KeyValueArg` instance.
Used for headers, form data, and other key-value pair types.
"""
key_value_class = KeyValueArg
def __init__(self, *separators: str):
self.separators = separators
self.special_characters = set('\\')
for separator in separators:
self.special_characters.update(separator)
def __call__(self, s: str) -> KeyValueArg:
"""Parse raw string arg and return `self.key_value_class` instance.
The best of `self.separators` is determined (first found, longest).
Back slash escaped characters aren't considered as separators
(or parts thereof). Literal back slash characters have to be escaped
as well (r'\\').
"""
tokens = self.tokenize(s)
# Sorting by length ensures that the longest one will be
# chosen as it will overwrite any shorter ones starting
# at the same position in the `found` dictionary.
separators = sorted(self.separators, key=len)
for i, token in enumerate(tokens):
if isinstance(token, Escaped):
continue
found = {}
for sep in separators:
pos = token.find(sep)
if pos != -1:
found[pos] = sep
if found:
# Starting first, longest separator found.
sep = found[min(found.keys())]
key, value = token.split(sep, 1)
# Any preceding tokens are part of the key.
key = ''.join(tokens[:i]) + key
# Any following tokens are part of the value.
value += ''.join(tokens[i + 1:])
break
else:
raise argparse.ArgumentTypeError(f'{s!r} is not a valid value')
return self.key_value_class(key=key, value=value, sep=sep, orig=s)
def tokenize(self, s: str) -> List[Union[str, Escaped]]:
r"""Tokenize the raw arg string
There are only two token types - strings and escaped characters:
>>> KeyValueArgType('=').tokenize(r'foo\=bar\\baz')
['foo', Escaped('='), 'bar', Escaped('\\'), 'baz']
"""
tokens = ['']
characters = iter(s)
for char in characters:
if char == '\\':
char = next(characters, '')
if char not in self.special_characters:
tokens[-1] += '\\' + char
else:
tokens.extend([Escaped(char), ''])
else:
tokens[-1] += char
return tokens
class AuthCredentials(KeyValueArg):
"""Represents parsed credentials."""
def has_password(self) -> bool:
return self.value is not None
def prompt_password(self, host: str):
prompt_text = f'http: password for {self.key}@{host}: '
try:
self.value = self._getpass(prompt_text)
except (EOFError, KeyboardInterrupt):
sys.stderr.write('\n')
sys.exit(0)
@staticmethod
def _getpass(prompt):
# To allow easy mocking.
return getpass.getpass(str(prompt))
class AuthCredentialsArgType(KeyValueArgType):
"""A key-value arg type that parses credentials."""
key_value_class = AuthCredentials
def __call__(self, s):
"""Parse credentials from `s`.
("username" or "username:password").
"""
try:
return super().__call__(s)
except argparse.ArgumentTypeError:
# No password provided, will prompt for it later.
return self.key_value_class(
key=s,
value=None,
sep=SEPARATOR_CREDENTIALS,
orig=s
)
parse_auth = AuthCredentialsArgType(SEPARATOR_CREDENTIALS)
def readable_file_arg(filename):
try:
with open(filename, 'rb'):
return filename
except OSError as ex:
raise argparse.ArgumentTypeError(f'{ex.filename}: {ex.strerror}')
def parse_format_options(s: str, defaults: Optional[dict]) -> dict:
"""
Parse `s` and update `defaults` with the parsed values.
>>> parse_format_options(
... defaults={'json': {'indent': 4, 'sort_keys': True}},
... s='json.indent:2,json.sort_keys:False',
... )
{'json': {'indent': 2, 'sort_keys': False}}
"""
value_map = {
'true': True,
'false': False,
}
options = deepcopy(defaults or {})
for option in s.split(','):
try:
path, value = option.lower().split(':')
section, key = path.split('.')
except ValueError:
raise argparse.ArgumentTypeError(f'invalid option {option!r}')
if value in value_map:
parsed_value = value_map[value]
else:
if value.isnumeric():
parsed_value = int(value)
else:
parsed_value = value
if defaults is None:
options.setdefault(section, {})
else:
try:
default_value = defaults[section][key]
except KeyError:
raise argparse.ArgumentTypeError(
f'invalid key {path!r}')
default_type, parsed_type = type(default_value), type(parsed_value)
if parsed_type is not default_type:
raise argparse.ArgumentTypeError(
'invalid value'
f' {value!r} in {option!r}'
f' (expected {default_type.__name__}'
f' got {parsed_type.__name__})'
)
options[section][key] = parsed_value
return options
PARSED_DEFAULT_FORMAT_OPTIONS = parse_format_options(
s=','.join(DEFAULT_FORMAT_OPTIONS),
defaults=None,
)
def response_charset_type(encoding: str) -> str:
try:
''.encode(encoding)
except LookupError:
raise argparse.ArgumentTypeError(
f'{encoding!r} is not a supported encoding')
return encoding
def response_mime_type(mime_type: str) -> str:
if mime_type.count('/') != 1:
raise argparse.ArgumentTypeError(
f'{mime_type!r} doesnt look like a mime type; use type/subtype')
return mime_type

113
httpie/cli/constants.py Normal file
View File

@ -0,0 +1,113 @@
"""Parsing and processing of CLI input (args, auth credentials, files, stdin).
"""
import enum
import re
URL_SCHEME_RE = re.compile(r'^[a-z][a-z0-9.+-]*://', re.IGNORECASE)
HTTP_POST = 'POST'
HTTP_GET = 'GET'
# Various separators used in args
SEPARATOR_HEADER = ':'
SEPARATOR_HEADER_EMPTY = ';'
SEPARATOR_CREDENTIALS = ':'
SEPARATOR_PROXY = ':'
SEPARATOR_DATA_STRING = '='
SEPARATOR_DATA_RAW_JSON = ':='
SEPARATOR_FILE_UPLOAD = '@'
SEPARATOR_FILE_UPLOAD_TYPE = ';type=' # in already parsed file upload path only
SEPARATOR_DATA_EMBED_FILE_CONTENTS = '=@'
SEPARATOR_DATA_EMBED_RAW_JSON_FILE = ':=@'
SEPARATOR_QUERY_PARAM = '=='
# Separators that become request data
SEPARATOR_GROUP_DATA_ITEMS = frozenset({
SEPARATOR_DATA_STRING,
SEPARATOR_DATA_RAW_JSON,
SEPARATOR_FILE_UPLOAD,
SEPARATOR_DATA_EMBED_FILE_CONTENTS,
SEPARATOR_DATA_EMBED_RAW_JSON_FILE
})
SEPARATORS_GROUP_MULTIPART = frozenset({
SEPARATOR_DATA_STRING,
SEPARATOR_DATA_EMBED_FILE_CONTENTS,
SEPARATOR_FILE_UPLOAD,
})
# Separators for items whose value is a filename to be embedded
SEPARATOR_GROUP_DATA_EMBED_ITEMS = frozenset({
SEPARATOR_DATA_EMBED_FILE_CONTENTS,
SEPARATOR_DATA_EMBED_RAW_JSON_FILE,
})
# Separators for raw JSON items
SEPARATOR_GROUP_RAW_JSON_ITEMS = frozenset([
SEPARATOR_DATA_RAW_JSON,
SEPARATOR_DATA_EMBED_RAW_JSON_FILE,
])
# Separators allowed in ITEM arguments
SEPARATOR_GROUP_ALL_ITEMS = frozenset({
SEPARATOR_HEADER,
SEPARATOR_HEADER_EMPTY,
SEPARATOR_QUERY_PARAM,
SEPARATOR_DATA_STRING,
SEPARATOR_DATA_RAW_JSON,
SEPARATOR_FILE_UPLOAD,
SEPARATOR_DATA_EMBED_FILE_CONTENTS,
SEPARATOR_DATA_EMBED_RAW_JSON_FILE,
})
# Output options
OUT_REQ_HEAD = 'H'
OUT_REQ_BODY = 'B'
OUT_RESP_HEAD = 'h'
OUT_RESP_BODY = 'b'
OUTPUT_OPTIONS = frozenset({
OUT_REQ_HEAD,
OUT_REQ_BODY,
OUT_RESP_HEAD,
OUT_RESP_BODY
})
# Pretty
PRETTY_MAP = {
'all': ['format', 'colors'],
'colors': ['colors'],
'format': ['format'],
'none': []
}
PRETTY_STDOUT_TTY_ONLY = object()
DEFAULT_FORMAT_OPTIONS = [
'headers.sort:true',
'json.format:true',
'json.indent:4',
'json.sort_keys:true',
'xml.format:true',
'xml.indent:2',
]
SORTED_FORMAT_OPTIONS = [
'headers.sort:true',
'json.sort_keys:true',
]
SORTED_FORMAT_OPTIONS_STRING = ','.join(SORTED_FORMAT_OPTIONS)
UNSORTED_FORMAT_OPTIONS_STRING = ','.join(
option.replace('true', 'false') for option in SORTED_FORMAT_OPTIONS)
# Defaults
OUTPUT_OPTIONS_DEFAULT = OUT_RESP_HEAD + OUT_RESP_BODY
OUTPUT_OPTIONS_DEFAULT_STDOUT_REDIRECTED = OUT_RESP_BODY
OUTPUT_OPTIONS_DEFAULT_OFFLINE = OUT_REQ_HEAD + OUT_REQ_BODY
class RequestType(enum.Enum):
FORM = enum.auto()
MULTIPART = enum.auto()
JSON = enum.auto()

852
httpie/cli/definition.py Normal file
View File

@ -0,0 +1,852 @@
"""
CLI arguments definition.
"""
from argparse import FileType, OPTIONAL, SUPPRESS, ZERO_OR_MORE
from textwrap import dedent, wrap
from .. import __doc__, __version__
from .argparser import HTTPieArgumentParser
from .argtypes import (
KeyValueArgType, SessionNameValidator,
readable_file_arg, response_charset_type, response_mime_type,
)
from .constants import (
DEFAULT_FORMAT_OPTIONS, OUTPUT_OPTIONS,
OUTPUT_OPTIONS_DEFAULT, OUT_REQ_BODY, OUT_REQ_HEAD,
OUT_RESP_BODY, OUT_RESP_HEAD, PRETTY_MAP, PRETTY_STDOUT_TTY_ONLY,
RequestType, SEPARATOR_GROUP_ALL_ITEMS, SEPARATOR_PROXY,
SORTED_FORMAT_OPTIONS_STRING,
UNSORTED_FORMAT_OPTIONS_STRING,
)
from ..output.formatters.colors import (
AUTO_STYLE, AVAILABLE_STYLES, DEFAULT_STYLE,
)
from ..plugins.builtin import BuiltinAuthPlugin
from ..plugins.registry import plugin_manager
from ..sessions import DEFAULT_SESSIONS_DIR
from ..ssl import AVAILABLE_SSL_VERSION_ARG_MAPPING, DEFAULT_SSL_CIPHERS
parser = HTTPieArgumentParser(
prog='http',
description=f'{__doc__.strip()} <https://httpie.io>',
epilog=dedent('''
For every --OPTION there is also a --no-OPTION that reverts OPTION
to its default value.
Suggestions and bug reports are greatly appreciated:
https://github.com/httpie/httpie/issues
'''),
)
#######################################################################
# Positional arguments.
#######################################################################
positional = parser.add_argument_group(
title='Positional Arguments',
description=dedent('''
These arguments come after any flags and in the order they are listed here.
Only URL is required.
''')
)
positional.add_argument(
dest='method',
metavar='METHOD',
nargs=OPTIONAL,
default=None,
help='''
The HTTP method to be used for the request (GET, POST, PUT, DELETE, ...).
This argument can be omitted in which case HTTPie will use POST if there
is some data to be sent, otherwise GET:
$ http example.org # => GET
$ http example.org hello=world # => POST
'''
)
positional.add_argument(
dest='url',
metavar='URL',
nargs=OPTIONAL,
help='''
The scheme defaults to 'http://' if the URL does not include one.
(You can override this with: --default-scheme=https)
You can also use a shorthand for localhost
$ http :3000 # => http://localhost:3000
$ http :/foo # => http://localhost/foo
'''
)
positional.add_argument(
dest='request_items',
metavar='REQUEST_ITEM',
nargs=ZERO_OR_MORE,
default=None,
type=KeyValueArgType(*SEPARATOR_GROUP_ALL_ITEMS),
help=r'''
Optional key-value pairs to be included in the request. The separator used
determines the type:
':' HTTP headers:
Referer:https://httpie.io Cookie:foo=bar User-Agent:bacon/1.0
'==' URL parameters to be appended to the request URI:
search==httpie
'=' Data fields to be serialized into a JSON object (with --json, -j)
or form data (with --form, -f):
name=HTTPie language=Python description='CLI HTTP client'
':=' Non-string JSON data fields (only with --json, -j):
awesome:=true amount:=42 colors:='["red", "green", "blue"]'
'@' Form file fields (only with --form or --multipart):
cv@~/Documents/CV.pdf
cv@'~/Documents/CV.pdf;type=application/pdf'
'=@' A data field like '=', but takes a file path and embeds its content:
essay=@Documents/essay.txt
':=@' A raw JSON field like ':=', but takes a file path and embeds its content:
package:=@./package.json
You can use a backslash to escape a colliding separator in the field name:
field-name-with\:colon=value
'''
)
#######################################################################
# Content type.
#######################################################################
content_type = parser.add_argument_group(
title='Predefined Content Types',
description=None
)
content_type.add_argument(
'--json', '-j',
action='store_const',
const=RequestType.JSON,
dest='request_type',
help='''
(default) Data items from the command line are serialized as a JSON object.
The Content-Type and Accept headers are set to application/json
(if not specified).
'''
)
content_type.add_argument(
'--form', '-f',
action='store_const',
const=RequestType.FORM,
dest='request_type',
help='''
Data items from the command line are serialized as form fields.
The Content-Type is set to application/x-www-form-urlencoded (if not
specified). The presence of any file fields results in a
multipart/form-data request.
'''
)
content_type.add_argument(
'--multipart',
action='store_const',
const=RequestType.MULTIPART,
dest='request_type',
help='''
Similar to --form, but always sends a multipart/form-data
request (i.e., even without files).
'''
)
content_type.add_argument(
'--boundary',
help='''
Specify a custom boundary string for multipart/form-data requests.
Only has effect only together with --form.
'''
)
content_type.add_argument(
'--raw',
help='''
This option allows you to pass raw request data without extra processing
(as opposed to the structured request items syntax):
$ http --raw='data' pie.dev/post
You can achieve the same by piping the data via stdin:
$ echo data | http pie.dev/post
Or have HTTPie load the raw data from a file:
$ http pie.dev/post @data.txt
'''
)
#######################################################################
# Content processing.
#######################################################################
content_processing = parser.add_argument_group(
title='Content Processing Options',
description=None
)
content_processing.add_argument(
'--compress', '-x',
action='count',
default=0,
help='''
Content compressed (encoded) with Deflate algorithm.
The Content-Encoding header is set to deflate.
Compression is skipped if it appears that compression ratio is
negative. Compression can be forced by repeating the argument.
'''
)
#######################################################################
# Output processing
#######################################################################
output_processing = parser.add_argument_group(title='Output Processing')
output_processing.add_argument(
'--pretty',
dest='prettify',
default=PRETTY_STDOUT_TTY_ONLY,
choices=sorted(PRETTY_MAP.keys()),
help='''
Controls output processing. The value can be "none" to not prettify
the output (default for redirected output), "all" to apply both colors
and formatting (default for terminal output), "colors", or "format".
'''
)
output_processing.add_argument(
'--style', '-s',
dest='style',
metavar='STYLE',
default=DEFAULT_STYLE,
choices=sorted(AVAILABLE_STYLES),
help='''
Output coloring style (default is "{default}"). It can be One of:
{available_styles}
The "{auto_style}" style follows your terminal's ANSI color styles.
For non-{auto_style} styles to work properly, please make sure that the
$TERM environment variable is set to "xterm-256color" or similar
(e.g., via `export TERM=xterm-256color' in your ~/.bashrc).
'''.format(
default=DEFAULT_STYLE,
available_styles='\n'.join(
f' {line.strip()}'
for line in wrap(', '.join(sorted(AVAILABLE_STYLES)), 60)
).strip(),
auto_style=AUTO_STYLE,
)
)
_sorted_kwargs = {
'action': 'append_const',
'const': SORTED_FORMAT_OPTIONS_STRING,
'dest': 'format_options'
}
_unsorted_kwargs = {
'action': 'append_const',
'const': UNSORTED_FORMAT_OPTIONS_STRING,
'dest': 'format_options'
}
# The closest approx. of the documented resetting to default via --no-<option>.
# We hide them from the doc because they act only as low-level aliases here.
output_processing.add_argument('--no-unsorted', **_sorted_kwargs, help=SUPPRESS)
output_processing.add_argument('--no-sorted', **_unsorted_kwargs, help=SUPPRESS)
output_processing.add_argument(
'--unsorted',
**_unsorted_kwargs,
help=f'''
Disables all sorting while formatting output. It is a shortcut for:
--format-options={UNSORTED_FORMAT_OPTIONS_STRING}
'''
)
output_processing.add_argument(
'--sorted',
**_sorted_kwargs,
help=f'''
Re-enables all sorting options while formatting output. It is a shortcut for:
--format-options={SORTED_FORMAT_OPTIONS_STRING}
'''
)
output_processing.add_argument(
'--response-charset',
metavar='ENCODING',
type=response_charset_type,
help='''
Override the response encoding for terminal display purposes, e.g.:
--response-charset=utf8
--response-charset=big5
'''
)
output_processing.add_argument(
'--response-mime',
metavar='MIME_TYPE',
type=response_mime_type,
help='''
Override the response mime type for coloring and formatting for the terminal, e.g.:
--response-mime=application/json
--response-mime=text/xml
'''
)
output_processing.add_argument(
'--format-options',
action='append',
help='''
Controls output formatting. Only relevant when formatting is enabled
through (explicit or implied) --pretty=all or --pretty=format.
The following are the default options:
{option_list}
You may use this option multiple times, as well as specify multiple
comma-separated options at the same time. For example, this modifies the
settings to disable the sorting of JSON keys, and sets the indent size to 2:
--format-options json.sort_keys:false,json.indent:2
This is something you will typically put into your config file.
'''.format(
option_list='\n'.join(
f' {option}' for option in DEFAULT_FORMAT_OPTIONS).strip()
)
)
#######################################################################
# Output options
#######################################################################
output_options = parser.add_argument_group(title='Output Options')
output_options.add_argument(
'--print', '-p',
dest='output_options',
metavar='WHAT',
help=f'''
String specifying what the output should contain:
'{OUT_REQ_HEAD}' request headers
'{OUT_REQ_BODY}' request body
'{OUT_RESP_HEAD}' response headers
'{OUT_RESP_BODY}' response body
The default behaviour is '{OUTPUT_OPTIONS_DEFAULT}' (i.e., the response
headers and body is printed), if standard output is not redirected.
If the output is piped to another program or to a file, then only the
response body is printed by default.
'''
)
output_options.add_argument(
'--headers', '-h',
dest='output_options',
action='store_const',
const=OUT_RESP_HEAD,
help=f'''
Print only the response headers. Shortcut for --print={OUT_RESP_HEAD}.
'''
)
output_options.add_argument(
'--body', '-b',
dest='output_options',
action='store_const',
const=OUT_RESP_BODY,
help=f'''
Print only the response body. Shortcut for --print={OUT_RESP_BODY}.
'''
)
output_options.add_argument(
'--verbose', '-v',
dest='verbose',
action='store_true',
help=f'''
Verbose output. Print the whole request as well as the response. Also print
any intermediary requests/responses (such as redirects).
It's a shortcut for: --all --print={''.join(OUTPUT_OPTIONS)}
'''
)
output_options.add_argument(
'--all',
default=False,
action='store_true',
help='''
By default, only the final request/response is shown. Use this flag to show
any intermediary requests/responses as well. Intermediary requests include
followed redirects (with --follow), the first unauthorized request when
Digest auth is used (--auth=digest), etc.
'''
)
output_options.add_argument(
'--history-print', '-P',
dest='output_options_history',
metavar='WHAT',
help='''
The same as --print, -p but applies only to intermediary requests/responses
(such as redirects) when their inclusion is enabled with --all. If this
options is not specified, then they are formatted the same way as the final
response.
'''
)
output_options.add_argument(
'--stream', '-S',
action='store_true',
default=False,
help='''
Always stream the response body by line, i.e., behave like `tail -f'.
Without --stream and with --pretty (either set or implied),
HTTPie fetches the whole response before it outputs the processed data.
Set this option when you want to continuously display a prettified
long-lived response, such as one from the Twitter streaming API.
It is useful also without --pretty: It ensures that the output is flushed
more often and in smaller chunks.
'''
)
output_options.add_argument(
'--output', '-o',
type=FileType('a+b'),
dest='output_file',
metavar='FILE',
help='''
Save output to FILE instead of stdout. If --download is also set, then only
the response body is saved to FILE. Other parts of the HTTP exchange are
printed to stderr.
'''
)
output_options.add_argument(
'--download', '-d',
action='store_true',
default=False,
help='''
Do not print the response body to stdout. Rather, download it and store it
in a file. The filename is guessed unless specified with --output
[filename]. This action is similar to the default behaviour of wget.
'''
)
output_options.add_argument(
'--continue', '-c',
dest='download_resume',
action='store_true',
default=False,
help='''
Resume an interrupted download. Note that the --output option needs to be
specified as well.
'''
)
output_options.add_argument(
'--quiet', '-q',
action='store_true',
default=False,
help='''
Do not print to stdout or stderr.
stdout is still redirected if --output is specified.
Flag doesn't affect behaviour of download beyond not printing to terminal.
'''
)
#######################################################################
# Sessions
#######################################################################
sessions = parser.add_argument_group(title='Sessions') \
.add_mutually_exclusive_group(required=False)
session_name_validator = SessionNameValidator(
'Session name contains invalid characters.'
)
sessions.add_argument(
'--session',
metavar='SESSION_NAME_OR_PATH',
type=session_name_validator,
help=f'''
Create, or reuse and update a session. Within a session, custom headers,
auth credential, as well as any cookies sent by the server persist between
requests.
Session files are stored in:
{DEFAULT_SESSIONS_DIR}/<HOST>/<SESSION_NAME>.json.
'''
)
sessions.add_argument(
'--session-read-only',
metavar='SESSION_NAME_OR_PATH',
type=session_name_validator,
help='''
Create or read a session without updating it form the request/response
exchange.
'''
)
#######################################################################
# Authentication
#######################################################################
# ``requests.request`` keyword arguments.
auth = parser.add_argument_group(title='Authentication')
auth.add_argument(
'--auth', '-a',
default=None,
metavar='USER[:PASS]',
help='''
If only the username is provided (-a username), HTTPie will prompt
for the password.
''',
)
class _AuthTypeLazyChoices:
# Needed for plugin testing
def __contains__(self, item):
return item in plugin_manager.get_auth_plugin_mapping()
def __iter__(self):
return iter(sorted(plugin_manager.get_auth_plugin_mapping().keys()))
_auth_plugins = plugin_manager.get_auth_plugins()
auth.add_argument(
'--auth-type', '-A',
choices=_AuthTypeLazyChoices(),
default=None,
help='''
The authentication mechanism to be used. Defaults to "{default}".
{types}
'''.format(default=_auth_plugins[0].auth_type, types='\n '.join(
'"{type}": {name}{package}{description}'.format(
type=plugin.auth_type,
name=plugin.name,
package=(
'' if issubclass(plugin, BuiltinAuthPlugin)
else f' (provided by {plugin.package_name})'
),
description=(
'' if not plugin.description else
'\n ' + ('\n '.join(wrap(plugin.description)))
)
)
for plugin in _auth_plugins
)),
)
auth.add_argument(
'--ignore-netrc',
default=False,
action='store_true',
help='''
Ignore credentials from .netrc.
''',
)
#######################################################################
# Network
#######################################################################
network = parser.add_argument_group(title='Network')
network.add_argument(
'--offline',
default=False,
action='store_true',
help='''
Build the request and print it but dont actually send it.
'''
)
network.add_argument(
'--proxy',
default=[],
action='append',
metavar='PROTOCOL:PROXY_URL',
type=KeyValueArgType(SEPARATOR_PROXY),
help='''
String mapping protocol to the URL of the proxy
(e.g. http:http://foo.bar:3128). You can specify multiple proxies with
different protocols. The environment variables $ALL_PROXY, $HTTP_PROXY,
and $HTTPS_proxy are supported as well.
'''
)
network.add_argument(
'--follow', '-F',
default=False,
action='store_true',
help='''
Follow 30x Location redirects.
'''
)
network.add_argument(
'--max-redirects',
type=int,
default=30,
help='''
By default, requests have a limit of 30 redirects (works with --follow).
'''
)
network.add_argument(
'--max-headers',
type=int,
default=0,
help='''
The maximum number of response headers to be read before giving up
(default 0, i.e., no limit).
'''
)
network.add_argument(
'--timeout',
type=float,
default=0,
metavar='SECONDS',
help='''
The connection timeout of the request in seconds.
The default value is 0, i.e., there is no timeout limit.
This is not a time limit on the entire response download;
rather, an error is reported if the server has not issued a response for
timeout seconds (more precisely, if no bytes have been received on
the underlying socket for timeout seconds).
'''
)
network.add_argument(
'--check-status',
default=False,
action='store_true',
help='''
By default, HTTPie exits with 0 when no network or other fatal errors
occur. This flag instructs HTTPie to also check the HTTP status code and
exit with an error if the status indicates one.
When the server replies with a 4xx (Client Error) or 5xx (Server Error)
status code, HTTPie exits with 4 or 5 respectively. If the response is a
3xx (Redirect) and --follow hasn't been set, then the exit status is 3.
Also an error message is written to stderr if stdout is redirected.
'''
)
network.add_argument(
'--path-as-is',
default=False,
action='store_true',
help='''
Bypass dot segment (/../ or /./) URL squashing.
'''
)
network.add_argument(
'--chunked',
default=False,
action='store_true',
help='''
Enable streaming via chunked transfer encoding.
The Transfer-Encoding header is set to chunked.
'''
)
#######################################################################
# SSL
#######################################################################
ssl = parser.add_argument_group(title='SSL')
ssl.add_argument(
'--verify',
default='yes',
help='''
Set to "no" (or "false") to skip checking the host's SSL certificate.
Defaults to "yes" ("true"). You can also pass the path to a CA_BUNDLE file
for private certs. (Or you can set the REQUESTS_CA_BUNDLE environment
variable instead.)
'''
)
ssl.add_argument(
'--ssl',
dest='ssl_version',
choices=sorted(AVAILABLE_SSL_VERSION_ARG_MAPPING.keys()),
help='''
The desired protocol version to use. This will default to
SSL v2.3 which will negotiate the highest protocol that both
the server and your installation of OpenSSL support. Available protocols
may vary depending on OpenSSL installation (only the supported ones
are shown here).
'''
)
ssl.add_argument(
'--ciphers',
help=f'''
A string in the OpenSSL cipher list format. By default, the following
is used:
{DEFAULT_SSL_CIPHERS}
'''
)
ssl.add_argument(
'--cert',
default=None,
type=readable_file_arg,
help='''
You can specify a local cert to use as client side SSL certificate.
This file may either contain both private key and certificate or you may
specify --cert-key separately.
'''
)
ssl.add_argument(
'--cert-key',
default=None,
type=readable_file_arg,
help='''
The private key to use with SSL. Only needed if --cert is given and the
certificate file does not contain the private key.
'''
)
#######################################################################
# Troubleshooting
#######################################################################
troubleshooting = parser.add_argument_group(title='Troubleshooting')
troubleshooting.add_argument(
'--ignore-stdin', '-I',
action='store_true',
default=False,
help='''
Do not attempt to read stdin.
'''
)
troubleshooting.add_argument(
'--help',
action='help',
default=SUPPRESS,
help='''
Show this help message and exit.
'''
)
troubleshooting.add_argument(
'--version',
action='version',
version=__version__,
help='''
Show version and exit.
'''
)
troubleshooting.add_argument(
'--traceback',
action='store_true',
default=False,
help='''
Prints the exception traceback should one occur.
'''
)
troubleshooting.add_argument(
'--default-scheme',
default="http",
help='''
The default scheme to use if not specified in the URL.
'''
)
troubleshooting.add_argument(
'--debug',
action='store_true',
default=False,
help='''
Prints the exception traceback should one occur, as well as other
information useful for debugging HTTPie itself and for reporting bugs.
'''
)
troubleshooting.add_argument(
'--prompt',
action='store_true',
default=False,
help='''
Start the shell!
'''
)

58
httpie/cli/dicts.py Normal file
View File

@ -0,0 +1,58 @@
from collections import OrderedDict
from requests.structures import CaseInsensitiveDict
class RequestHeadersDict(CaseInsensitiveDict):
"""
Headers are case-insensitive and multiple values are currently not supported.
"""
class RequestJSONDataDict(OrderedDict):
pass
class MultiValueOrderedDict(OrderedDict):
"""Multi-value dict for URL parameters and form data."""
def __setitem__(self, key, value):
"""
If `key` is assigned more than once, `self[key]` holds a
`list` of all the values.
This allows having multiple fields with the same name in form
data and URL params.
"""
assert not isinstance(value, list)
if key not in self:
super().__setitem__(key, value)
else:
if not isinstance(self[key], list):
super().__setitem__(key, [self[key]])
self[key].append(value)
def items(self):
for key, values in super().items():
if not isinstance(values, list):
values = [values]
for value in values:
yield key, value
class RequestQueryParamsDict(MultiValueOrderedDict):
pass
class RequestDataDict(MultiValueOrderedDict):
pass
class MultipartRequestDataDict(MultiValueOrderedDict):
pass
class RequestFilesDict(RequestDataDict):
pass

2
httpie/cli/exceptions.py Normal file
View File

@ -0,0 +1,2 @@
class ParseError(Exception):
pass

155
httpie/cli/requestitems.py Normal file
View File

@ -0,0 +1,155 @@
import os
from typing import Callable, Dict, IO, List, Optional, Tuple, Union
from .argtypes import KeyValueArg
from .constants import (
SEPARATORS_GROUP_MULTIPART, SEPARATOR_DATA_EMBED_FILE_CONTENTS,
SEPARATOR_DATA_EMBED_RAW_JSON_FILE,
SEPARATOR_DATA_RAW_JSON, SEPARATOR_DATA_STRING, SEPARATOR_FILE_UPLOAD,
SEPARATOR_FILE_UPLOAD_TYPE, SEPARATOR_HEADER, SEPARATOR_HEADER_EMPTY,
SEPARATOR_QUERY_PARAM,
)
from .dicts import (
MultipartRequestDataDict, RequestDataDict, RequestFilesDict,
RequestHeadersDict, RequestJSONDataDict,
RequestQueryParamsDict,
)
from .exceptions import ParseError
from ..utils import get_content_type, load_json_preserve_order_and_dupe_keys
class RequestItems:
def __init__(self, as_form=False):
self.headers = RequestHeadersDict()
self.data = RequestDataDict() if as_form else RequestJSONDataDict()
self.files = RequestFilesDict()
self.params = RequestQueryParamsDict()
# To preserve the order of fields in file upload multipart requests.
self.multipart_data = MultipartRequestDataDict()
@classmethod
def from_args(
cls,
request_item_args: List[KeyValueArg],
as_form=False,
) -> 'RequestItems':
instance = cls(as_form=as_form)
rules: Dict[str, Tuple[Callable, dict]] = {
SEPARATOR_HEADER: (
process_header_arg,
instance.headers,
),
SEPARATOR_HEADER_EMPTY: (
process_empty_header_arg,
instance.headers,
),
SEPARATOR_QUERY_PARAM: (
process_query_param_arg,
instance.params,
),
SEPARATOR_FILE_UPLOAD: (
process_file_upload_arg,
instance.files,
),
SEPARATOR_DATA_STRING: (
process_data_item_arg,
instance.data,
),
SEPARATOR_DATA_EMBED_FILE_CONTENTS: (
process_data_embed_file_contents_arg,
instance.data,
),
SEPARATOR_DATA_RAW_JSON: (
process_data_raw_json_embed_arg,
instance.data,
),
SEPARATOR_DATA_EMBED_RAW_JSON_FILE: (
process_data_embed_raw_json_file_arg,
instance.data,
),
}
for arg in request_item_args:
processor_func, target_dict = rules[arg.sep]
value = processor_func(arg)
target_dict[arg.key] = value
if arg.sep in SEPARATORS_GROUP_MULTIPART:
instance.multipart_data[arg.key] = value
return instance
JSONType = Union[str, bool, int, list, dict]
def process_header_arg(arg: KeyValueArg) -> Optional[str]:
return arg.value or None
def process_empty_header_arg(arg: KeyValueArg) -> str:
if not arg.value:
return arg.value
raise ParseError(
f'Invalid item {arg.orig!r} (to specify an empty header use `Header;`)'
)
def process_query_param_arg(arg: KeyValueArg) -> str:
return arg.value
def process_file_upload_arg(arg: KeyValueArg) -> Tuple[str, IO, str]:
parts = arg.value.split(SEPARATOR_FILE_UPLOAD_TYPE)
filename = parts[0]
mime_type = parts[1] if len(parts) > 1 else None
try:
f = open(os.path.expanduser(filename), 'rb')
except OSError as e:
raise ParseError(f'{arg.orig!r}: {e}')
return (
os.path.basename(filename),
f,
mime_type or get_content_type(filename),
)
def process_data_item_arg(arg: KeyValueArg) -> str:
return arg.value
def process_data_embed_file_contents_arg(arg: KeyValueArg) -> str:
return load_text_file(arg)
def process_data_embed_raw_json_file_arg(arg: KeyValueArg) -> JSONType:
contents = load_text_file(arg)
value = load_json(arg, contents)
return value
def process_data_raw_json_embed_arg(arg: KeyValueArg) -> JSONType:
value = load_json(arg, arg.value)
return value
def load_text_file(item: KeyValueArg) -> str:
path = item.value
try:
with open(os.path.expanduser(path), 'rb') as f:
return f.read().decode()
except OSError as e:
raise ParseError(f'{item.orig!r}: {e}')
except UnicodeDecodeError:
raise ParseError(
f'{item.orig!r}: cannot embed the content of {item.value!r},'
' not a UTF-8 or ASCII-encoded text file'
)
def load_json(arg: KeyValueArg, contents: str) -> JSONType:
try:
return load_json_preserve_order_and_dupe_keys(contents)
except ValueError as e:
raise ParseError(f'{arg.orig!r}: {e}')

319
httpie/client.py Normal file
View File

@ -0,0 +1,319 @@
import argparse
import http.client
import json
import sys
from contextlib import contextmanager
from pathlib import Path
from typing import Callable, Iterable, Union
from urllib.parse import urlparse, urlunparse
import requests
# noinspection PyPackageRequirements
import urllib3
from . import __version__
from .cli.dicts import RequestHeadersDict
from .encoding import UTF8
from .plugins.registry import plugin_manager
from .sessions import get_httpie_session
from .ssl import AVAILABLE_SSL_VERSION_ARG_MAPPING, HTTPieHTTPSAdapter
from .uploads import (
compress_request, prepare_request_body,
get_multipart_data_and_content_type,
)
from .utils import get_expired_cookies, repr_dict
urllib3.disable_warnings()
FORM_CONTENT_TYPE = f'application/x-www-form-urlencoded; charset={UTF8}'
JSON_CONTENT_TYPE = 'application/json'
JSON_ACCEPT = f'{JSON_CONTENT_TYPE}, */*;q=0.5'
DEFAULT_UA = f'HTTPie/{__version__}'
def collect_messages(
args: argparse.Namespace,
config_dir: Path,
request_body_read_callback: Callable[[bytes], None] = None,
) -> Iterable[Union[requests.PreparedRequest, requests.Response]]:
httpie_session = None
httpie_session_headers = None
if args.session or args.session_read_only:
httpie_session = get_httpie_session(
config_dir=config_dir,
session_name=args.session or args.session_read_only,
host=args.headers.get('Host'),
url=args.url,
)
httpie_session_headers = httpie_session.headers
request_kwargs = make_request_kwargs(
args=args,
base_headers=httpie_session_headers,
request_body_read_callback=request_body_read_callback
)
send_kwargs = make_send_kwargs(args)
send_kwargs_mergeable_from_env = make_send_kwargs_mergeable_from_env(args)
requests_session = build_requests_session(
ssl_version=args.ssl_version,
ciphers=args.ciphers,
verify=bool(send_kwargs_mergeable_from_env['verify'])
)
if httpie_session:
httpie_session.update_headers(request_kwargs['headers'])
requests_session.cookies = httpie_session.cookies
if args.auth_plugin:
# Save auth from CLI to HTTPie session.
httpie_session.auth = {
'type': args.auth_plugin.auth_type,
'raw_auth': args.auth_plugin.raw_auth,
}
elif httpie_session.auth:
# Apply auth from HTTPie session
request_kwargs['auth'] = httpie_session.auth
if args.debug:
# TODO: reflect the split between request and send kwargs.
dump_request(request_kwargs)
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_request(
request=prepared_request,
always=args.compress > 1,
)
response_count = 0
expired_cookies = []
while prepared_request:
yield prepared_request
if not args.offline:
send_kwargs_merged = requests_session.merge_environment_settings(
url=prepared_request.url,
**send_kwargs_mergeable_from_env,
)
with max_headers(args.max_headers):
response = requests_session.send(
request=prepared_request,
**send_kwargs_merged,
**send_kwargs,
)
expired_cookies += get_expired_cookies(
response.headers.get('Set-Cookie', '')
)
response_count += 1
if response.next:
if args.max_redirects and response_count == args.max_redirects:
raise requests.TooManyRedirects
if args.follow:
prepared_request = response.next
if args.all:
yield response
continue
yield response
break
if httpie_session:
if httpie_session.is_new() or not args.session_read_only:
httpie_session.cookies = requests_session.cookies
httpie_session.remove_cookies(
# TODO: take path & domain into account?
cookie['name'] for cookie in expired_cookies
)
httpie_session.save()
# noinspection PyProtectedMember
@contextmanager
def max_headers(limit):
# <https://github.com/httpie/httpie/issues/802>
# noinspection PyUnresolvedReferences
orig = http.client._MAXHEADERS
http.client._MAXHEADERS = limit or float('Inf')
try:
yield
finally:
http.client._MAXHEADERS = orig
def build_requests_session(
verify: bool,
ssl_version: str = None,
ciphers: str = None,
) -> requests.Session:
requests_session = requests.Session()
# Install our adapter.
https_adapter = HTTPieHTTPSAdapter(
ciphers=ciphers,
verify=verify,
ssl_version=(
AVAILABLE_SSL_VERSION_ARG_MAPPING[ssl_version]
if ssl_version else None
),
)
requests_session.mount('https://', https_adapter)
# Install adapters from plugins.
for plugin_cls in plugin_manager.get_transport_plugins():
transport_plugin = plugin_cls()
requests_session.mount(
prefix=transport_plugin.prefix,
adapter=transport_plugin.get_adapter(),
)
return requests_session
def dump_request(kwargs: dict):
sys.stderr.write(
f'\n>>> requests.request(**{repr_dict(kwargs)})\n\n')
def finalize_headers(headers: RequestHeadersDict) -> RequestHeadersDict:
final_headers = RequestHeadersDict()
for name, value in headers.items():
if value is not None:
# “leading or trailing LWS MAY be removed without
# changing the semantics of the field value”
# <https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html>
# Also, requests raises `InvalidHeader` for leading spaces.
value = value.strip()
if isinstance(value, str):
# See <https://github.com/httpie/httpie/issues/212>
value = value.encode()
final_headers[name] = value
return final_headers
def make_default_headers(args: argparse.Namespace) -> RequestHeadersDict:
default_headers = RequestHeadersDict({
'User-Agent': DEFAULT_UA
})
auto_json = args.data and not args.form
if args.json or auto_json:
default_headers['Accept'] = JSON_ACCEPT
if args.json or (auto_json and args.data):
default_headers['Content-Type'] = JSON_CONTENT_TYPE
elif args.form and not args.files:
# If sending files, `requests` will set
# the `Content-Type` for us.
default_headers['Content-Type'] = FORM_CONTENT_TYPE
return default_headers
def make_send_kwargs(args: argparse.Namespace) -> dict:
return {
'timeout': args.timeout or None,
'allow_redirects': False,
}
def make_send_kwargs_mergeable_from_env(args: argparse.Namespace) -> dict:
cert = None
if args.cert:
cert = args.cert
if args.cert_key:
cert = cert, args.cert_key
return {
'proxies': {p.key: p.value for p in args.proxy},
'stream': True,
'verify': {
'yes': True,
'true': True,
'no': False,
'false': False,
}.get(args.verify.lower(), args.verify),
'cert': cert,
}
def make_request_kwargs(
args: argparse.Namespace,
base_headers: RequestHeadersDict = None,
request_body_read_callback=lambda chunk: chunk
) -> dict:
"""
Translate our `args` into `requests.Request` keyword arguments.
"""
files = args.files
# Serialize JSON data, if needed.
data = args.data
auto_json = data and not args.form
if (args.json or auto_json) and isinstance(data, dict):
if data:
data = json.dumps(data)
else:
# We need to set data to an empty string to prevent requests
# from assigning an empty list to `response.request.data`.
data = ''
# Finalize headers.
headers = make_default_headers(args)
if base_headers:
headers.update(base_headers)
headers.update(args.headers)
if args.offline and args.chunked and 'Transfer-Encoding' not in headers:
# When online, we let requests set the header instead to be able more
# easily verify chunking is taking place.
headers['Transfer-Encoding'] = 'chunked'
headers = finalize_headers(headers)
if (args.form and files) or args.multipart:
data, headers['Content-Type'] = get_multipart_data_and_content_type(
data=args.multipart_data,
boundary=args.boundary,
content_type=args.headers.get('Content-Type'),
)
return {
'method': args.method.lower(),
'url': args.url,
'headers': headers,
'data': prepare_request_body(
body=data,
body_read_callback=request_body_read_callback,
chunked=args.chunked,
offline=args.offline,
content_length_header_value=headers.get('Content-Length'),
),
'auth': args.auth,
'params': args.params.items(),
}
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/httpie/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,
}
return urlunparse(tuple(final_dict.values()))

View File

@ -1,165 +0,0 @@
"""
CLI argument parsing logic.
"""
import os
import json
import re
from collections import namedtuple
try:
from collections import OrderedDict
except ImportError:
OrderedDict = dict
import argparse
from requests.structures import CaseInsensitiveDict
from . import __version__
SEP_COMMON = ':'
SEP_HEADERS = SEP_COMMON
SEP_DATA = '='
SEP_DATA_RAW_JSON = ':='
SEP_FILES = '@'
OUT_REQ_HEADERS = 'H'
OUT_REQ_BODY = 'B'
OUT_RESP_HEADERS = 'h'
OUT_RESP_BODY = 'b'
OUTPUT_OPTIONS = [OUT_REQ_HEADERS,
OUT_REQ_BODY,
OUT_RESP_HEADERS,
OUT_RESP_BODY]
PRETTIFY_STDOUT_TTY_ONLY = object()
DEFAULT_UA = 'HTTPie/%s' % __version__
class HTTPieArgumentParser(argparse.ArgumentParser):
def parse_args(self, args=None, namespace=None):
args = super(HTTPieArgumentParser, self).parse_args(args, namespace)
self._validate_output_options(args)
self._validate_auth_options(args)
self._parse_items(args)
return args
def _parse_items(self, args):
args.headers = CaseInsensitiveDict()
args.headers['User-Agent'] = DEFAULT_UA
args.data = OrderedDict()
args.files = OrderedDict()
try:
parse_items(items=args.items, headers=args.headers,
data=args.data, files=args.files)
except ParseError as e:
if args.traceback:
raise
self.error(e.message)
if args.files and not args.form:
# We could just switch to --form automatically here,
# but I think it's better to make it explicit.
self.error(
' You need to set the --form / -f flag to'
' to issue a multipart request. File fields: %s'
% ','.join(args.files.keys()))
def _validate_output_options(self, args):
unknown_output_options = set(args.output_options) - set(OUTPUT_OPTIONS)
if unknown_output_options:
self.error('Unknown output options: %s' % ','.join(unknown_output_options))
def _validate_auth_options(self, args):
if args.auth_type and not args.auth:
self.error('--auth-type can only be used with --auth')
class ParseError(Exception):
pass
KeyValue = namedtuple('KeyValue', ['key', 'value', 'sep', 'orig'])
class KeyValueType(object):
"""A type used with `argparse`."""
def __init__(self, *separators):
self.separators = separators
self.escapes = ['\\\\' + sep for sep in separators]
def __call__(self, string):
found = {}
found_escapes = []
for esc in self.escapes:
found_escapes += [m.span() for m in re.finditer(esc, string)]
for sep in self.separators:
matches = re.finditer(sep, string)
for match in matches:
start, end = match.span()
inside_escape = False
for estart, eend in found_escapes:
if start >= estart and end <= eend:
inside_escape = True
break
if not inside_escape:
found[start] = sep
if not found:
raise argparse.ArgumentTypeError(
'"%s" is not a valid value' % string)
# split the string at the earliest non-escaped separator.
seploc = min(found.keys())
sep = found[seploc]
key = string[:seploc]
value = string[seploc + len(sep):]
# remove escape chars
for sepstr in self.separators:
key = key.replace('\\' + sepstr, sepstr)
value = value.replace('\\' + sepstr, sepstr)
return KeyValue(key=key, value=value, sep=sep, orig=string)
def parse_items(items, data=None, headers=None, files=None):
"""Parse `KeyValueType` `items` into `data`, `headers` and `files`."""
if headers is None:
headers = {}
if data is None:
data = {}
if files is None:
files = {}
for item in items:
value = item.value
key = item.key
if item.sep == SEP_HEADERS:
target = headers
elif item.sep == SEP_FILES:
try:
value = open(os.path.expanduser(item.value), 'r')
except IOError as e:
raise ParseError(
'Invalid argument %r. %s' % (item.orig, e))
if not key:
key = os.path.basename(value.name)
target = files
elif item.sep in [SEP_DATA, SEP_DATA_RAW_JSON]:
if item.sep == SEP_DATA_RAW_JSON:
try:
value = json.loads(item.value)
except ValueError:
raise ParseError('%s is not valid JSON' % item.orig)
target = data
else:
raise ParseError('%s is not valid item' % item.orig)
if key in target:
ParseError('duplicate item %s (%s)' % (item.key, item.orig))
target[key] = value
return headers, data, files

54
httpie/compat.py Normal file
View File

@ -0,0 +1,54 @@
import sys
is_windows = 'win32' in str(sys.platform).lower()
try:
from functools import cached_property
except ImportError:
# Can be removed once we drop Python <3.8 support.
# Taken from `django.utils.functional.cached_property`.
class cached_property:
"""
Decorator that converts a method with a single self argument into a
property cached on the instance.
A cached property can be made out of an existing method:
(e.g. ``url = cached_property(get_absolute_url)``).
The optional ``name`` argument is obsolete as of Python 3.6 and will be
deprecated in Django 4.0 (#30127).
"""
name = None
@staticmethod
def func(instance):
raise TypeError(
'Cannot use cached_property instance without calling '
'__set_name__() on it.'
)
def __init__(self, func, name=None):
self.real_func = func
self.__doc__ = getattr(func, '__doc__')
def __set_name__(self, owner, name):
if self.name is None:
self.name = name
self.func = self.real_func
elif name != self.name:
raise TypeError(
"Cannot assign the same cached_property to two different names "
"(%r and %r)." % (self.name, name)
)
def __get__(self, instance, cls=None):
"""
Call the function and put the return value in instance.__dict__ so that
subsequent attribute access on the instance returns the cached value
instead of calling cached_property.__get__().
"""
if instance is None:
return self
res = instance.__dict__[self.name] = self.func(instance)
return res

130
httpie/config.py Normal file
View File

@ -0,0 +1,130 @@
import json
import os
from pathlib import Path
from typing import Union
from . import __version__
from .compat import is_windows
from .encoding import UTF8
ENV_XDG_CONFIG_HOME = 'XDG_CONFIG_HOME'
ENV_HTTPIE_CONFIG_DIR = 'HTTPIE_CONFIG_DIR'
DEFAULT_CONFIG_DIRNAME = 'httpie'
DEFAULT_RELATIVE_XDG_CONFIG_HOME = Path('.config')
DEFAULT_RELATIVE_LEGACY_CONFIG_DIR = Path('.httpie')
DEFAULT_WINDOWS_CONFIG_DIR = Path(
os.path.expandvars('%APPDATA%')) / DEFAULT_CONFIG_DIRNAME
def get_default_config_dir() -> Path:
"""
Return the path to the httpie configuration directory.
This directory isn't guaranteed to exist, and nor are any of its
ancestors (only the legacy ~/.httpie, if returned, is guaranteed to exist).
XDG Base Directory Specification support:
<https://wiki.archlinux.org/index.php/XDG_Base_Directory>
$XDG_CONFIG_HOME is supported; $XDG_CONFIG_DIRS is not
"""
# 1. explicitly set through env
env_config_dir = os.environ.get(ENV_HTTPIE_CONFIG_DIR)
if env_config_dir:
return Path(env_config_dir)
# 2. Windows
if is_windows:
return DEFAULT_WINDOWS_CONFIG_DIR
home_dir = Path.home()
# 3. legacy ~/.httpie
legacy_config_dir = home_dir / DEFAULT_RELATIVE_LEGACY_CONFIG_DIR
if legacy_config_dir.exists():
return legacy_config_dir
# 4. XDG
xdg_config_home_dir = os.environ.get(
ENV_XDG_CONFIG_HOME, # 4.1. explicit
home_dir / DEFAULT_RELATIVE_XDG_CONFIG_HOME # 4.2. default
)
return Path(xdg_config_home_dir) / DEFAULT_CONFIG_DIRNAME
DEFAULT_CONFIG_DIR = get_default_config_dir()
class ConfigFileError(Exception):
pass
class BaseConfigDict(dict):
name = None
helpurl = None
about = None
def __init__(self, path: Path):
super().__init__()
self.path = path
def ensure_directory(self):
self.path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
def is_new(self) -> bool:
return not self.path.exists()
def load(self):
config_type = type(self).__name__.lower()
try:
with self.path.open(encoding=UTF8) as f:
try:
data = json.load(f)
except ValueError as e:
raise ConfigFileError(
f'invalid {config_type} file: {e} [{self.path}]'
)
self.update(data)
except FileNotFoundError:
pass
except OSError as e:
raise ConfigFileError(f'cannot read {config_type} file: {e}')
def save(self):
self['__meta__'] = {
'httpie': __version__
}
if self.helpurl:
self['__meta__']['help'] = self.helpurl
if self.about:
self['__meta__']['about'] = self.about
self.ensure_directory()
json_string = json.dumps(
obj=self,
indent=4,
sort_keys=True,
ensure_ascii=True,
)
self.path.write_text(json_string + '\n', encoding=UTF8)
class Config(BaseConfigDict):
FILENAME = 'config.json'
DEFAULTS = {
'default_options': []
}
def __init__(self, directory: Union[str, Path] = DEFAULT_CONFIG_DIR):
self.directory = Path(directory)
super().__init__(path=self.directory / self.FILENAME)
self.update(self.DEFAULTS)
@property
def default_options(self) -> list:
return self['default_options']

125
httpie/context.py Normal file
View File

@ -0,0 +1,125 @@
import sys
import os
from pathlib import Path
from typing import IO, Optional
try:
import curses
except ImportError:
curses = None # Compiled w/o curses
from .compat import is_windows
from .config import DEFAULT_CONFIG_DIR, Config, ConfigFileError
from .encoding import UTF8
from .utils import repr_dict
class Environment:
"""
Information about the execution context
(standard streams, config directory, etc).
By default, it represents the actual environment.
All of the attributes can be overwritten though, which
is used by the test suite to simulate various scenarios.
"""
is_windows: bool = is_windows
config_dir: Path = DEFAULT_CONFIG_DIR
stdin: Optional[IO] = sys.stdin # `None` when closed fd (#791)
stdin_isatty: bool = stdin.isatty() if stdin else False
stdin_encoding: str = None
stdout: IO = sys.stdout
stdout_isatty: bool = stdout.isatty()
stdout_encoding: str = None
stderr: IO = sys.stderr
stderr_isatty: bool = stderr.isatty()
colors = 256
program_name: str = 'http'
if not is_windows:
if curses:
try:
curses.setupterm()
colors = curses.tigetnum('colors')
except curses.error:
pass
else:
# noinspection PyUnresolvedReferences
import colorama.initialise
stdout = colorama.initialise.wrap_stream(
stdout, convert=None, strip=None,
autoreset=True, wrap=True
)
stderr = colorama.initialise.wrap_stream(
stderr, convert=None, strip=None,
autoreset=True, wrap=True
)
del colorama
def __init__(self, devnull=None, **kwargs):
"""
Use keyword arguments to overwrite
any of the class attributes for this instance.
"""
assert all(hasattr(type(self), attr) for attr in kwargs.keys())
self.__dict__.update(**kwargs)
# The original STDERR unaffected by --quieting.
self._orig_stderr = self.stderr
self._devnull = devnull
# Keyword arguments > stream.encoding > default UTF-8
if self.stdin and self.stdin_encoding is None:
self.stdin_encoding = getattr(
self.stdin, 'encoding', None) or UTF8
if self.stdout_encoding is None:
actual_stdout = self.stdout
if is_windows:
# noinspection PyUnresolvedReferences
from colorama import AnsiToWin32
if isinstance(self.stdout, AnsiToWin32):
# noinspection PyUnresolvedReferences
actual_stdout = self.stdout.wrapped
self.stdout_encoding = getattr(
actual_stdout, 'encoding', None) or UTF8
def __str__(self):
defaults = dict(type(self).__dict__)
actual = dict(defaults)
actual.update(self.__dict__)
actual['config'] = self.config
return repr_dict({
key: value
for key, value in actual.items()
if not key.startswith('_')
})
def __repr__(self):
return f'<{type(self).__name__} {self}>'
_config: Config = None
@property
def config(self) -> Config:
config = self._config
if not config:
self._config = config = Config(directory=self.config_dir)
if not config.is_new():
try:
config.load()
except ConfigFileError as e:
self.log_error(e, level='warning')
return config
@property
def devnull(self) -> IO:
if self._devnull is None:
self._devnull = open(os.devnull, 'w+')
return self._devnull
def log_error(self, msg, level='error'):
assert level in ['error', 'warning']
self._orig_stderr.write(f'\n{self.program_name}: {level}: {msg}\n\n')

252
httpie/core.py Normal file
View File

@ -0,0 +1,252 @@
import argparse
import os
import platform
import sys
from typing import List, Optional, Tuple, Union
import requests
from pygments import __version__ as pygments_version
from requests import __version__ as requests_version
from . import __version__ as httpie_version
from .cli.constants import OUT_REQ_BODY, OUT_REQ_HEAD, OUT_RESP_BODY, OUT_RESP_HEAD
from .client import collect_messages
from .context import Environment
from .downloads import Downloader
from .output.writer import write_message, write_stream, MESSAGE_SEPARATOR_BYTES
from .plugins.registry import plugin_manager
from .status import ExitStatus, http_status_to_exit_status
# noinspection PyDefaultArgument
def main(args: List[Union[str, bytes]] = sys.argv, env=Environment()) -> ExitStatus:
"""
The main function.
Pre-process args, handle some special types of invocations,
and run the main program with error handling.
Return exit status code.
"""
if '--prompt' in args:
from .prompt.cli import cli
return cli(sys.argv[2:])
program_name, *args = args
env.program_name = os.path.basename(program_name)
args = decode_raw_args(args, env.stdin_encoding)
plugin_manager.load_installed_plugins()
from .cli.definition import parser
if env.config.default_options:
args = env.config.default_options + args
include_debug_info = '--debug' in args
include_traceback = include_debug_info or '--traceback' in args
if include_debug_info:
print_debug_info(env)
if args == ['--debug']:
return ExitStatus.SUCCESS
exit_status = ExitStatus.SUCCESS
try:
parsed_args = parser.parse_args(
args=args,
env=env,
)
except KeyboardInterrupt:
env.stderr.write('\n')
if include_traceback:
raise
exit_status = ExitStatus.ERROR_CTRL_C
except SystemExit as e:
if e.code != ExitStatus.SUCCESS:
env.stderr.write('\n')
if include_traceback:
raise
exit_status = ExitStatus.ERROR
else:
try:
exit_status = program(
args=parsed_args,
env=env,
)
except KeyboardInterrupt:
env.stderr.write('\n')
if include_traceback:
raise
exit_status = ExitStatus.ERROR_CTRL_C
except SystemExit as e:
if e.code != ExitStatus.SUCCESS:
env.stderr.write('\n')
if include_traceback:
raise
exit_status = ExitStatus.ERROR
except requests.Timeout:
exit_status = ExitStatus.ERROR_TIMEOUT
env.log_error(f'Request timed out ({parsed_args.timeout}s).')
except requests.TooManyRedirects:
exit_status = ExitStatus.ERROR_TOO_MANY_REDIRECTS
env.log_error(
f'Too many redirects'
f' (--max-redirects={parsed_args.max_redirects}).'
)
except Exception as e:
# TODO: Further distinction between expected and unexpected errors.
msg = str(e)
if hasattr(e, 'request'):
request = e.request
if hasattr(request, 'url'):
msg = (
f'{msg} while doing a {request.method}'
f' request to URL: {request.url}'
)
env.log_error(f'{type(e).__name__}: {msg}')
if include_traceback:
raise
exit_status = ExitStatus.ERROR
return exit_status
def get_output_options(
args: argparse.Namespace,
message: Union[requests.PreparedRequest, requests.Response]
) -> Tuple[bool, bool]:
return {
requests.PreparedRequest: (
OUT_REQ_HEAD in args.output_options,
OUT_REQ_BODY in args.output_options,
),
requests.Response: (
OUT_RESP_HEAD in args.output_options,
OUT_RESP_BODY in args.output_options,
),
}[type(message)]
def program(args: argparse.Namespace, env: Environment) -> ExitStatus:
"""
The main program without error handling.
"""
# TODO: Refactor and drastically simplify, especially so that the separator logic is elsewhere.
exit_status = ExitStatus.SUCCESS
downloader = None
initial_request: Optional[requests.PreparedRequest] = None
final_response: Optional[requests.Response] = None
def separate():
getattr(env.stdout, 'buffer', env.stdout).write(MESSAGE_SEPARATOR_BYTES)
def request_body_read_callback(chunk: bytes):
should_pipe_to_stdout = bool(
# Request body output desired
OUT_REQ_BODY in args.output_options
# & not `.read()` already pre-request (e.g., for compression)
and initial_request
# & non-EOF chunk
and chunk
)
if should_pipe_to_stdout:
msg = requests.PreparedRequest()
msg.is_body_upload_chunk = True
msg.body = chunk
msg.headers = initial_request.headers
write_message(requests_message=msg, env=env, args=args, with_body=True, with_headers=False)
try:
if args.download:
args.follow = True # --download implies --follow.
downloader = Downloader(output_file=args.output_file, progress_file=env.stderr, resume=args.download_resume)
downloader.pre_request(args.headers)
messages = collect_messages(args=args, config_dir=env.config.directory,
request_body_read_callback=request_body_read_callback)
force_separator = False
prev_with_body = False
# Process messages as theyre generated
for message in messages:
is_request = isinstance(message, requests.PreparedRequest)
with_headers, with_body = get_output_options(args=args, message=message)
do_write_body = with_body
if prev_with_body and (with_headers or with_body) and (force_separator or not env.stdout_isatty):
# Separate after a previous message with body, if needed. See test_tokens.py.
separate()
force_separator = False
if is_request:
if not initial_request:
initial_request = message
if with_body:
is_streamed_upload = not isinstance(message.body, (str, bytes))
do_write_body = not is_streamed_upload
force_separator = is_streamed_upload and env.stdout_isatty
else:
final_response = message
if args.check_status or downloader:
exit_status = http_status_to_exit_status(http_status=message.status_code, follow=args.follow)
if exit_status != ExitStatus.SUCCESS and (not env.stdout_isatty or args.quiet):
env.log_error(f'HTTP {message.raw.status} {message.raw.reason}', level='warning')
write_message(requests_message=message, env=env, args=args, with_headers=with_headers,
with_body=do_write_body)
prev_with_body = with_body
# Cleanup
if force_separator:
separate()
if downloader and exit_status == ExitStatus.SUCCESS:
# Last response body download.
download_stream, download_to = downloader.start(
initial_url=initial_request.url,
final_response=final_response,
)
write_stream(stream=download_stream, outfile=download_to, flush=False)
downloader.finish()
if downloader.interrupted:
exit_status = ExitStatus.ERROR
env.log_error(
f'Incomplete download: size={downloader.status.total_size};'
f' downloaded={downloader.status.downloaded}'
)
return exit_status
finally:
if downloader and not downloader.finished:
downloader.failed()
if args.output_file and args.output_file_specified:
args.output_file.close()
def print_debug_info(env: Environment):
env.stderr.writelines([
f'HTTPie {httpie_version}\n',
f'Requests {requests_version}\n',
f'Pygments {pygments_version}\n',
f'Python {sys.version}\n{sys.executable}\n',
f'{platform.system()} {platform.release()}',
])
env.stderr.write('\n\n')
env.stderr.write(repr(env))
env.stderr.write('\n\n')
env.stderr.write(repr(plugin_manager))
env.stderr.write('\n')
def decode_raw_args(
args: List[Union[str, bytes]],
stdin_encoding: str
) -> List[str]:
"""
Convert all bytes args to str
by decoding them using stdin encoding.
"""
return [
arg.decode(stdin_encoding)
if type(arg) is bytes else arg
for arg in args
]

456
httpie/downloads.py Normal file
View File

@ -0,0 +1,456 @@
"""
Download mode implementation.
"""
import mimetypes
import os
import re
import sys
import threading
from mailbox import Message
from time import sleep, monotonic
from typing import IO, Optional, Tuple
from urllib.parse import urlsplit
import requests
from .models import HTTPResponse
from .output.streams import RawStream
from .utils import humanize_bytes
PARTIAL_CONTENT = 206
CLEAR_LINE = '\r\033[K'
PROGRESS = (
'{percentage: 6.2f} %'
' {downloaded: >10}'
' {speed: >10}/s'
' {eta: >8} ETA'
)
PROGRESS_NO_CONTENT_LENGTH = '{downloaded: >10} {speed: >10}/s'
SUMMARY = 'Done. {downloaded} in {time:0.5f}s ({speed}/s)\n'
SPINNER = '|/-\\'
class ContentRangeError(ValueError):
pass
def parse_content_range(content_range: str, resumed_from: int) -> int:
"""
Parse and validate Content-Range header.
<https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html>
:param content_range: the value of a Content-Range response header
eg. "bytes 21010-47021/47022"
:param resumed_from: first byte pos. from the Range request header
:return: total size of the response body when fully downloaded.
"""
if content_range is None:
raise ContentRangeError('Missing Content-Range')
pattern = (
r'^bytes (?P<first_byte_pos>\d+)-(?P<last_byte_pos>\d+)'
r'/(\*|(?P<instance_length>\d+))$'
)
match = re.match(pattern, content_range)
if not match:
raise ContentRangeError(
f'Invalid Content-Range format {content_range!r}')
content_range_dict = match.groupdict()
first_byte_pos = int(content_range_dict['first_byte_pos'])
last_byte_pos = int(content_range_dict['last_byte_pos'])
instance_length = (
int(content_range_dict['instance_length'])
if content_range_dict['instance_length']
else None
)
# "A byte-content-range-spec with a byte-range-resp-spec whose
# last- byte-pos value is less than its first-byte-pos value,
# or whose instance-length value is less than or equal to its
# last-byte-pos value, is invalid. The recipient of an invalid
# byte-content-range- spec MUST ignore it and any content
# transferred along with it."
if (first_byte_pos > last_byte_pos
or (instance_length is not None
and instance_length <= last_byte_pos)):
raise ContentRangeError(
f'Invalid Content-Range returned: {content_range!r}')
if (first_byte_pos != resumed_from
or (instance_length is not None
and last_byte_pos + 1 != instance_length)):
# Not what we asked for.
raise ContentRangeError(
f'Unexpected Content-Range returned ({content_range!r})'
f' for the requested Range ("bytes={resumed_from}-")'
)
return last_byte_pos + 1
def filename_from_content_disposition(
content_disposition: str
) -> Optional[str]:
"""
Extract and validate filename from a Content-Disposition header.
:param content_disposition: Content-Disposition value
:return: the filename if present and valid, otherwise `None`
"""
# attachment; filename=jakubroztocil-httpie-0.4.1-20-g40bd8f6.tar.gz
msg = Message(f'Content-Disposition: {content_disposition}')
filename = msg.get_filename()
if filename:
# Basic sanitation.
filename = os.path.basename(filename).lstrip('.').strip()
if filename:
return filename
def filename_from_url(url: str, content_type: Optional[str]) -> str:
fn = urlsplit(url).path.rstrip('/')
fn = os.path.basename(fn) if fn else 'index'
if '.' not in fn and content_type:
content_type = content_type.split(';')[0]
if content_type == 'text/plain':
# mimetypes returns '.ksh'
ext = '.txt'
else:
ext = mimetypes.guess_extension(content_type)
if ext == '.htm':
ext = '.html'
if ext:
fn += ext
return fn
def trim_filename(filename: str, max_len: int) -> str:
if len(filename) > max_len:
trim_by = len(filename) - max_len
name, ext = os.path.splitext(filename)
if trim_by >= len(name):
filename = filename[:-trim_by]
else:
filename = name[:-trim_by] + ext
return filename
def get_filename_max_length(directory: str) -> int:
max_len = 255
if hasattr(os, 'pathconf') and 'PC_NAME_MAX' in os.pathconf_names:
max_len = os.pathconf(directory, 'PC_NAME_MAX')
return max_len
def trim_filename_if_needed(filename: str, directory='.', extra=0) -> str:
max_len = get_filename_max_length(directory) - extra
if len(filename) > max_len:
filename = trim_filename(filename, max_len)
return filename
def get_unique_filename(filename: str, exists=os.path.exists) -> str:
attempt = 0
while True:
suffix = f'-{attempt}' if attempt > 0 else ''
try_filename = trim_filename_if_needed(filename, extra=len(suffix))
try_filename += suffix
if not exists(try_filename):
return try_filename
attempt += 1
class Downloader:
def __init__(
self,
output_file: IO = None,
resume: bool = False,
progress_file: IO = sys.stderr
):
"""
:param resume: Should the download resume if partial download
already exists.
:param output_file: The file to store response body in. If not
provided, it will be guessed from the response.
:param progress_file: Where to report download progress.
"""
self.finished = False
self.status = DownloadStatus()
self._output_file = output_file
self._resume = resume
self._resumed_from = 0
self._progress_reporter = ProgressReporterThread(
status=self.status,
output=progress_file
)
def pre_request(self, request_headers: dict):
"""Called just before the HTTP request is sent.
Might alter `request_headers`.
"""
# Ask the server not to encode the content so that we can resume, etc.
request_headers['Accept-Encoding'] = 'identity'
if self._resume:
bytes_have = os.path.getsize(self._output_file.name)
if bytes_have:
# Set ``Range`` header to resume the download
# TODO: Use "If-Range: mtime" to make sure it's fresh?
request_headers['Range'] = f'bytes={bytes_have}-'
self._resumed_from = bytes_have
def start(
self,
initial_url: str,
final_response: requests.Response
) -> Tuple[RawStream, IO]:
"""
Initiate and return a stream for `response` body with progress
callback attached. Can be called only once.
:param initial_url: The original requested URL
:param final_response: Initiated response object with headers already fetched
:return: RawStream, output_file
"""
assert not self.status.time_started
# FIXME: some servers still might sent Content-Encoding: gzip
# <https://github.com/httpie/httpie/issues/423>
try:
total_size = int(final_response.headers['Content-Length'])
except (KeyError, ValueError, TypeError):
total_size = None
if not self._output_file:
self._output_file = self._get_output_file_from_response(
initial_url=initial_url,
final_response=final_response,
)
else:
# `--output, -o` provided
if self._resume and final_response.status_code == PARTIAL_CONTENT:
total_size = parse_content_range(
final_response.headers.get('Content-Range'),
self._resumed_from
)
else:
self._resumed_from = 0
try:
self._output_file.seek(0)
self._output_file.truncate()
except OSError:
pass # stdout
self.status.started(
resumed_from=self._resumed_from,
total_size=total_size
)
stream = RawStream(
msg=HTTPResponse(final_response),
with_headers=False,
with_body=True,
on_body_chunk_downloaded=self.chunk_downloaded,
chunk_size=1024 * 8
)
self._progress_reporter.output.write(
f'Downloading {humanize_bytes(total_size) + " " if total_size is not None else ""}'
f'to "{self._output_file.name}"\n'
)
self._progress_reporter.start()
return stream, self._output_file
def finish(self):
assert not self.finished
self.finished = True
self.status.finished()
def failed(self):
self._progress_reporter.stop()
@property
def interrupted(self) -> bool:
return (
self.finished
and self.status.total_size
and self.status.total_size != self.status.downloaded
)
def chunk_downloaded(self, chunk: bytes):
"""
A download progress callback.
:param chunk: A chunk of response body data that has just
been downloaded and written to the output.
"""
self.status.chunk_downloaded(len(chunk))
@staticmethod
def _get_output_file_from_response(
initial_url: str,
final_response: requests.Response,
) -> IO:
# Output file not specified. Pick a name that doesn't exist yet.
filename = None
if 'Content-Disposition' in final_response.headers:
filename = filename_from_content_disposition(
final_response.headers['Content-Disposition'])
if not filename:
filename = filename_from_url(
url=initial_url,
content_type=final_response.headers.get('Content-Type'),
)
unique_filename = get_unique_filename(filename)
return open(unique_filename, mode='a+b')
class DownloadStatus:
"""Holds details about the download status."""
def __init__(self):
self.downloaded = 0
self.total_size = None
self.resumed_from = 0
self.time_started = None
self.time_finished = None
def started(self, resumed_from=0, total_size=None):
assert self.time_started is None
self.total_size = total_size
self.downloaded = self.resumed_from = resumed_from
self.time_started = monotonic()
def chunk_downloaded(self, size):
assert self.time_finished is None
self.downloaded += size
@property
def has_finished(self):
return self.time_finished is not None
def finished(self):
assert self.time_started is not None
assert self.time_finished is None
self.time_finished = monotonic()
class ProgressReporterThread(threading.Thread):
"""
Reports download progress based on its status.
Uses threading to periodically update the status (speed, ETA, etc.).
"""
def __init__(
self,
status: DownloadStatus,
output: IO,
tick=.1,
update_interval=1
):
super().__init__()
self.status = status
self.output = output
self._tick = tick
self._update_interval = update_interval
self._spinner_pos = 0
self._status_line = ''
self._prev_bytes = 0
self._prev_time = monotonic()
self._should_stop = threading.Event()
def stop(self):
"""Stop reporting on next tick."""
self._should_stop.set()
def run(self):
while not self._should_stop.is_set():
if self.status.has_finished:
self.sum_up()
break
self.report_speed()
sleep(self._tick)
def report_speed(self):
now = monotonic()
if now - self._prev_time >= self._update_interval:
downloaded = self.status.downloaded
speed = ((downloaded - self._prev_bytes)
/ (now - self._prev_time))
if not self.status.total_size:
self._status_line = PROGRESS_NO_CONTENT_LENGTH.format(
downloaded=humanize_bytes(downloaded),
speed=humanize_bytes(speed),
)
else:
percentage = (downloaded / self.status.total_size * 100
if self.status.total_size
else 0)
if not speed:
eta = '-:--:--'
else:
s = int((self.status.total_size - downloaded) / speed)
h, s = divmod(s, 60 * 60)
m, s = divmod(s, 60)
eta = f'{h}:{m:0>2}:{s:0>2}'
self._status_line = PROGRESS.format(
percentage=percentage,
downloaded=humanize_bytes(downloaded),
speed=humanize_bytes(speed),
eta=eta,
)
self._prev_time = now
self._prev_bytes = downloaded
self.output.write(
f'{CLEAR_LINE} {SPINNER[self._spinner_pos]} {self._status_line}'
)
self.output.flush()
self._spinner_pos = (self._spinner_pos + 1) % len(SPINNER)
def sum_up(self):
actually_downloaded = (
self.status.downloaded - self.status.resumed_from)
time_taken = self.status.time_finished - self.status.time_started
speed = actually_downloaded / time_taken if time_taken else actually_downloaded
self.output.write(CLEAR_LINE)
self.output.write(SUMMARY.format(
downloaded=humanize_bytes(actually_downloaded),
total=(self.status.total_size
and humanize_bytes(self.status.total_size)),
speed=humanize_bytes(speed),
time=time_taken,
))
self.output.flush()

50
httpie/encoding.py Normal file
View File

@ -0,0 +1,50 @@
from typing import Union
from charset_normalizer import from_bytes
from charset_normalizer.constant import TOO_SMALL_SEQUENCE
UTF8 = 'utf-8'
ContentBytes = Union[bytearray, bytes]
def detect_encoding(content: ContentBytes) -> str:
"""
We default to UTF-8 if text too short, because the detection
can return a random encoding leading to confusing results
given the `charset_normalizer` version (< 2.0.5).
>>> too_short = ']"foo"'
>>> detected = from_bytes(too_short.encode()).best().encoding
>>> detected
'ascii'
>>> too_short.encode().decode(detected)
']"foo"'
"""
encoding = UTF8
if len(content) > TOO_SMALL_SEQUENCE:
match = from_bytes(bytes(content)).best()
if match:
encoding = match.encoding
return encoding
def smart_decode(content: ContentBytes, encoding: str) -> str:
"""Decode `content` using the given `encoding`.
If no `encoding` is provided, the best effort is to guess it from `content`.
Unicode errors are replaced.
"""
if not encoding:
encoding = detect_encoding(content)
return content.decode(encoding, 'replace')
def smart_encode(content: str, encoding: str) -> bytes:
"""Encode `content` using the given `encoding`.
Unicode errors are replaced.
"""
return content.encode(encoding, 'replace')

View File

@ -1,66 +0,0 @@
from requests.compat import urlparse
class HTTPMessage(object):
"""Model representing an HTTP message."""
def __init__(self, line, headers, body, content_type=None):
# {Request,Status}-Line
self.line = line
self.headers = headers
self.body = body
self.content_type = content_type
def from_request(request):
"""Make an `HTTPMessage` from `requests.models.Request`."""
url = urlparse(request.url)
request_headers = dict(request.headers)
if 'Host' not in request_headers:
request_headers['Host'] = url.netloc
return HTTPMessage(
line='{method} {path} HTTP/1.1'.format(
method=request.method,
path=url.path or '/'),
headers='\n'.join(str('%s: %s') % (name, value)
for name, value
in request_headers.items()),
body=request._enc_data,
content_type=request_headers.get('Content-Type')
)
def from_response(response):
"""Make an `HTTPMessage` from `requests.models.Response`."""
encoding = response.encoding or 'ISO-8859-1'
original = response.raw._original_response
response_headers = response.headers
return HTTPMessage(
line='HTTP/{version} {status} {reason}'.format(
version='.'.join(str(original.version)),
status=original.status, reason=original.reason,),
headers=str(original.msg),
body=response.content.decode(encoding) if response.content else '',
content_type=response_headers.get('Content-Type'))
def format(message, prettifier=None,
with_headers=True, with_body=True):
"""Return a `unicode` representation of `message`. """
bits = []
if with_headers:
if prettifier:
bits.append(prettifier.headers(message.line))
bits.append(prettifier.headers(message.headers))
else:
bits.append(message.line)
bits.append(message.headers)
if with_body and message.body:
bits.append('\n')
if with_body and message.body:
if prettifier and message.content_type:
bits.append(prettifier.body(message.body, message.content_type))
else:
bits.append(message.body)
bits.append('\n')
return '\n'.join(bit.strip() for bit in bits)

118
httpie/models.py Normal file
View File

@ -0,0 +1,118 @@
from typing import Iterable
from urllib.parse import urlsplit
from .utils import split_cookies, parse_content_type_header
from .compat import cached_property
class HTTPMessage:
"""Abstract class for HTTP messages."""
def __init__(self, orig):
self._orig = orig
def iter_body(self, chunk_size: int) -> Iterable[bytes]:
"""Return an iterator over the body."""
raise NotImplementedError
def iter_lines(self, chunk_size: int) -> Iterable[bytes]:
"""Return an iterator over the body yielding (`line`, `line_feed`)."""
raise NotImplementedError
@property
def headers(self) -> str:
"""Return a `str` with the message's headers."""
raise NotImplementedError
@cached_property
def encoding(self) -> str:
ct, params = parse_content_type_header(self.content_type)
return params.get('charset', '')
@property
def content_type(self) -> str:
"""Return the message content type."""
ct = self._orig.headers.get('Content-Type', '')
if not isinstance(ct, str):
ct = ct.decode()
return ct
class HTTPResponse(HTTPMessage):
"""A :class:`requests.models.Response` wrapper."""
def iter_body(self, chunk_size=1):
return self._orig.iter_content(chunk_size=chunk_size)
def iter_lines(self, chunk_size):
return ((line, b'\n') for line in self._orig.iter_lines(chunk_size))
# noinspection PyProtectedMember
@property
def headers(self):
try:
raw_version = self._orig.raw._original_response.version
except AttributeError:
# Assume HTTP/1.1
raw_version = 11
version = {
9: '0.9',
10: '1.0',
11: '1.1',
20: '2',
}[raw_version]
original = self._orig
status_line = f'HTTP/{version} {original.status_code} {original.reason}'
headers = [status_line]
headers.extend(
': '.join(header)
for header in original.headers.items()
if header[0] != 'Set-Cookie'
)
headers.extend(
f'Set-Cookie: {cookie}'
for cookie in split_cookies(original.headers.get('Set-Cookie'))
)
return '\r\n'.join(headers)
class HTTPRequest(HTTPMessage):
"""A :class:`requests.models.Request` wrapper."""
def iter_body(self, chunk_size):
yield self.body
def iter_lines(self, chunk_size):
yield self.body, b''
@property
def headers(self):
url = urlsplit(self._orig.url)
request_line = '{method} {path}{query} HTTP/1.1'.format(
method=self._orig.method,
path=url.path or '/',
query=f'?{url.query}' if url.query else ''
)
headers = dict(self._orig.headers)
if 'Host' not in self._orig.headers:
headers['Host'] = url.netloc.split('@')[-1]
headers = [
f'{name}: {value if isinstance(value, str) else value.decode()}'
for name, value in headers.items()
]
headers.insert(0, request_line)
headers = '\r\n'.join(headers).strip()
return headers
@property
def body(self):
body = self._orig.body
if isinstance(body, str):
# Happens with JSON/form request data parsed from the command line.
body = body.encode()
return body or b''

View File

View File

View File

@ -0,0 +1,234 @@
import json
from typing import Optional, Type
import pygments.lexer
import pygments.lexers
import pygments.style
import pygments.styles
import pygments.token
from pygments.formatters.terminal import TerminalFormatter
from pygments.formatters.terminal256 import Terminal256Formatter
from pygments.lexer import Lexer
from pygments.lexers.data import JsonLexer
from pygments.lexers.special import TextLexer
from pygments.lexers.text import HttpLexer as PygmentsHttpLexer
from pygments.util import ClassNotFound
from ..lexers.json import EnhancedJsonLexer
from ...compat import is_windows
from ...context import Environment
from ...plugins import FormatterPlugin
AUTO_STYLE = 'auto' # Follows terminal ANSI color styles
DEFAULT_STYLE = AUTO_STYLE
SOLARIZED_STYLE = 'solarized' # Bundled here
if is_windows:
# Colors on Windows via colorama don't look that
# great and fruity seems to give the best result there.
DEFAULT_STYLE = 'fruity'
AVAILABLE_STYLES = set(pygments.styles.get_all_styles())
AVAILABLE_STYLES.add(SOLARIZED_STYLE)
AVAILABLE_STYLES.add(AUTO_STYLE)
class ColorFormatter(FormatterPlugin):
"""
Colorize using Pygments
This processor that applies syntax highlighting to the headers,
and also to the body if its content type is recognized.
"""
group_name = 'colors'
def __init__(
self,
env: Environment,
explicit_json=False,
color_scheme=DEFAULT_STYLE,
**kwargs
):
super().__init__(**kwargs)
if not env.colors:
self.enabled = False
return
use_auto_style = color_scheme == AUTO_STYLE
has_256_colors = env.colors == 256
if use_auto_style or not has_256_colors:
http_lexer = PygmentsHttpLexer()
formatter = TerminalFormatter()
else:
from ..lexers.http import SimplifiedHTTPLexer
http_lexer = SimplifiedHTTPLexer()
formatter = Terminal256Formatter(
style=self.get_style_class(color_scheme)
)
self.explicit_json = explicit_json # --json
self.formatter = formatter
self.http_lexer = http_lexer
def format_headers(self, headers: str) -> str:
return pygments.highlight(
code=headers,
lexer=self.http_lexer,
formatter=self.formatter,
).strip()
def format_body(self, body: str, mime: str) -> str:
lexer = self.get_lexer_for_body(mime, body)
if lexer:
body = pygments.highlight(
code=body,
lexer=lexer,
formatter=self.formatter,
)
return body
def get_lexer_for_body(
self, mime: str,
body: str
) -> Optional[Type[Lexer]]:
return get_lexer(
mime=mime,
explicit_json=self.explicit_json,
body=body,
)
@staticmethod
def get_style_class(color_scheme: str) -> Type[pygments.style.Style]:
try:
return pygments.styles.get_style_by_name(color_scheme)
except ClassNotFound:
return Solarized256Style
def get_lexer(
mime: str,
explicit_json=False,
body=''
) -> Optional[Type[Lexer]]:
# Build candidate mime type and lexer names.
mime_types, lexer_names = [mime], []
type_, subtype = mime.split('/', 1)
if '+' not in subtype:
lexer_names.append(subtype)
else:
subtype_name, subtype_suffix = subtype.split('+', 1)
lexer_names.extend([subtype_name, subtype_suffix])
mime_types.extend([
f'{type_}/{subtype_name}',
f'{type_}/{subtype_suffix}',
])
# As a last resort, if no lexer feels responsible, and
# the subtype contains 'json', take the JSON lexer
if 'json' in subtype:
lexer_names.append('json')
# Try to resolve the right lexer.
lexer = None
for mime_type in mime_types:
try:
lexer = pygments.lexers.get_lexer_for_mimetype(mime_type)
break
except ClassNotFound:
pass
else:
for name in lexer_names:
try:
lexer = pygments.lexers.get_lexer_by_name(name)
except ClassNotFound:
pass
if explicit_json and body and (not lexer or isinstance(lexer, TextLexer)):
# JSON response with an incorrect Content-Type?
try:
json.loads(body) # FIXME: the body also gets parsed in json.py
except ValueError:
pass # Nope
else:
lexer = pygments.lexers.get_lexer_by_name('json')
# Use our own JSON lexer: it supports JSON bodies preceded by non-JSON data
# as well as legit JSON bodies.
if isinstance(lexer, JsonLexer):
lexer = EnhancedJsonLexer()
return lexer
class Solarized256Style(pygments.style.Style):
"""
solarized256
------------
A Pygments style inspired by Solarized's 256 color mode.
:copyright: (c) 2011 by Hank Gay, (c) 2012 by John Mastro.
:license: BSD, see LICENSE for more details.
"""
BASE03 = "#1c1c1c"
BASE02 = "#262626"
BASE01 = "#4e4e4e"
BASE00 = "#585858"
BASE0 = "#808080"
BASE1 = "#8a8a8a"
BASE2 = "#d7d7af"
BASE3 = "#ffffd7"
YELLOW = "#af8700"
ORANGE = "#d75f00"
RED = "#af0000"
MAGENTA = "#af005f"
VIOLET = "#5f5faf"
BLUE = "#0087ff"
CYAN = "#00afaf"
GREEN = "#5f8700"
background_color = BASE03
styles = {
pygments.token.Keyword: GREEN,
pygments.token.Keyword.Constant: ORANGE,
pygments.token.Keyword.Declaration: BLUE,
pygments.token.Keyword.Namespace: ORANGE,
pygments.token.Keyword.Reserved: BLUE,
pygments.token.Keyword.Type: RED,
pygments.token.Name.Attribute: BASE1,
pygments.token.Name.Builtin: BLUE,
pygments.token.Name.Builtin.Pseudo: BLUE,
pygments.token.Name.Class: BLUE,
pygments.token.Name.Constant: ORANGE,
pygments.token.Name.Decorator: BLUE,
pygments.token.Name.Entity: ORANGE,
pygments.token.Name.Exception: YELLOW,
pygments.token.Name.Function: BLUE,
pygments.token.Name.Tag: BLUE,
pygments.token.Name.Variable: BLUE,
pygments.token.String: CYAN,
pygments.token.String.Backtick: BASE01,
pygments.token.String.Char: CYAN,
pygments.token.String.Doc: CYAN,
pygments.token.String.Escape: RED,
pygments.token.String.Heredoc: CYAN,
pygments.token.String.Regex: RED,
pygments.token.Number: CYAN,
pygments.token.Operator: BASE1,
pygments.token.Operator.Word: GREEN,
pygments.token.Comment: BASE01,
pygments.token.Comment.Preproc: GREEN,
pygments.token.Comment.Special: GREEN,
pygments.token.Generic.Deleted: CYAN,
pygments.token.Generic.Emph: 'italic',
pygments.token.Generic.Error: RED,
pygments.token.Generic.Heading: ORANGE,
pygments.token.Generic.Inserted: GREEN,
pygments.token.Generic.Strong: 'bold',
pygments.token.Generic.Subheading: ORANGE,
pygments.token.Token: BASE1,
pygments.token.Token.Other: ORANGE,
}

View File

@ -0,0 +1,18 @@
from ...plugins import FormatterPlugin
class HeadersFormatter(FormatterPlugin):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.enabled = self.format_options['headers']['sort']
def format_headers(self, headers: str) -> str:
"""
Sorts headers by name while retaining relative
order of multiple headers with the same name.
"""
lines = headers.splitlines()
headers = sorted(lines[1:], key=lambda h: h.split(':')[0])
return '\r\n'.join(lines[:1] + headers)

View File

@ -0,0 +1,34 @@
import json
from ...plugins import FormatterPlugin
class JSONFormatter(FormatterPlugin):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.enabled = self.format_options['json']['format']
def format_body(self, body: str, mime: str) -> str:
maybe_json = [
'json',
'javascript',
'text',
]
if (self.kwargs['explicit_json']
or any(token in mime for token in maybe_json)):
from ..utils import load_prefixed_json
try:
data_prefix, json_obj = load_prefixed_json(body)
except ValueError:
pass # Invalid JSON, ignore.
else:
# Indent, sort keys by name, and avoid
# unicode escapes to improve readability.
body = data_prefix + json.dumps(
obj=json_obj,
sort_keys=self.format_options['json']['sort_keys'],
ensure_ascii=False,
indent=self.format_options['json']['indent']
)
return body

View File

@ -0,0 +1,59 @@
import sys
from typing import TYPE_CHECKING, Optional
from ...encoding import UTF8
from ...plugins import FormatterPlugin
if TYPE_CHECKING:
from xml.dom.minidom import Document
def parse_xml(data: str) -> 'Document':
"""Parse given XML `data` string into an appropriate :class:`~xml.dom.minidom.Document` object."""
from defusedxml.minidom import parseString
return parseString(data)
def pretty_xml(document: 'Document',
encoding: Optional[str] = UTF8,
indent: int = 2,
standalone: Optional[bool] = None) -> str:
"""Render the given :class:`~xml.dom.minidom.Document` `document` into a prettified string."""
kwargs = {
'encoding': encoding or UTF8,
'indent': ' ' * indent,
}
if standalone is not None and sys.version_info >= (3, 9):
kwargs['standalone'] = standalone
body = document.toprettyxml(**kwargs).decode(kwargs['encoding'])
# Remove blank lines automatically added by `toprettyxml()`.
return '\n'.join(line for line in body.splitlines() if line.strip())
class XMLFormatter(FormatterPlugin):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.enabled = self.format_options['xml']['format']
def format_body(self, body: str, mime: str):
if 'xml' not in mime:
return body
from xml.parsers.expat import ExpatError
from defusedxml.common import DefusedXmlException
try:
parsed_body = parse_xml(body)
except ExpatError:
pass # Invalid XML, ignore.
except DefusedXmlException:
pass # Unsafe XML, ignore.
else:
body = pretty_xml(parsed_body,
encoding=parsed_body.encoding,
indent=self.format_options['xml']['indent'],
standalone=parsed_body.standalone)
return body

View File

View File

@ -0,0 +1,49 @@
import pygments
class SimplifiedHTTPLexer(pygments.lexer.RegexLexer):
"""Simplified HTTP lexer for Pygments.
It only operates on headers and provides a stronger contrast between
their names and values than the original one bundled with Pygments
(:class:`pygments.lexers.text import HttpLexer`), especially when
Solarized color scheme is used.
"""
name = 'HTTP'
aliases = ['http']
filenames = ['*.http']
tokens = {
'root': [
# Request-Line
(r'([A-Z]+)( +)([^ ]+)( +)(HTTP)(/)(\d+\.\d+)',
pygments.lexer.bygroups(
pygments.token.Name.Function,
pygments.token.Text,
pygments.token.Name.Namespace,
pygments.token.Text,
pygments.token.Keyword.Reserved,
pygments.token.Operator,
pygments.token.Number
)),
# Response Status-Line
(r'(HTTP)(/)(\d+\.\d+)( +)(\d{3})( +)(.+)',
pygments.lexer.bygroups(
pygments.token.Keyword.Reserved, # 'HTTP'
pygments.token.Operator, # '/'
pygments.token.Number, # Version
pygments.token.Text,
pygments.token.Number, # Status code
pygments.token.Text,
pygments.token.Name.Exception, # Reason
)),
# Header
(r'(.*?)( *)(:)( *)(.+)', pygments.lexer.bygroups(
pygments.token.Name.Attribute, # Name
pygments.token.Text,
pygments.token.Operator, # Colon
pygments.token.Text,
pygments.token.String # Value
))
]
}

View File

@ -0,0 +1,31 @@
import re
from pygments.lexer import bygroups, using, RegexLexer
from pygments.lexers.data import JsonLexer
from pygments.token import Token
PREFIX_TOKEN = Token.Error
PREFIX_REGEX = r'[^{\["]+'
class EnhancedJsonLexer(RegexLexer):
"""
Enhanced JSON lexer for Pygments.
It adds support for eventual data prefixing the actual JSON body.
"""
name = 'JSON'
flags = re.IGNORECASE | re.DOTALL
tokens = {
'root': [
# Eventual non-JSON data prefix followed by actual JSON body.
# FIX: data prefix + number (integer or float) are not correctly handled.
(
fr'({PREFIX_REGEX})' + r'((?:[{\["]|true|false|null).+)',
bygroups(PREFIX_TOKEN, using(JsonLexer))
),
# JSON body.
(r'.+', using(JsonLexer)),
],
}

View File

@ -0,0 +1,53 @@
import re
from typing import Optional, List
from ..plugins import ConverterPlugin
from ..plugins.registry import plugin_manager
from ..context import Environment
MIME_RE = re.compile(r'^[^/]+/[^/]+$')
def is_valid_mime(mime):
return mime and MIME_RE.match(mime)
class Conversion:
@staticmethod
def get_converter(mime: str) -> Optional[ConverterPlugin]:
if is_valid_mime(mime):
for converter_class in plugin_manager.get_converters():
if converter_class.supports(mime):
return converter_class(mime)
class Formatting:
"""A delegate class that invokes the actual processors."""
def __init__(self, groups: List[str], env=Environment(), **kwargs):
"""
:param groups: names of processor groups to be applied
:param env: Environment
:param kwargs: additional keyword arguments for processors
"""
available_plugins = plugin_manager.get_formatters_grouped()
self.enabled_plugins = []
for group in groups:
for cls in available_plugins[group]:
p = cls(env=env, **kwargs)
if p.enabled:
self.enabled_plugins.append(p)
def format_headers(self, headers: str) -> str:
for p in self.enabled_plugins:
headers = p.format_headers(headers)
return headers
def format_body(self, content: str, mime: str) -> str:
if is_valid_mime(mime):
for p in self.enabled_plugins:
content = p.format_body(content, mime)
return content

208
httpie/output/streams.py Normal file
View File

@ -0,0 +1,208 @@
from abc import ABCMeta, abstractmethod
from itertools import chain
from typing import Callable, Iterable, Union
from .processing import Conversion, Formatting
from ..context import Environment
from ..encoding import smart_decode, smart_encode, UTF8
from ..models import HTTPMessage
BINARY_SUPPRESSED_NOTICE = (
b'\n'
b'+-----------------------------------------+\n'
b'| NOTE: binary data not shown in terminal |\n'
b'+-----------------------------------------+'
)
class DataSuppressedError(Exception):
message = None
class BinarySuppressedError(DataSuppressedError):
"""An error indicating that the body is binary and won't be written,
e.g., for terminal output)."""
message = BINARY_SUPPRESSED_NOTICE
class BaseStream(metaclass=ABCMeta):
"""Base HTTP message output stream class."""
def __init__(
self,
msg: HTTPMessage,
with_headers=True,
with_body=True,
on_body_chunk_downloaded: Callable[[bytes], None] = None
):
"""
:param msg: a :class:`models.HTTPMessage` subclass
:param with_headers: if `True`, headers will be included
:param with_body: if `True`, body will be included
"""
assert with_headers or with_body
self.msg = msg
self.with_headers = with_headers
self.with_body = with_body
self.on_body_chunk_downloaded = on_body_chunk_downloaded
def get_headers(self) -> bytes:
"""Return the headers' bytes."""
return self.msg.headers.encode()
@abstractmethod
def iter_body(self) -> Iterable[bytes]:
"""Return an iterator over the message body."""
def __iter__(self) -> Iterable[bytes]:
"""Return an iterator over `self.msg`."""
if self.with_headers:
yield self.get_headers()
yield b'\r\n\r\n'
if self.with_body:
try:
for chunk in self.iter_body():
yield chunk
if self.on_body_chunk_downloaded:
self.on_body_chunk_downloaded(chunk)
except DataSuppressedError as e:
if self.with_headers:
yield b'\n'
yield e.message
class RawStream(BaseStream):
"""The message is streamed in chunks with no processing."""
CHUNK_SIZE = 1024 * 100
CHUNK_SIZE_BY_LINE = 1
def __init__(self, chunk_size=CHUNK_SIZE, **kwargs):
super().__init__(**kwargs)
self.chunk_size = chunk_size
def iter_body(self) -> Iterable[bytes]:
return self.msg.iter_body(self.chunk_size)
class EncodedStream(BaseStream):
"""Encoded HTTP message stream.
The message bytes are converted to an encoding suitable for
`self.env.stdout`. Unicode errors are replaced and binary data
is suppressed. The body is always streamed by line.
"""
CHUNK_SIZE = 1
def __init__(
self,
env=Environment(),
mime_overwrite: str = None,
encoding_overwrite: str = None,
**kwargs
):
super().__init__(**kwargs)
self.mime = mime_overwrite or self.msg.content_type
self.encoding = encoding_overwrite or self.msg.encoding
if env.stdout_isatty:
# Use the encoding supported by the terminal.
output_encoding = env.stdout_encoding
else:
# Preserve the message encoding.
output_encoding = self.msg.encoding
# Default to UTF-8 when unsure.
self.output_encoding = output_encoding or UTF8
def iter_body(self) -> Iterable[bytes]:
for line, lf in self.msg.iter_lines(self.CHUNK_SIZE):
if b'\0' in line:
raise BinarySuppressedError()
line = smart_decode(line, self.encoding)
yield smart_encode(line, self.output_encoding) + lf
class PrettyStream(EncodedStream):
"""In addition to :class:`EncodedStream` behaviour, this stream applies
content processing.
Useful for long-lived HTTP responses that stream by lines
such as the Twitter streaming API.
"""
CHUNK_SIZE = 1
def __init__(
self, conversion: Conversion,
formatting: Formatting,
**kwargs,
):
super().__init__(**kwargs)
self.formatting = formatting
self.conversion = conversion
def get_headers(self) -> bytes:
return self.formatting.format_headers(
self.msg.headers).encode(self.output_encoding)
def iter_body(self) -> Iterable[bytes]:
first_chunk = True
iter_lines = self.msg.iter_lines(self.CHUNK_SIZE)
for line, lf in iter_lines:
if b'\0' in line:
if first_chunk:
converter = self.conversion.get_converter(self.mime)
if converter:
body = bytearray()
# noinspection PyAssignmentToLoopOrWithParameter
for line, lf in chain([(line, lf)], iter_lines):
body.extend(line)
body.extend(lf)
self.mime, body = converter.convert(body)
assert isinstance(body, str)
yield self.process_body(body)
return
raise BinarySuppressedError()
yield self.process_body(line) + lf
first_chunk = False
def process_body(self, chunk: Union[str, bytes]) -> bytes:
if not isinstance(chunk, str):
# Text when a converter has been used,
# otherwise it will always be bytes.
chunk = smart_decode(chunk, self.encoding)
chunk = self.formatting.format_body(content=chunk, mime=self.mime)
return smart_encode(chunk, self.output_encoding)
class BufferedPrettyStream(PrettyStream):
"""The same as :class:`PrettyStream` except that the body is fully
fetched before it's processed.
Suitable regular HTTP responses.
"""
CHUNK_SIZE = 1024 * 10
def iter_body(self) -> Iterable[bytes]:
# Read the whole body before prettifying it,
# but bail out immediately if the body is binary.
converter = None
body = bytearray()
for chunk in self.msg.iter_body(self.CHUNK_SIZE):
if not converter and b'\0' in chunk:
converter = self.conversion.get_converter(self.mime)
if not converter:
raise BinarySuppressedError()
body.extend(chunk)
if converter:
self.mime, body = converter.convert(body)
yield self.process_body(body)

37
httpie/output/utils.py Normal file
View File

@ -0,0 +1,37 @@
import json
import re
from typing import Tuple
from ..utils import load_json_preserve_order_and_dupe_keys
from .lexers.json import PREFIX_REGEX
def load_prefixed_json(data: str) -> Tuple[str, json.JSONDecoder]:
"""Simple JSON loading from `data`.
"""
# First, the full data.
try:
return '', load_json_preserve_order_and_dupe_keys(data)
except ValueError:
pass
# Then, try to find the start of the actual body.
data_prefix, body = parse_prefixed_json(data)
try:
return data_prefix, load_json_preserve_order_and_dupe_keys(body)
except ValueError:
raise ValueError('Invalid JSON')
def parse_prefixed_json(data: str) -> Tuple[str, str]:
"""Find the potential JSON body from `data`.
Sometimes the JSON body is prefixed with a XSSI magic string, specific to the server.
Return a tuple (data prefix, actual JSON body).
"""
matches = re.findall(PREFIX_REGEX, data)
data_prefix = matches[0] if matches else ''
body = data[len(data_prefix):]
return data_prefix, body

162
httpie/output/writer.py Normal file
View File

@ -0,0 +1,162 @@
import argparse
import errno
from typing import IO, TextIO, Tuple, Type, Union
import requests
from ..context import Environment
from ..models import HTTPRequest, HTTPResponse, HTTPMessage
from .processing import Conversion, Formatting
from .streams import (
BaseStream, BufferedPrettyStream, EncodedStream, PrettyStream, RawStream,
)
MESSAGE_SEPARATOR = '\n\n'
MESSAGE_SEPARATOR_BYTES = MESSAGE_SEPARATOR.encode()
def write_message(
requests_message: Union[requests.PreparedRequest, requests.Response],
env: Environment,
args: argparse.Namespace,
with_headers=False,
with_body=False,
):
if not (with_body or with_headers):
return
write_stream_kwargs = {
'stream': build_output_stream_for_message(
args=args,
env=env,
requests_message=requests_message,
with_body=with_body,
with_headers=with_headers,
),
# NOTE: `env.stdout` will in fact be `stderr` with `--download`
'outfile': env.stdout,
'flush': env.stdout_isatty or args.stream
}
try:
if env.is_windows and 'colors' in args.prettify:
write_stream_with_colors_win(**write_stream_kwargs)
else:
write_stream(**write_stream_kwargs)
except OSError as e:
show_traceback = args.debug or args.traceback
if not show_traceback and e.errno == errno.EPIPE:
# Ignore broken pipes unless --traceback.
env.stderr.write('\n')
else:
raise
def write_stream(
stream: BaseStream,
outfile: Union[IO, TextIO],
flush: bool
):
"""Write the output stream."""
try:
# Writing bytes so we use the buffer interface.
buf = outfile.buffer
except AttributeError:
buf = outfile
for chunk in stream:
buf.write(chunk)
if flush:
outfile.flush()
def write_stream_with_colors_win(
stream: 'BaseStream',
outfile: TextIO,
flush: bool
):
"""Like `write`, but colorized chunks are written as text
directly to `outfile` to ensure it gets processed by colorama.
Applies only to Windows and colorized terminal output.
"""
color = b'\x1b['
encoding = outfile.encoding
for chunk in stream:
if color in chunk:
outfile.write(chunk.decode(encoding))
else:
outfile.buffer.write(chunk)
if flush:
outfile.flush()
def build_output_stream_for_message(
args: argparse.Namespace,
env: Environment,
requests_message: Union[requests.PreparedRequest, requests.Response],
with_headers: bool,
with_body: bool,
):
message_type = {
requests.PreparedRequest: HTTPRequest,
requests.Response: HTTPResponse,
}[type(requests_message)]
stream_class, stream_kwargs = get_stream_type_and_kwargs(
env=env,
args=args,
message_type=message_type,
)
yield from stream_class(
msg=message_type(requests_message),
with_headers=with_headers,
with_body=with_body,
**stream_kwargs,
)
if (env.stdout_isatty and with_body
and not getattr(requests_message, 'is_body_upload_chunk', False)):
# Ensure a blank line after the response body.
# For terminal output only.
yield MESSAGE_SEPARATOR_BYTES
def get_stream_type_and_kwargs(
env: Environment,
args: argparse.Namespace,
message_type: Type[HTTPMessage],
) -> Tuple[Type['BaseStream'], dict]:
"""Pick the right stream type and kwargs for it based on `env` and `args`.
"""
if not env.stdout_isatty and not args.prettify:
stream_class = RawStream
stream_kwargs = {
'chunk_size': (
RawStream.CHUNK_SIZE_BY_LINE
if args.stream
else RawStream.CHUNK_SIZE
)
}
else:
stream_class = EncodedStream
stream_kwargs = {
'env': env,
}
if message_type is HTTPResponse:
stream_kwargs.update({
'mime_overwrite': args.response_mime,
'encoding_overwrite': args.response_charset,
})
if args.prettify:
stream_class = PrettyStream if args.stream else BufferedPrettyStream
stream_kwargs.update({
'conversion': Conversion(),
'formatting': Formatting(
env=env,
groups=args.prettify,
color_scheme=args.style,
explicit_json=args.json,
format_options=args.format_options,
)
})
return stream_class, stream_kwargs

Some files were not shown because too many files have changed in this diff Show More