forked from extern/httpie-cli
Compare commits
1 Commits
master
...
fix-initia
Author | SHA1 | Date | |
---|---|---|---|
|
9d2e2afede |
@ -1,22 +1,28 @@
|
||||
name: Update Generated Content
|
||||
name: Update Autogenerated Files
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
update-content:
|
||||
regen-autogenerated-files:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
|
||||
- uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: 3.9
|
||||
- run: make content
|
||||
|
||||
- run: make regen-all
|
||||
|
||||
- name: Create Pull Request
|
||||
id: cpr
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
commit-message: "[automated] Update generated content"
|
||||
title: "[automated] Update generated content"
|
||||
commit-message: "[automated] Update auto-generated files"
|
||||
title: "[automated] Update auto-generated files"
|
||||
delete-branch: true
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
2
.github/workflows/benchmark.yml
vendored
2
.github/workflows/benchmark.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: "3.9"
|
||||
|
||||
|
2
.github/workflows/code-style.yml
vendored
2
.github/workflows/code-style.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: 3.9
|
||||
- run: make venv
|
||||
|
2
.github/workflows/coverage.yml
vendored
2
.github/workflows/coverage.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- run: make install
|
||||
|
2
.github/workflows/docs-deploy.yml
vendored
2
.github/workflows/docs-deploy.yml
vendored
@ -17,6 +17,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install HTTPie
|
||||
run: sudo pip install httpie
|
||||
run: sudo snap install --edge httpie
|
||||
- name: Trigger new documentation build
|
||||
run: http --ignore-stdin POST ${{ secrets.DOCS_UPDATE_VERCEL_HOOK }}
|
||||
|
2
.github/workflows/release-brew.yml
vendored
2
.github/workflows/release-brew.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.event.inputs.branch }}
|
||||
|
||||
- uses: mislav/bump-homebrew-formula-action@v2
|
||||
- uses: mislav/bump-homebrew-formula-action@v1
|
||||
with:
|
||||
formula-name: httpie
|
||||
tag-name: ${{ github.events.inputs.branch }}
|
||||
|
@ -24,7 +24,7 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.event.inputs.branch }}
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: 3.9
|
||||
|
||||
@ -52,7 +52,7 @@ jobs:
|
||||
id: release_id
|
||||
run: |
|
||||
pip install httpie
|
||||
export API_URL="api.github.com/repos/httpie/cli/releases/tags/${{ github.event.inputs.tag_name }}"
|
||||
export API_URL="api.github.com/repos/httpie/httpie/releases/tags/${{ github.event.inputs.tag_name }}"
|
||||
export UPLOAD_URL=`https --ignore-stdin GET $API_URL | jq -r ".upload_url"`
|
||||
echo "::set-output name=UPLOAD_URL::$UPLOAD_URL"
|
||||
|
||||
|
2
.github/workflows/release-pypi.yml
vendored
2
.github/workflows/release-pypi.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.event.inputs.branch }}
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: 3.9
|
||||
|
||||
|
3
.github/workflows/release-snap.yml
vendored
3
.github/workflows/release-snap.yml
vendored
@ -34,8 +34,7 @@ jobs:
|
||||
id: build
|
||||
|
||||
- uses: snapcore/action-publish@v1
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||
with:
|
||||
store_login: ${{ secrets.SNAP_STORE_LOGIN }}
|
||||
snap: ${{ steps.build.outputs.snap }}
|
||||
release: ${{ matrix.level }}
|
||||
|
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v8
|
||||
- uses: actions/stale@v5
|
||||
with:
|
||||
close-pr-message: 'Thanks for the pull request, but since it was stale for more than a 30 days we are closing it. If you want to work back on it, feel free to re-open it or create a new one.'
|
||||
stale-pr-label: 'stale'
|
||||
|
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@ -30,7 +30,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Windows setup
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
## Patches, features, ideas
|
||||
|
||||
[Complete list of contributors on GitHub](https://github.com/httpie/cli/graphs/contributors)
|
||||
[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)
|
||||
|
254
CHANGELOG.md
254
CHANGELOG.md
@ -3,151 +3,143 @@
|
||||
This document records all notable changes to [HTTPie](https://httpie.io).
|
||||
This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## [3.3.0-dev](https://github.com/httpie/cli/compare/3.2.2...master) (unreleased)
|
||||
## [3.2.1](https://github.com/httpie/httpie/compare/3.1.0...3.2.1) (2022-05-06)
|
||||
|
||||
- Make it possible to [unset](https://httpie.io/docs/cli/default-request-headers) the `User-Agent`, `Accept-Encoding`, and `Host` request headers. ([#1502](https://github.com/httpie/cli/issues/1502))
|
||||
- Improved support for determining auto-streaming when the `Content-Type` header includes encoding information. ([#1383](https://github.com/httpie/httpie/pull/1383))
|
||||
- Fixed the display of the crash happening in the secondary process for update checks. ([#1388](https://github.com/httpie/httpie/issues/1388))
|
||||
|
||||
## [3.2.2](https://github.com/httpie/cli/compare/3.2.1...3.2.2) (2022-05-19)
|
||||
## [3.2.0](https://github.com/httpie/httpie/compare/3.1.0...3.2.0) (2022-05-05)
|
||||
|
||||
- Fixed compatibility with urllib3 2.0.0. ([#1499](https://github.com/httpie/cli/issues/1499))
|
||||
- Added a warning for notifying the user about the new updates. ([#1336](https://github.com/httpie/httpie/pull/1336))
|
||||
- Added support for single binary executables. ([#1330](https://github.com/httpie/httpie/pull/1330))
|
||||
- Added support for man pages (and auto generation of them from the parser declaration). ([#1317](https://github.com/httpie/httpie/pull/1317))
|
||||
- Added `http --manual` for man pages & regular manual with pager. ([#1343](https://github.com/httpie/httpie/pull/1343))
|
||||
- Added support for session persistence of repeated headers with the same name. ([#1335](https://github.com/httpie/httpie/pull/1335))
|
||||
- Added support for sending `Secure` cookies to the `localhost` (and `.local` suffixed domains). ([#1308](https://github.com/httpie/httpie/issues/1308))
|
||||
- Improved UI for the progress bars. ([#1324](https://github.com/httpie/httpie/pull/1324))
|
||||
- Fixed redundant creation of `Content-Length` header on `OPTIONS` requests. ([#1310](https://github.com/httpie/httpie/issues/1310))
|
||||
- Fixed blocking of warning thread on some use cases. ([#1349](https://github.com/httpie/httpie/issues/1349))
|
||||
- Changed `httpie plugins` to the new `httpie cli` namespace as `httpie cli plugins` (`httpie plugins` continues to work as a hidden alias). ([#1320](https://github.com/httpie/httpie/issues/1320))
|
||||
- Soft deprecated the `--history-print`. ([#1380](https://github.com/httpie/httpie/pull/1380))
|
||||
|
||||
## [3.2.1](https://github.com/httpie/cli/compare/3.1.0...3.2.1) (2022-05-06)
|
||||
## [3.1.0](https://github.com/httpie/httpie/compare/3.0.2...3.1.0) (2022-03-08)
|
||||
|
||||
- Improved support for determining auto-streaming when the `Content-Type` header includes encoding information. ([#1383](https://github.com/httpie/cli/pull/1383))
|
||||
- Fixed the display of the crash happening in the secondary process for update checks. ([#1388](https://github.com/httpie/cli/issues/1388))
|
||||
- **SECURITY** Fixed the [vulnerability](https://github.com/httpie/httpie/security/advisories/GHSA-9w4w-cpc8-h2fq) that caused exposure of cookies on redirects to third party hosts. ([#1312](https://github.com/httpie/httpie/pull/1312))
|
||||
- Fixed escaping of integer indexes with multiple backslashes in the nested JSON builder. ([#1285](https://github.com/httpie/httpie/issues/1285))
|
||||
- Fixed displaying of status code without a status message on non-`auto` themes. ([#1300](https://github.com/httpie/httpie/issues/1300))
|
||||
- Fixed redundant issuance of stdin detection warnings on some rare cases due to underlying implementation. ([#1303](https://github.com/httpie/httpie/pull/1303))
|
||||
- Fixed double `--quiet` so that it will now suppress all python level warnings. ([#1271](https://github.com/httpie/httpie/issues/1271))
|
||||
- Added support for specifying certificate private key passphrases through `--cert-key-pass` and prompts. ([#946](https://github.com/httpie/httpie/issues/946))
|
||||
- Added `httpie cli export-args` command for exposing the parser specification for the `http`/`https` commands. ([#1293](https://github.com/httpie/httpie/pull/1293))
|
||||
- Improved regulation of top-level arrays. ([#1292](https://github.com/httpie/httpie/commit/225dccb2186f14f871695b6c4e0bfbcdb2e3aa28))
|
||||
- Improved UI layout for standalone invocations. ([#1296](https://github.com/httpie/httpie/pull/1296))
|
||||
|
||||
## [3.2.0](https://github.com/httpie/cli/compare/3.1.0...3.2.0) (2022-05-05)
|
||||
|
||||
- Added a warning for notifying the user about the new updates. ([#1336](https://github.com/httpie/cli/pull/1336))
|
||||
- Added support for single binary executables. ([#1330](https://github.com/httpie/cli/pull/1330))
|
||||
- Added support for man pages (and auto generation of them from the parser declaration). ([#1317](https://github.com/httpie/cli/pull/1317))
|
||||
- Added `http --manual` for man pages & regular manual with pager. ([#1343](https://github.com/httpie/cli/pull/1343))
|
||||
- Added support for session persistence of repeated headers with the same name. ([#1335](https://github.com/httpie/cli/pull/1335))
|
||||
- Added support for sending `Secure` cookies to the `localhost` (and `.local` suffixed domains). ([#1308](https://github.com/httpie/cli/issues/1308))
|
||||
- Improved UI for the progress bars. ([#1324](https://github.com/httpie/cli/pull/1324))
|
||||
- Fixed redundant creation of `Content-Length` header on `OPTIONS` requests. ([#1310](https://github.com/httpie/cli/issues/1310))
|
||||
- Fixed blocking of warning thread on some use cases. ([#1349](https://github.com/httpie/cli/issues/1349))
|
||||
- Changed `httpie plugins` to the new `httpie cli` namespace as `httpie cli plugins` (`httpie plugins` continues to work as a hidden alias). ([#1320](https://github.com/httpie/cli/issues/1320))
|
||||
- Soft deprecated the `--history-print`. ([#1380](https://github.com/httpie/cli/pull/1380))
|
||||
|
||||
## [3.1.0](https://github.com/httpie/cli/compare/3.0.2...3.1.0) (2022-03-08)
|
||||
|
||||
- **SECURITY** Fixed the [vulnerability](https://github.com/httpie/cli/security/advisories/GHSA-9w4w-cpc8-h2fq) that caused exposure of cookies on redirects to third party hosts. ([#1312](https://github.com/httpie/cli/pull/1312))
|
||||
- Fixed escaping of integer indexes with multiple backslashes in the nested JSON builder. ([#1285](https://github.com/httpie/cli/issues/1285))
|
||||
- Fixed displaying of status code without a status message on non-`auto` themes. ([#1300](https://github.com/httpie/cli/issues/1300))
|
||||
- Fixed redundant issuance of stdin detection warnings on some rare cases due to underlying implementation. ([#1303](https://github.com/httpie/cli/pull/1303))
|
||||
- Fixed double `--quiet` so that it will now suppress all python level warnings. ([#1271](https://github.com/httpie/cli/issues/1271))
|
||||
- Added support for specifying certificate private key passphrases through `--cert-key-pass` and prompts. ([#946](https://github.com/httpie/cli/issues/946))
|
||||
- Added `httpie cli export-args` command for exposing the parser specification for the `http`/`https` commands. ([#1293](https://github.com/httpie/cli/pull/1293))
|
||||
- Improved regulation of top-level arrays. ([#1292](https://github.com/httpie/cli/commit/225dccb2186f14f871695b6c4e0bfbcdb2e3aa28))
|
||||
- Improved UI layout for standalone invocations. ([#1296](https://github.com/httpie/cli/pull/1296))
|
||||
|
||||
## [3.0.2](https://github.com/httpie/cli/compare/3.0.1...3.0.2) (2022-01-24)
|
||||
## [3.0.2](https://github.com/httpie/httpie/compare/3.0.1...3.0.2) (2022-01-24)
|
||||
|
||||
[What’s new in HTTPie for Terminal 3.0 →](https://httpie.io/blog/httpie-3.0.0)
|
||||
|
||||
- Fixed usage of `httpie` when there is a presence of a config with `default_options`. ([#1280](https://github.com/httpie/cli/pull/1280))
|
||||
- Fixed usage of `httpie` when there is a presence of a config with `default_options`. ([#1280](https://github.com/httpie/httpie/pull/1280))
|
||||
|
||||
## [3.0.1](https://github.com/httpie/cli/compare/3.0.0...3.0.1) (2022-01-23)
|
||||
## [3.0.1](https://github.com/httpie/httpie/compare/3.0.0...3.0.1) (2022-01-23)
|
||||
|
||||
[What’s new in HTTPie for Terminal 3.0 →](https://httpie.io/blog/httpie-3.0.0)
|
||||
|
||||
- Changed the value shown as time elapsed from time-to-read-headers to total exchange time. ([#1277](https://github.com/httpie/cli/issues/1277))
|
||||
- Changed the value shown as time elapsed from time-to-read-headers to total exchange time. ([#1277](https://github.com/httpie/httpie/issues/1277))
|
||||
|
||||
## [3.0.0](https://github.com/httpie/cli/compare/2.6.0...3.0.0) (2022-01-21)
|
||||
## [3.0.0](https://github.com/httpie/httpie/compare/2.6.0...3.0.0) (2022-01-21)
|
||||
|
||||
[What’s new in HTTPie for Terminal 3.0 →](https://httpie.io/blog/httpie-3.0.0)
|
||||
|
||||
- Dropped support for Python 3.6. ([#1177](https://github.com/httpie/cli/issues/1177))
|
||||
- Improved startup time by 40%. ([#1211](https://github.com/httpie/cli/pull/1211))
|
||||
- Added support for nested JSON syntax. ([#1169](https://github.com/httpie/cli/issues/1169))
|
||||
- Added `httpie plugins` interface for plugin management. ([#566](https://github.com/httpie/cli/issues/566))
|
||||
- Added support for Bearer authentication via `--auth-type=bearer` ([#1215](https://github.com/httpie/cli/issues/1215)).
|
||||
- Added support for quick conversions of pasted URLs into HTTPie calls by adding a space after the protocol name (`$ https ://pie.dev` → `https://pie.dev`). ([#1195](https://github.com/httpie/cli/issues/1195))
|
||||
- Added support for _sending_ multiple HTTP header lines with the same name. ([#130](https://github.com/httpie/cli/issues/130))
|
||||
- Added support for _receiving_ multiple HTTP headers lines with the same name. ([#1207](https://github.com/httpie/cli/issues/1207))
|
||||
- Added support for basic JSON types on `--form`/`--multipart` when using JSON only operators (`:=`/`:=@`). ([#1212](https://github.com/httpie/cli/issues/1212))
|
||||
- Added support for automatically enabling `--stream` when `Content-Type` is `text/event-stream`. ([#376](https://github.com/httpie/cli/issues/376))
|
||||
- Added support for displaying the total elapsed time through `--meta`/`-vv` or `--print=m`. ([#243](https://github.com/httpie/cli/issues/243))
|
||||
- Added new `pie-dark`/`pie-light` (and `pie`) styles that match with [HTTPie for Web and Desktop](https://httpie.io/product). ([#1237](https://github.com/httpie/cli/issues/1237))
|
||||
- Added support for better error handling on DNS failures. ([#1248](https://github.com/httpie/cli/issues/1248))
|
||||
- Added support for storing prompted passwords in the local sessions. ([#1098](https://github.com/httpie/cli/issues/1098))
|
||||
- Added warnings about the `--ignore-stdin`, when there is no incoming data from stdin. ([#1255](https://github.com/httpie/cli/issues/1255))
|
||||
- Fixed crashing due to broken plugins. ([#1204](https://github.com/httpie/cli/issues/1204))
|
||||
- Fixed auto addition of XML declaration to every formatted XML response. ([#1156](https://github.com/httpie/cli/issues/1156))
|
||||
- Fixed highlighting when `Content-Type` specifies `charset`. ([#1242](https://github.com/httpie/cli/issues/1242))
|
||||
- Fixed an unexpected crash when `--raw` is used with `--chunked`. ([#1253](https://github.com/httpie/cli/issues/1253))
|
||||
- Changed the default Windows theme from `fruity` to `auto`. ([#1266](https://github.com/httpie/cli/issues/1266))
|
||||
- Dropped support for Python 3.6. ([#1177](https://github.com/httpie/httpie/issues/1177))
|
||||
- Improved startup time by 40%. ([#1211](https://github.com/httpie/httpie/pull/1211))
|
||||
- Added support for nested JSON syntax. ([#1169](https://github.com/httpie/httpie/issues/1169))
|
||||
- Added `httpie plugins` interface for plugin management. ([#566](https://github.com/httpie/httpie/issues/566))
|
||||
- Added support for Bearer authentication via `--auth-type=bearer` ([#1215](https://github.com/httpie/httpie/issues/1215)).
|
||||
- Added support for quick conversions of pasted URLs into HTTPie calls by adding a space after the protocol name (`$ https ://pie.dev` → `https://pie.dev`). ([#1195](https://github.com/httpie/httpie/issues/1195))
|
||||
- Added support for _sending_ multiple HTTP header lines with the same name. ([#130](https://github.com/httpie/httpie/issues/130))
|
||||
- Added support for _receiving_ multiple HTTP headers lines with the same name. ([#1207](https://github.com/httpie/httpie/issues/1207))
|
||||
- Added support for basic JSON types on `--form`/`--multipart` when using JSON only operators (`:=`/`:=@`). ([#1212](https://github.com/httpie/httpie/issues/1212))
|
||||
- Added support for automatically enabling `--stream` when `Content-Type` is `text/event-stream`. ([#376](https://github.com/httpie/httpie/issues/376))
|
||||
- Added support for displaying the total elapsed time through `--meta`/`-vv` or `--print=m`. ([#243](https://github.com/httpie/httpie/issues/243))
|
||||
- Added new `pie-dark`/`pie-light` (and `pie`) styles that match with [HTTPie for Web and Desktop](https://httpie.io/product). ([#1237](https://github.com/httpie/httpie/issues/1237))
|
||||
- Added support for better error handling on DNS failures. ([#1248](https://github.com/httpie/httpie/issues/1248))
|
||||
- Added support for storing prompted passwords in the local sessions. ([#1098](https://github.com/httpie/httpie/issues/1098))
|
||||
- Added warnings about the `--ignore-stdin`, when there is no incoming data from stdin. ([#1255](https://github.com/httpie/httpie/issues/1255))
|
||||
- Fixed crashing due to broken plugins. ([#1204](https://github.com/httpie/httpie/issues/1204))
|
||||
- Fixed auto addition of XML declaration to every formatted XML response. ([#1156](https://github.com/httpie/httpie/issues/1156))
|
||||
- Fixed highlighting when `Content-Type` specifies `charset`. ([#1242](https://github.com/httpie/httpie/issues/1242))
|
||||
- Fixed an unexpected crash when `--raw` is used with `--chunked`. ([#1253](https://github.com/httpie/httpie/issues/1253))
|
||||
- Changed the default Windows theme from `fruity` to `auto`. ([#1266](https://github.com/httpie/httpie/issues/1266))
|
||||
|
||||
## [2.6.0](https://github.com/httpie/cli/compare/2.5.0...2.6.0) (2021-10-14)
|
||||
## [2.6.0](https://github.com/httpie/httpie/compare/2.5.0...2.6.0) (2021-10-14)
|
||||
|
||||
[What’s new in HTTPie for Terminal 2.6.0 →](https://httpie.io/blog/httpie-2.6.0)
|
||||
|
||||
- Added support for formatting & coloring of JSON bodies preceded by non-JSON data (e.g., an XXSI prefix). ([#1130](https://github.com/httpie/cli/issues/1130))
|
||||
- Added charset auto-detection when `Content-Type` doesn’t include it. ([#1110](https://github.com/httpie/cli/issues/1110), [#1168](https://github.com/httpie/cli/issues/1168))
|
||||
- Added `--response-charset` to allow overriding the response encoding for terminal display purposes. ([#1168](https://github.com/httpie/cli/issues/1168))
|
||||
- Added `--response-mime` to allow overriding the response mime type for coloring and formatting for the terminal. ([#1168](https://github.com/httpie/cli/issues/1168))
|
||||
- Added the ability to silence warnings through using `-q` or `--quiet` twice (e.g. `-qq`) ([#1175](https://github.com/httpie/cli/issues/1175))
|
||||
- Added installed plugin list to `--debug` output. ([#1165](https://github.com/httpie/cli/issues/1165))
|
||||
- Fixed duplicate keys preservation in JSON data. ([#1163](https://github.com/httpie/cli/issues/1163))
|
||||
- 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 charset auto-detection when `Content-Type` doesn’t include it. ([#1110](https://github.com/httpie/httpie/issues/1110), [#1168](https://github.com/httpie/httpie/issues/1168))
|
||||
- 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))
|
||||
- Added the ability to silence warnings through using `-q` or `--quiet` twice (e.g. `-qq`) ([#1175](https://github.com/httpie/httpie/issues/1175))
|
||||
- Added installed plugin list to `--debug` output. ([#1165](https://github.com/httpie/httpie/issues/1165))
|
||||
- Fixed duplicate keys preservation in JSON data. ([#1163](https://github.com/httpie/httpie/issues/1163))
|
||||
|
||||
## [2.5.0](https://github.com/httpie/cli/compare/2.4.0...2.5.0) (2021-09-06)
|
||||
## [2.5.0](https://github.com/httpie/httpie/compare/2.4.0...2.5.0) (2021-09-06)
|
||||
|
||||
[What’s new in HTTPie for Terminal 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/cli/issues/534))
|
||||
- Added support for XML formatting. ([#1129](https://github.com/httpie/cli/issues/1129))
|
||||
- Added internal support for file-like object responses to improve adapter plugin support. ([#1094](https://github.com/httpie/cli/issues/1094))
|
||||
- Fixed `--continue --download` with a single byte to be downloaded left. ([#1032](https://github.com/httpie/cli/issues/1032))
|
||||
- Fixed `--verbose` HTTP 307 redirects with streamed request body. ([#1088](https://github.com/httpie/cli/issues/1088))
|
||||
- Fixed handling of session files with `Cookie:` followed by other headers. ([#1126](https://github.com/httpie/cli/issues/1126))
|
||||
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/cli/compare/2.3.0...2.4.0) (2021-02-06)
|
||||
## [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/cli/issues/1029))
|
||||
- Show a `--check-status` warning with `--quiet` as well, not only when the output is redirected. ([#1026](https://github.com/httpie/cli/issues/1026))
|
||||
- Fixed upload with `--session` ([#1020](https://github.com/httpie/cli/issues/1020)).
|
||||
- Fixed a missing blank line between request and response ([#1006](https://github.com/httpie/cli/issues/1006)).
|
||||
- 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/cli/compare/2.2.0...2.3.0) (2020-10-25)
|
||||
## [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/cli/issues/201)).
|
||||
- Added support for multipart upload streaming ([#684](https://github.com/httpie/cli/issues/684)).
|
||||
- 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/cli/issues/753)).
|
||||
- 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/cli/issues/903)).
|
||||
- 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/cli/issues/932)).
|
||||
- Added out of the box SOCKS support with no extra installation ([#904](https://github.com/httpie/cli/issues/904)).
|
||||
- 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/cli/issues/963)).
|
||||
- Removed Tox testing entirely ([#943](https://github.com/httpie/cli/issues/943)).
|
||||
- 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/cli/compare/2.1.0...2.2.0) (2020-06-18)
|
||||
## [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/cli/issues/668)).
|
||||
- Added support for `$XDG_CONFIG_HOME` ([#920](https://github.com/httpie/cli/issues/920)).
|
||||
- Added support for `Set-Cookie`-triggered cookie expiration ([#853](https://github.com/httpie/cli/issues/853)).
|
||||
- Added `--format-options` to allow disabling sorting, etc. ([#128](https://github.com/httpie/cli/issues/128))
|
||||
- Added `--sorted` and `--unsorted` shortcuts for (un)setting all sorting-related `--format-options`. ([#128](https://github.com/httpie/cli/issues/128))
|
||||
- Added `--ciphers` to allow configuring OpenSSL ciphers ([#870](https://github.com/httpie/cli/issues/870)).
|
||||
- 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/cli/issues/718), [#719](https://github.com/httpie/cli/issues/719), [#852](https://github.com/httpie/cli/issues/852), [#934](https://github.com/httpie/cli/issues/934)).
|
||||
- Fixed built-in plugins-related circular imports ([#925](https://github.com/httpie/cli/issues/925)).
|
||||
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/cli/compare/2.0.0...2.1.0) (2020-04-18)
|
||||
## [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/cli/issues/895)).
|
||||
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/cli/issues/488)).
|
||||
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/cli/issues/840)).
|
||||
([#840](https://github.com/httpie/httpie/issues/840)).
|
||||
|
||||
## [2.0.0](https://github.com/httpie/cli/compare/1.0.3...2.0.0) (2020-01-12)
|
||||
## [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
|
||||
@ -170,7 +162,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- Fixed an error when `stdin` was a closed fd.
|
||||
- Improved `--debug` output formatting.
|
||||
|
||||
## [1.0.3](https://github.com/httpie/cli/compare/1.0.2...1.0.3) (2019-08-26)
|
||||
## [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
|
||||
@ -196,15 +188,15 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
Reported by Raul Onitza and Giulio Comi.
|
||||
|
||||
## [1.0.2](https://github.com/httpie/cli/compare/1.0.1...1.0.2) (2018-11-14)
|
||||
## [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/cli/compare/1.0.0...1.0.1) (2018-11-14)
|
||||
## [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/cli/compare/0.9.9...1.0.0) (2018-11-02)
|
||||
## [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`
|
||||
@ -215,11 +207,11 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- Fixed default headers being incorrectly case-sensitive.
|
||||
- Removed Python 2.6 support.
|
||||
|
||||
## [0.9.9](https://github.com/httpie/cli/compare/0.9.8...0.9.9) (2016-12-08)
|
||||
## [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/cli/compare/0.9.6...0.9.8) (2016-12-08)
|
||||
## [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.
|
||||
@ -228,7 +220,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- Improved `CTRL-C` interrupt handling.
|
||||
- Added the standard exit status code `130` for keyboard interrupts.
|
||||
|
||||
## [0.9.6](https://github.com/httpie/cli/compare/0.9.4...0.9.6) (2016-08-13)
|
||||
## [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
|
||||
@ -247,7 +239,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- Changed the pre-processing of request HTTP headers so that any leading
|
||||
and trailing whitespace is removed.
|
||||
|
||||
## [0.9.4](https://github.com/httpie/cli/compare/0.9.3...0.9.4) (2016-07-01)
|
||||
## [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
|
||||
@ -271,7 +263,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- 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/cli/compare/0.9.2...0.9.3) (2016-01-01)
|
||||
## [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)
|
||||
@ -281,19 +273,19 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- Fixed colors and formatting on Windows
|
||||
- Fixed `--auth` prompt on Windows
|
||||
|
||||
## [0.9.2](https://github.com/httpie/cli/compare/0.9.1...0.9.2) (2015-02-24)
|
||||
## [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/cli/compare/0.9.0...0.9.1) (2015-02-07)
|
||||
## [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/cli/compare/0.8.0...0.9.0) (2015-01-31)
|
||||
## [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
|
||||
@ -312,7 +304,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- Fixed `--output=/dev/null` on Linux
|
||||
- Miscellaneous bugfixes
|
||||
|
||||
## [0.8.0](https://github.com/httpie/cli/compare/0.7.1...0.8.0) (2014-01-25)
|
||||
## [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
|
||||
@ -320,7 +312,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- 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/cli/compare/0.6.0...0.7.1) (2013-09-24)
|
||||
## [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
|
||||
@ -328,27 +320,27 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- Improved `Content-Disposition` parsing for `--download` mode
|
||||
- Update to Requests 2.0.0
|
||||
|
||||
## [0.6.0](https://github.com/httpie/cli/compare/0.5.1...0.6.0) (2013-06-03)
|
||||
## [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/cli/compare/0.5.0...0.5.1) (2013-05-13)
|
||||
## [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/cli/compare/0.4.1...0.5.0) (2013-04-27)
|
||||
## [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/cli/compare/0.4.0...0.4.1) (2013-02-26)
|
||||
## [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/cli/compare/0.3.0...0.4.0) (2013-02-22)
|
||||
## [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
|
||||
@ -357,7 +349,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- Mutually exclusive arguments can be specified multiple times. The
|
||||
last value is used
|
||||
|
||||
## [0.3.0](https://github.com/httpie/cli/compare/0.2.7...0.3.0) (2012-09-21)
|
||||
## [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
|
||||
@ -372,7 +364,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
(`--pretty=all`, `--pretty=colors` and `--pretty=format`)
|
||||
`--ugly` has bee removed in favor of `--pretty=none`
|
||||
|
||||
## [0.2.7](https://github.com/httpie/cli/compare/0.2.5...0.2.7) (2012-08-07)
|
||||
## [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
|
||||
@ -389,7 +381,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- Fixed printing of `multipart/form-data` requests
|
||||
- Renamed `--traceback` to `--debug`
|
||||
|
||||
## [0.2.6](https://github.com/httpie/cli/compare/0.2.5...0.2.6) (2012-07-26)
|
||||
## [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`)
|
||||
@ -404,7 +396,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- Added query string parameters (`param==value`)
|
||||
- Added support for terminal colors under Windows
|
||||
|
||||
## [0.2.5](https://github.com/httpie/cli/compare/0.2.2...0.2.5) (2012-07-17)
|
||||
## [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
|
||||
@ -415,20 +407,20 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
`--verbose`
|
||||
- Fixed Content-Type for requests with no data
|
||||
|
||||
## [0.2.2](https://github.com/httpie/cli/compare/0.2.1...0.2.2) (2012-06-24)
|
||||
## [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/cli/compare/0.2.0...0.2.1) (2012-06-13)
|
||||
## [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/cli/compare/0.1.6...0.2.0) (2012-04-25)
|
||||
## [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
|
||||
@ -440,18 +432,18 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- Added support for field name escaping
|
||||
- Many bug fixes
|
||||
|
||||
## [0.1.6](https://github.com/httpie/cli/compare/0.1.5...0.1.6) (2012-03-04)
|
||||
## [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/cli/compare/0.1.4...0.1.5) (2012-03-04)
|
||||
## [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/cli/compare/b966efa...0.1.4) (2012-02-28)
|
||||
## [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/cli/commit/b966efa) (2012-02-25)
|
||||
## [0.1.0](https://github.com/httpie/httpie/commit/b966efa) (2012-02-25)
|
||||
|
||||
- Initial public release
|
||||
|
@ -19,7 +19,7 @@ $ http --debug <COMPLETE ARGUMENT LIST THAT TRIGGERS THE ERROR>
|
||||
|
||||
## 2. Contributing Code and Docs
|
||||
|
||||
Before working on a new feature or a bug, please browse [existing issues](https://github.com/httpie/cli/issues)
|
||||
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 HTTPie’s behaviour or interface, it's a good idea to
|
||||
@ -38,13 +38,13 @@ 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/cli/blob/master/CHANGELOG.md) entry for your changes.
|
||||
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/cli> and fork the project repository.
|
||||
Go to <https://github.com/httpie/httpie> and fork the project repository.
|
||||
|
||||
```bash
|
||||
# Clone your fork
|
||||
@ -59,7 +59,7 @@ $ git checkout -b my_topical_branch
|
||||
|
||||
#### Setup
|
||||
|
||||
The [Makefile](https://github.com/httpie/cli/blob/master/Makefile) contains a bunch of tasks to get you started.
|
||||
The [Makefile](https://github.com/httpie/httpie/blob/master/Makefile) contains a bunch of tasks to get you started.
|
||||
You can run `$ make` to see all the available tasks.
|
||||
|
||||
To get started, run the command below, which:
|
||||
@ -112,7 +112,7 @@ and that `make pycodestyle` passes.
|
||||
|
||||
Please add tests for any new features and bug fixes.
|
||||
|
||||
When you open a Pull Request, [GitHub Actions](https://github.com/httpie/cli/actions) will automatically run HTTPie’s [test suite](https://github.com/httpie/cli/tree/master/tests) against your code, so please make sure all checks pass.
|
||||
When you open a Pull Request, [GitHub Actions](https://github.com/httpie/httpie/actions) will automatically run HTTPie’s [test suite](https://github.com/httpie/httpie/tree/master/tests) against your code, so please make sure all checks pass.
|
||||
|
||||
#### Running tests locally
|
||||
|
||||
@ -144,7 +144,7 @@ $ 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/cli/blob/master/Makefile) for additional development utilities.
|
||||
See [Makefile](https://github.com/httpie/httpie/blob/master/Makefile) for additional development utilities.
|
||||
|
||||
#### Running benchmarks
|
||||
|
||||
@ -154,7 +154,7 @@ with the master branch of your repository (or a fresh checkout of HTTPie master,
|
||||
`--fresh`) and report the results back.
|
||||
|
||||
```bash
|
||||
$ python extras/profiling/run.py
|
||||
$ python extras/benchmarks/run.py
|
||||
```
|
||||
|
||||
The benchmarks can also be run on the CI. Since it is a long process, it requires manual
|
||||
@ -209,4 +209,4 @@ $ python -m pytest
|
||||
|
||||
______________________________________________________________________
|
||||
|
||||
Finally, feel free to add yourself to [AUTHORS](https://github.com/httpie/cli/blob/master/AUTHORS.md)!
|
||||
Finally, feel free to add yourself to [AUTHORS](https://github.com/httpie/httpie/blob/master/AUTHORS.md)!
|
||||
|
@ -4,5 +4,5 @@ include CHANGELOG.md
|
||||
include AUTHORS.md
|
||||
include docs/README.md
|
||||
|
||||
# <https://github.com/httpie/cli/issues/182>
|
||||
# <https://github.com/httpie/httpie/issues/182>
|
||||
recursive-include tests/ *
|
||||
|
10
Makefile
10
Makefile
@ -34,7 +34,7 @@ default: list-tasks
|
||||
list-tasks:
|
||||
@echo Available tasks:
|
||||
@echo ----------------
|
||||
@$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | grep -E -v -e '^[^[:alnum:]]' -e '^$@$$'
|
||||
@$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$'
|
||||
@echo
|
||||
|
||||
|
||||
@ -231,15 +231,15 @@ brew-test:
|
||||
brew audit --strict httpie
|
||||
|
||||
###############################################################################
|
||||
# Generated content
|
||||
# Regeneration
|
||||
###############################################################################
|
||||
|
||||
content: man installation-docs
|
||||
regen-all: regen-man-pages regen-install-methods
|
||||
|
||||
man: install
|
||||
regen-man-pages: install
|
||||
@echo $(H1)Regenerate man pages$(H1END)
|
||||
$(VENV_PYTHON) extras/scripts/generate_man_pages.py
|
||||
|
||||
installation-docs:
|
||||
regen-install-methods:
|
||||
@echo $(H1)Updating installation instructions in the docs$(H1END)
|
||||
$(VENV_PYTHON) docs/installation/generate.py
|
||||
|
63
README.md
63
README.md
@ -1,31 +1,10 @@
|
||||
<h2 align="center">
|
||||
<a href="https://httpie.io" target="blank_">
|
||||
<img height="100" alt="HTTPie" src="https://raw.githubusercontent.com/httpie/cli/master/docs/httpie-logo.svg" />
|
||||
</a>
|
||||
<br>
|
||||
HTTPie CLI: human-friendly HTTP client for the API era
|
||||
</h2>
|
||||
<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/>
|
||||
|
||||
<div align="center">
|
||||
|
||||
[![HTTPie for Desktop](https://img.shields.io/static/v1?label=HTTPie&message=Desktop&color=4B78E6)](https://httpie.io/product)
|
||||
[![](https://img.shields.io/static/v1?label=HTTPie&message=Web%20%26%20Mobile&color=73DC8C)](https://httpie.io/app)
|
||||
[![](https://img.shields.io/static/v1?label=HTTPie&message=CLI&color=FA9BFA)](https://httpie.io/cli)
|
||||
[![Twitter](https://img.shields.io/twitter/follow/httpie?style=flat&color=%234B78E6&logoColor=%234B78E6)](https://twitter.com/httpie)
|
||||
[![Chat](https://img.shields.io/discord/725351238698270761?style=flat&label=Chat%20on%20Discord&color=%23FA9BFA)](https://httpie.io/discord)
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div align="center">
|
||||
|
||||
[![Docs](https://img.shields.io/badge/stable%20docs-httpie.io%2Fdocs%2Fcli-brightgreen?style=flat&color=%2373DC8C&label=Docs)](https://httpie.org/docs/cli)
|
||||
[![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/actions/workflow/status/httpie/cli/tests.yml?branch=master&color=%23FA9BFA&label=Build)](https://github.com/httpie/cli/actions)
|
||||
[![Coverage](https://img.shields.io/codecov/c/github/httpie/cli?style=flat&label=Coverage&color=%2373DC8C)](https://codecov.io/gh/httpie/cli)
|
||||
[![PyPi downloads](https://img.shields.io/pepy/dt/httpie?style=flat&label=Downloads%20from%20PyPi%20only&color=4B78E6)](https://www.pepy.tech/projects/httpie)
|
||||
|
||||
</div>
|
||||
# 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.
|
||||
@ -33,14 +12,14 @@ HTTPie is designed for testing, debugging, and generally interacting with APIs &
|
||||
The `http` & `https` commands allow for creating and sending arbitrary HTTP requests.
|
||||
They use simple and natural syntax and provide formatted and colorized output.
|
||||
|
||||
<div align="center">
|
||||
|
||||
<img src="https://raw.githubusercontent.com/httpie/cli/master/docs/httpie-animation.gif" alt="HTTPie in action" width="100%"/>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
[![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%"/>
|
||||
|
||||
|
||||
## We lost 54k GitHub stars
|
||||
@ -74,25 +53,25 @@ Please note we recently accidentally made this repo private for a moment, and Gi
|
||||
Hello World:
|
||||
|
||||
```bash
|
||||
https httpie.io/hello
|
||||
$ 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
|
||||
$ 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
|
||||
$ 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/cli/issues/83) with [authentication](https://httpie.io/docs#authentication):
|
||||
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/cli/issues/83/comments body='HTTPie is awesome! :heart:'
|
||||
$ 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)
|
||||
@ -103,11 +82,11 @@ http -a USERNAME POST https://api.github.com/repos/httpie/cli/issues/83/comments
|
||||
- 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/cli/issues) for bug reports and feature requests.
|
||||
- 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/cli/issues) and [Pull Requests](https://github.com/httpie/cli/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/cli/issues) using one of the templates provided.
|
||||
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/cli/blob/master/CONTRIBUTING.md)
|
||||
[See contribution guide →](https://github.com/httpie/httpie/blob/master/CONTRIBUTING.md)
|
||||
|
186
docs/README.md
186
docs/README.md
@ -19,7 +19,7 @@ This documentation is best viewed at [httpie.io/docs](https://httpie.org/docs).
|
||||
You can select your corresponding HTTPie version as well as run examples directly from the browser using a [termible.io](https://termible.io?utm_source=httpie-readme) embedded terminal.
|
||||
|
||||
If you are reading this on GitHub, then this text covers the current *development* version.
|
||||
You are invited to submit fixes and improvements to the docs by editing [this file](https://github.com/httpie/cli/blob/master/docs/README.md).
|
||||
You are invited to submit fixes and improvements to the docs by editing [this file](https://github.com/httpie/httpie/blob/master/docs/README.md).
|
||||
|
||||
</div>
|
||||
|
||||
@ -126,66 +126,6 @@ $ choco upgrade httpie
|
||||
|
||||
### Linux
|
||||
|
||||
#### Debian and Ubuntu
|
||||
|
||||
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.
|
||||
|
||||
```bash
|
||||
# Install httpie
|
||||
$ curl -SsL https://packages.httpie.io/deb/KEY.gpg | sudo gpg --dearmor -o /usr/share/keyrings/httpie.gpg
|
||||
$ sudo echo "deb [arch=amd64 signed-by=/usr/share/keyrings/httpie.gpg] https://packages.httpie.io/deb ./" > /etc/apt/sources.list.d/httpie.list
|
||||
$ sudo apt update
|
||||
$ sudo apt install httpie
|
||||
```
|
||||
|
||||
```bash
|
||||
# Upgrade httpie
|
||||
$ sudo apt update && sudo apt upgrade httpie
|
||||
```
|
||||
|
||||
#### Fedora
|
||||
|
||||
```bash
|
||||
# Install httpie
|
||||
$ dnf install httpie
|
||||
```
|
||||
|
||||
```bash
|
||||
# Upgrade httpie
|
||||
$ dnf upgrade httpie
|
||||
```
|
||||
|
||||
#### CentOS and RHEL
|
||||
|
||||
Also works for other RHEL-derived distributions like ClearOS, Oracle Linux, etc.
|
||||
|
||||
```bash
|
||||
# Install httpie
|
||||
$ yum install epel-release
|
||||
$ yum install httpie
|
||||
```
|
||||
|
||||
```bash
|
||||
# Upgrade httpie
|
||||
$ yum upgrade httpie
|
||||
```
|
||||
|
||||
#### Single binary executables
|
||||
|
||||
Get the standalone HTTPie Linux executables when you don't want to go through the full installation process.
|
||||
|
||||
```bash
|
||||
# Install httpie
|
||||
$ https --download packages.httpie.io/binaries/linux/http-latest -o http
|
||||
$ ln -ls ./http ./https
|
||||
$ chmod +x ./http ./https
|
||||
```
|
||||
|
||||
```bash
|
||||
# Upgrade httpie
|
||||
$ https --download packages.httpie.io/binaries/linux/http-latest -o http
|
||||
```
|
||||
|
||||
#### Snapcraft (Linux)
|
||||
|
||||
To install [Snapcraft](https://snapcraft.io/), see [its installation](https://snapcraft.io/docs/installing-snapd).
|
||||
@ -216,6 +156,51 @@ $ brew update
|
||||
$ brew upgrade httpie
|
||||
```
|
||||
|
||||
#### Debian and Ubuntu
|
||||
|
||||
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.
|
||||
|
||||
```bash
|
||||
# Install httpie
|
||||
$ curl -SsL https://packages.httpie.io/deb/KEY.gpg | apt-key add -
|
||||
$ curl -SsL -o /etc/apt/sources.list.d/httpie.list https://packages.httpie.io/deb/httpie.list
|
||||
$ apt update
|
||||
$ apt install httpie
|
||||
```
|
||||
|
||||
```bash
|
||||
# Upgrade httpie
|
||||
$ apt update
|
||||
$ apt upgrade httpie
|
||||
```
|
||||
|
||||
#### Fedora
|
||||
|
||||
```bash
|
||||
# Install httpie
|
||||
$ dnf install httpie
|
||||
```
|
||||
|
||||
```bash
|
||||
# Upgrade httpie
|
||||
$ dnf upgrade httpie
|
||||
```
|
||||
|
||||
#### CentOS and RHEL
|
||||
|
||||
Also works for other RHEL-derived distributions like ClearOS, Oracle Linux, etc.
|
||||
|
||||
```bash
|
||||
# Install httpie
|
||||
$ yum install epel-release
|
||||
$ yum install httpie
|
||||
```
|
||||
|
||||
```bash
|
||||
# Upgrade httpie
|
||||
$ yum upgrade httpie
|
||||
```
|
||||
|
||||
#### Arch Linux
|
||||
|
||||
Also works for other Arch-derived distributions like ArcoLinux, EndeavourOS, Artix Linux, etc.
|
||||
@ -230,6 +215,21 @@ $ pacman -Syu httpie
|
||||
$ pacman -Syu
|
||||
```
|
||||
|
||||
#### Single binary executables
|
||||
|
||||
Get the standalone HTTPie Linux executables when you don't want to go through the full installation process
|
||||
|
||||
```bash
|
||||
# Install httpie
|
||||
$ https --download packages.httpie.io/binaries/linux/http-latest -o http
|
||||
$ chmod +x ./http
|
||||
```
|
||||
|
||||
```bash
|
||||
# Upgrade httpie
|
||||
$ https --download packages.httpie.io/binaries/linux/http-latest -o http
|
||||
```
|
||||
|
||||
### FreeBSD
|
||||
|
||||
#### FreshPorts
|
||||
@ -250,39 +250,36 @@ $ pkg upgrade www/py-httpie
|
||||
|
||||
### Unstable version
|
||||
|
||||
If you want to try out the latest version of HTTPie that hasn't been officially released yet, you can install the development or unstable version directly from the master branch on GitHub. However, keep in mind that the development version is a work in progress and may not be as reliable as the stable version.
|
||||
You can also install the latest unreleased development version directly from the `master` branch on GitHub.
|
||||
It is a work-in-progress of a future stable release so the experience might be not as smooth.
|
||||
|
||||
You can use the following command to install the development version of HTTPie on Linux, macOS, Windows, or FreeBSD operating systems. With this command, the code present in the `master` branch is downloaded and installed using `pip`.
|
||||
You can install it on Linux, macOS, Windows, or FreeBSD with `pip`:
|
||||
|
||||
```bash
|
||||
$ python -m pip install --upgrade https://github.com/httpie/cli/archive/master.tar.gz
|
||||
$ python -m pip install --upgrade https://github.com/httpie/httpie/archive/master.tar.gz
|
||||
```
|
||||
|
||||
There are other ways to install the development version of HTTPie on macOS and Linux.
|
||||
|
||||
You can install it using Homebrew by running the following commands:
|
||||
Or on macOS, and Linux, with Homebrew:
|
||||
|
||||
```bash
|
||||
$ brew uninstall --force httpie
|
||||
$ brew install --HEAD httpie
|
||||
```
|
||||
|
||||
You can install it using Snapcraft by running the following commands:
|
||||
And even on macOS, and Linux, with Snapcraft:
|
||||
|
||||
```bash
|
||||
$ snap remove httpie
|
||||
$ snap install httpie --edge
|
||||
```
|
||||
|
||||
To verify the installation, you can compare the [version identifier on GitHub](https://github.com/httpie/cli/blob/master/httpie/__init__.py#L6) with the one available on your machine. You can check the version of HTTPie on your machine by using the command `http --version`.
|
||||
Verify that now you have the [current development version identifier](https://github.com/httpie/httpie/blob/master/httpie/__init__.py#L6) with the `.dev0` suffix, for example:
|
||||
|
||||
```bash
|
||||
$ http --version
|
||||
# 3.X.X.dev0
|
||||
```
|
||||
|
||||
Note that on your machine, the version name will have the `.dev0` suffix.
|
||||
|
||||
## Usage
|
||||
|
||||
Hello World:
|
||||
@ -325,10 +322,10 @@ Build and print a request without sending it using [offline mode](#offline-mode)
|
||||
$ 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/cli/issues/83) with [authentication](#authentication):
|
||||
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](#authentication):
|
||||
|
||||
```bash
|
||||
$ http -a USERNAME POST https://api.github.com/repos/httpie/cli/issues/83/comments body='HTTPie is awesome! :heart:'
|
||||
$ http -a USERNAME POST https://api.github.com/repos/httpie/httpie/issues/83/comments body='HTTPie is awesome! :heart:'
|
||||
```
|
||||
|
||||
Upload a file using [redirected input](#redirected-input):
|
||||
@ -915,8 +912,6 @@ http --offline --print=B pie.dev/post \
|
||||
]
|
||||
```
|
||||
|
||||
Sending scalar JSON types (a single `null`, `true`, `false`, string or number) as the top-level object is impossible using the key/value syntax. But you can still pass it via [`--raw='<value>'`](#raw-request-body).
|
||||
|
||||
##### Escaping behavior
|
||||
|
||||
Nested JSON syntax uses the same [escaping rules](#escaping-rules) as
|
||||
@ -1176,11 +1171,11 @@ User-Agent: HTTPie/<version>
|
||||
Host: <taken-from-URL>
|
||||
```
|
||||
|
||||
All of these can be overwritten or unset (see below).
|
||||
Any of these can be overwritten and some of them unset (see below).
|
||||
|
||||
### Reading headers from a file
|
||||
|
||||
You can read headers from a file by using the `:@` operator. This would also effectively strip the newlines from the end. See [file based separators](#file-based-separators) for more examples.
|
||||
You can read headers from a file by using the `:@` operator. This would also effectively strip the newlines from the end. See [#file-based-separators] for more examples.
|
||||
|
||||
```bash
|
||||
$ http pie.dev/headers X-Data:@files/text.txt
|
||||
@ -1458,8 +1453,7 @@ $ http --proxy=http:http://user:pass@10.10.1.10:3128 example.org
|
||||
|
||||
### Environment variables
|
||||
|
||||
You can also configure proxies by environment variables `ALL_PROXY`, `HTTP_PROXY` and `HTTPS_PROXY`, and the underlying
|
||||
[Requests library](https://requests.readthedocs.io/en/latest/) will pick them up.
|
||||
You can also configure proxies by environment variables `ALL_PROXY`, `HTTP_PROXY` and `HTTPS_PROXY`, and the underlying [Requests library](https://python-requests.org/) will pick them up.
|
||||
If you want to disable proxies configured through the environment variables for certain hosts, you can specify them in `NO_PROXY`.
|
||||
|
||||
In your `~/.bash_profile`:
|
||||
@ -1754,7 +1748,7 @@ $ http pie.dev/post <<<'{"name": "John"}'
|
||||
You can even pipe web services together using HTTPie:
|
||||
|
||||
```bash
|
||||
$ http GET https://api.github.com/repos/httpie/cli | http POST pie.dev/post
|
||||
$ http GET https://api.github.com/repos/httpie/httpie | http POST pie.dev/post
|
||||
```
|
||||
|
||||
You can use `cat` to enter multiline data on the terminal:
|
||||
@ -2002,7 +1996,7 @@ HTTPie features a download mode in which it acts similarly to `wget`.
|
||||
When enabled using the `--download, -d` flag, response headers are printed to the terminal (`stderr`), and a progress bar is shown while the response body is being saved to a file.
|
||||
|
||||
```bash
|
||||
$ http --download https://github.com/httpie/cli/archive/master.tar.gz
|
||||
$ http --download https://github.com/httpie/httpie/archive/master.tar.gz
|
||||
```
|
||||
|
||||
```http
|
||||
@ -2031,7 +2025,7 @@ To prevent data loss by overwriting, HTTPie adds a unique numerical suffix to th
|
||||
You can also redirect the response body to another program while the response headers and progress are still shown in the terminal:
|
||||
|
||||
```bash
|
||||
$ http -d https://github.com/httpie/cli/archive/master.tar.gz | tar zxf -
|
||||
$ http -d https://github.com/httpie/httpie/archive/master.tar.gz | tar zxf -
|
||||
```
|
||||
|
||||
### Resuming downloads
|
||||
@ -2313,7 +2307,7 @@ These flags are available for both `sessions upgrade` and `sessions upgrade-all`
|
||||
|
||||
| Option | Description |
|
||||
|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--bind-cookies` | Bind all previously [unbound cookies](#host-based-cookie-policy) to the session’s host ([context](https://github.com/httpie/cli/security/advisories/GHSA-9w4w-cpc8-h2fq)). |
|
||||
| `--bind-cookies` | Bind all previously [unbound cookies](#host-based-cookie-policy) to the session’s host ([context](https://github.com/httpie/httpie/security/advisories/GHSA-9w4w-cpc8-h2fq)). |
|
||||
|
||||
|
||||
## Config
|
||||
@ -2400,13 +2394,16 @@ fi
|
||||
The default behavior of automatically reading `stdin` is typically not desirable during non-interactive invocations.
|
||||
You most likely want to use the `--ignore-stdin` option to disable it.
|
||||
|
||||
It's important to note that without the `--ignore-stdin` option, HTTPie may appear to have stopped working (hang). This happens because, in situations where HTTPie is invoked outside of an interactive session, such as from a cron job, `stdin` is not connected to a terminal. This means that the rules for [redirected input](#redirected-input) will be followed. When `stdin` is redirected, HTTPie assumes that the input will contain the request body, and it waits for the input to be provided. But, since there is neither any input data nor an end-of-file (`EOF`) signal, HTTPie gets stuck. To avoid this problem, the `--ignore-stdin` flag should be used in scripts, unless data is being piped to HTTPie.
|
||||
It is a common *gotcha* that without this option HTTPie seemingly hangs.
|
||||
What happens is that when HTTPie is invoked, for example, from a cron job, `stdin` is not connected to a terminal.
|
||||
Therefore, the rules for [redirected input](#redirected-input) apply, i.e. HTTPie starts to read it expecting that the request body will be passed through.
|
||||
And since there’s neither data nor `EOF`, it will get stuck. So unless you’re piping some data to HTTPie, the `--ignore-stdin` flag should be used in scripts.
|
||||
|
||||
To prevent your program from becoming unresponsive when the server fails to respond, it's a good idea to use the `--timeout` option to set a connection timeout limit.
|
||||
Also, it might be good to set a connection `--timeout` limit to prevent your program from hanging if the server never responds.
|
||||
|
||||
## Plugin manager
|
||||
|
||||
HTTPie offers extensibility through a [plugin API](https://github.com/httpie/cli/blob/master/httpie/plugins/base.py),
|
||||
HTTPie offers extensibility through a [plugin API](https://github.com/httpie/httpie/blob/master/httpie/plugins/base.py),
|
||||
and there are dozens of plugins available to try!
|
||||
They add things like new authentication methods ([akamai/httpie-edgegrid](https://github.com/akamai/httpie-edgegrid)),
|
||||
transport mechanisms ([httpie/httpie-unixsocket](https://github.com/httpie/httpie-unixsocket)),
|
||||
@ -2546,7 +2543,7 @@ All changes are recorded in the [change log](#change-log).
|
||||
|
||||
HTTPie has the following community channels:
|
||||
|
||||
- [GitHub Issues](https://github.com/httpie/cli/issues) for bug reports and feature requests
|
||||
- [GitHub Issues](https://github.com/httpie/httpie/issues) for bug reports and feature requests
|
||||
- [Discord server](https://httpie.io/discord) to ask questions, discuss features, and for general API development discussion
|
||||
- [StackOverflow](https://stackoverflow.com) to ask questions (make sure to use the [httpie](https://stackoverflow.com/questions/tagged/httpie) tag)
|
||||
|
||||
@ -2556,7 +2553,7 @@ HTTPie has the following community channels:
|
||||
|
||||
Under the hood, HTTPie uses these two amazing libraries:
|
||||
|
||||
- [Requests](https://requests.readthedocs.io/en/latest/) — Python HTTP library for humans
|
||||
- [Requests](https://python-requests.org) — Python HTTP library for humans
|
||||
- [Pygments](https://pygments.org/) — Python syntax highlighter
|
||||
|
||||
#### HTTPie friends
|
||||
@ -2577,25 +2574,24 @@ Helpers to convert from other client tools:
|
||||
|
||||
### Contributing
|
||||
|
||||
See [CONTRIBUTING](https://github.com/httpie/cli/blob/master/CONTRIBUTING.md).
|
||||
See [CONTRIBUTING](https://github.com/httpie/httpie/blob/master/CONTRIBUTING.md).
|
||||
|
||||
### Security policy
|
||||
|
||||
See [github.com/httpie/cli/security/policy](https://github.com/httpie/cli/security/policy).
|
||||
See [github.com/httpie/httpie/security/policy](https://github.com/httpie/httpie/security/policy).
|
||||
|
||||
### Change log
|
||||
|
||||
See [CHANGELOG](https://github.com/httpie/cli/blob/master/CHANGELOG.md).
|
||||
See [CHANGELOG](https://github.com/httpie/httpie/blob/master/CHANGELOG.md).
|
||||
|
||||
### Artwork
|
||||
|
||||
- [README Animation](https://github.com/httpie/cli/blob/master/docs/httpie-animation.gif) by [Allen Smith](https://github.com/loranallensmith).
|
||||
- [README Animation](https://github.com/httpie/httpie/blob/master/docs/httpie-animation.gif) by [Allen Smith](https://github.com/loranallensmith).
|
||||
|
||||
### Licence
|
||||
|
||||
BSD-3-Clause: [LICENSE](https://github.com/httpie/cli/blob/master/LICENSE).
|
||||
BSD-3-Clause: [LICENSE](https://github.com/httpie/httpie/blob/master/LICENSE).
|
||||
|
||||
### Authors
|
||||
|
||||
[Jakub Roztocil](https://roztocil.co) ([@jakubroztocil](https://twitter.com/jakubroztocil)) created HTTPie and [these fine people](https://github.com/httpie/cli/blob/master/AUTHORS.md) have contributed.
|
||||
|
||||
[Jakub Roztocil](https://roztocil.co) ([@jakubroztocil](https://twitter.com/jakubroztocil)) created HTTPie and [these fine people](https://github.com/httpie/httpie/blob/master/AUTHORS.md) have contributed.
|
||||
|
@ -1,3 +1,3 @@
|
||||
Here we maintain a database of contributors, from which we generate credits on release blog posts and social media.
|
||||
Here we maintain a database of contributors, from which we generate credits on release blog posts and social medias.
|
||||
|
||||
For the HTTPie blog see: <https://httpie.io/blog>.
|
||||
|
@ -55,7 +55,7 @@ def build_docs_structure(database: Database):
|
||||
tree = database[KEY_DOC_STRUCTURE]
|
||||
structure = []
|
||||
for platform, tools_ids in tree.items():
|
||||
assert platform.isalnum(), f'{platform=} must be alphanumeric for generated links to work'
|
||||
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
|
||||
|
@ -37,13 +37,13 @@ tools:
|
||||
package: https://packages.debian.org/sid/web/httpie
|
||||
commands:
|
||||
install:
|
||||
- curl -SsL https://packages.httpie.io/deb/KEY.gpg | sudo gpg --dearmor -o /usr/share/keyrings/httpie.gpg
|
||||
# - curl -SsL -o /etc/apt/sources.list.d/httpie.list https://packages.httpie.io/deb/httpie.list
|
||||
- sudo echo "deb [arch=amd64 signed-by=/usr/share/keyrings/httpie.gpg] https://packages.httpie.io/deb ./" > /etc/apt/sources.list.d/httpie.list
|
||||
- sudo apt update
|
||||
- sudo apt install httpie
|
||||
- curl -SsL https://packages.httpie.io/deb/KEY.gpg | apt-key add -
|
||||
- curl -SsL -o /etc/apt/sources.list.d/httpie.list https://packages.httpie.io/deb/httpie.list
|
||||
- apt update
|
||||
- apt install httpie
|
||||
upgrade:
|
||||
- sudo apt update && sudo apt upgrade httpie
|
||||
- apt update
|
||||
- apt upgrade httpie
|
||||
|
||||
brew-mac:
|
||||
title: Homebrew
|
||||
|
@ -3,7 +3,7 @@
|
||||
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/cli/issues/).
|
||||
- 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
|
||||
@ -25,7 +25,7 @@ The overall release process starts simple:
|
||||
|
||||
## Company-specific tasks
|
||||
|
||||
- Blank the `master_and_released_docs_differ_after` value in [config.json](https://github.com/httpie/cli/blob/master/docs/config.json).
|
||||
- Blank the `master_and_released_docs_differ_after` value in [config.json](https://github.com/httpie/httpie/blob/master/docs/config.json).
|
||||
- Update the [contributors list](../contributors).
|
||||
- Update the HTTPie version bundled into [Termible](https://termible.io/) ([example](https://github.com/httpie/termible/pull/1)).
|
||||
|
||||
@ -44,4 +44,4 @@ A more complete state of deployment can be found on [repology](https://repology.
|
||||
| [Snapcraft](snapcraft/) | **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/cli/issues/).
|
||||
: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/).
|
||||
|
@ -13,7 +13,7 @@ We will discuss setting up the environment, installing development tools, instal
|
||||
|
||||
## Overall process
|
||||
|
||||
The brew deployment is completely automated, and only requires a trigger to [`Release on Homebrew`](https://github.com/httpie/cli/actions/workflows/release-brew.yml) action
|
||||
The brew deployment is completely automated, and only requires a trigger to [`Release on Homebrew`](https://github.com/httpie/httpie/actions/workflows/release-brew.yml) action
|
||||
from the release manager.
|
||||
|
||||
If it is needed to be done manually, the following command can be used:
|
||||
@ -26,6 +26,6 @@ which will bump the formula, and create a PR against the package index.
|
||||
|
||||
## Hacking
|
||||
|
||||
Make your changes, test the formula through the [`Test Brew Package`](https://github.com/httpie/cli/actions/workflows/test-package-mac-brew.yml) action
|
||||
Make your changes, test the formula through the [`Test Brew Package`](https://github.com/httpie/httpie/actions/workflows/test-package-mac-brew.yml) action
|
||||
and then finally submit your patch to [`homebrew-core`](https://github.com/Homebrew/homebrew-core`)
|
||||
|
||||
|
@ -6,7 +6,7 @@ class Httpie < Formula
|
||||
url "https://files.pythonhosted.org/packages/32/85/bb095699be20cc98731261cb80884e9458178f8fef2a38273530ce77c0a5/httpie-3.1.0.tar.gz"
|
||||
sha256 "2e4a2040b84a912e65c01fb34f7aafe88cad2a3af2da8c685ca65080f376feda"
|
||||
license "BSD-3-Clause"
|
||||
head "https://github.com/httpie/cli.git", branch: "master"
|
||||
head "https://github.com/httpie/httpie.git", branch: "master"
|
||||
|
||||
bottle do
|
||||
sha256 cellar: :any_skip_relocation, arm64_monterey: "9bb6e8c1ef5ba8b019ddedd7e908dd2174da695351aa9a238dfb28b0f57ef005"
|
||||
|
@ -7,7 +7,7 @@ pkgname=httpie
|
||||
pkgver=2.6.0
|
||||
pkgrel=1
|
||||
pkgdesc="human-friendly CLI HTTP client for the API era"
|
||||
url="https://github.com/httpie/cli"
|
||||
url="https://github.com/httpie/httpie"
|
||||
depends=('python-defusedxml'
|
||||
'python-pygments'
|
||||
'python-pysocks'
|
||||
@ -22,7 +22,7 @@ conflicts=(python-httpie)
|
||||
replaces=(python-httpie python2-httpie)
|
||||
license=('BSD')
|
||||
arch=('any')
|
||||
source=($pkgname-$pkgver.tar.gz::"https://github.com/httpie/cli/archive/$pkgver.tar.gz")
|
||||
source=($pkgname-$pkgver.tar.gz::"https://github.com/httpie/httpie/archive/$pkgver.tar.gz")
|
||||
sha256sums=('3bcd9a8cb2b11299da12d3af36c095c6d4b665e41c395898a07f1ae4d99fc14a')
|
||||
|
||||
build() {
|
||||
|
@ -17,7 +17,7 @@ command (due to the underlying `httpie cli plugins` interface) explicitly depend
|
||||
|
||||
## Overall process
|
||||
|
||||
The [`Release as Standalone Linux Binary`](https://github.com/httpie/cli/actions/workflows/release-linux-standalone.yml) will be automatically
|
||||
The [`Release as Standalone Linux Binary`](https://github.com/httpie/httpie/actions/workflows/release-linux-standalone.yml) will be automatically
|
||||
triggered when a new release is created, and it will submit the `.deb` package as a release asset.
|
||||
|
||||
For making that asset available for all debian users, the release manager needs to go to the [`httpie/debian.httpie.io`](https://github.com/httpie/debian.httpie.io) repo
|
||||
|
@ -15,7 +15,7 @@ The current maintainer is [Miro Hrončok](https://github.com/hroncok).
|
||||
|
||||
## Overall process
|
||||
|
||||
We added the [.packit.yaml](https://github.com/httpie/cli/blob/master/.packit.yaml) local file.
|
||||
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.
|
||||
|
@ -5,7 +5,7 @@ Summary: A Curl-like tool for humans
|
||||
|
||||
License: BSD
|
||||
URL: https://httpie.org/
|
||||
Source0: https://github.com/httpie/cli/archive/%{version}/%{name}-%{version}.tar.gz
|
||||
Source0: https://github.com/httpie/httpie/archive/%{version}/%{name}-%{version}.tar.gz
|
||||
|
||||
BuildArch: noarch
|
||||
|
||||
|
@ -19,7 +19,7 @@ Open a pull request to update the [downstream file](https://github.com/macports/
|
||||
|
||||
```bash
|
||||
# Download the archive
|
||||
$ wget https://api.github.com/repos/httpie/cli/tarball/2.5.0
|
||||
$ wget https://api.github.com/repos/httpie/httpie/tarball/2.5.0
|
||||
|
||||
# Size
|
||||
$ stat --printf="%s\n" 2.5.0
|
||||
|
@ -13,7 +13,7 @@ We will discuss setting up the environment, installing development tools, instal
|
||||
|
||||
## Overall process
|
||||
|
||||
Trigger the [`Release on Snap`](https://github.com/httpie/cli/actions/workflows/release-snap.yml) action, which will
|
||||
Trigger the [`Release on Snap`](https://github.com/httpie/httpie/actions/workflows/release-snap.yml) action, which will
|
||||
create a snap package for HTTPie and then push it to Snap Store in the following channels:
|
||||
|
||||
- Edge
|
||||
@ -37,7 +37,7 @@ From inside the container:
|
||||
|
||||
```bash
|
||||
# Clone
|
||||
git clone --depth=1 https://github.com/httpie/cli.git
|
||||
git clone --depth=1 https://github.com/httpie/httpie.git
|
||||
cd httpie
|
||||
|
||||
# Build
|
||||
|
@ -14,7 +14,7 @@ We will discuss setting up the environment, installing development tools, instal
|
||||
## Overall process
|
||||
|
||||
After having successfully [built and tested](#hacking) the package, either trigger the
|
||||
[`Release on Chocolatey`](https://github.com/httpie/cli/actions/workflows/release-choco.yml) action
|
||||
[`Release on Chocolatey`](https://github.com/httpie/httpie/actions/workflows/release-choco.yml) action
|
||||
to push it to the `Chocolatey` store or use the CLI:
|
||||
|
||||
```bash
|
||||
@ -29,7 +29,7 @@ sets of reviews (some of them are done manually).
|
||||
|
||||
```bash
|
||||
# Clone
|
||||
git clone --depth=1 https://github.com/httpie/cli.git
|
||||
git clone --depth=1 https://github.com/httpie/httpie.git
|
||||
cd httpie/docs/packaging/windows-chocolatey
|
||||
|
||||
# Build
|
||||
|
@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>httpie</id>
|
||||
<version>3.2.2</version>
|
||||
<version>3.2.1</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.
|
||||
@ -30,16 +30,16 @@ Main features:
|
||||
<authors>HTTPie</authors>
|
||||
<owners>jakubroztocil</owners>
|
||||
<copyright>2012-2022 Jakub Roztocil</copyright>
|
||||
<licenseUrl>https://raw.githubusercontent.com/httpie/cli/master/LICENSE</licenseUrl>
|
||||
<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/cli/releases/tag/3.2.2).</releaseNotes>
|
||||
<releaseNotes>See the [changelog](https://github.com/httpie/httpie/releases/tag/3.2.0).</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/cli/tree/master/docs/packaging/windows-chocolatey</packageSourceUrl>
|
||||
<projectSourceUrl>https://github.com/httpie/cli</projectSourceUrl>
|
||||
<packageSourceUrl>https://github.com/httpie/httpie/tree/master/docs/packaging/windows-chocolatey</packageSourceUrl>
|
||||
<projectSourceUrl>https://github.com/httpie/httpie</projectSourceUrl>
|
||||
<docsUrl>https://httpie.io/docs</docsUrl>
|
||||
<bugTrackerUrl>https://github.com/httpie/cli/issues</bugTrackerUrl>
|
||||
<bugTrackerUrl>https://github.com/httpie/httpie/issues</bugTrackerUrl>
|
||||
<dependencies>
|
||||
<dependency id="python3" version="3.7" />
|
||||
</dependencies>
|
||||
|
@ -1,5 +1,5 @@
|
||||
.\" This file is auto-generated from the parser declaration in httpie/cli/definition.py by extras/scripts/generate_man_pages.py.
|
||||
.TH http 1 "2022-05-06" "HTTPie 3.2.2" "HTTPie Manual"
|
||||
.TH http 1 "2022-05-06" "HTTPie 3.2.1" "HTTPie Manual"
|
||||
.SH NAME
|
||||
http
|
||||
.SH SYNOPSIS
|
||||
@ -399,7 +399,7 @@ The authentication mechanism to be used. Defaults to \[dq]basic\[dq].
|
||||
|
||||
\[dq]bearer\[dq]: Bearer HTTP Auth
|
||||
|
||||
To see all available auth types on your system, including ones installed via plugins, run:
|
||||
For finding out all available authentication types in your system, try:
|
||||
|
||||
$ http \fB\,--auth-type\/\fR
|
||||
|
||||
@ -510,12 +510,10 @@ are shown here).
|
||||
|
||||
|
||||
|
||||
A string in the OpenSSL cipher list format.
|
||||
|
||||
|
||||
See `http \fB\,--help\/\fR` for the default ciphers list on you system.
|
||||
|
||||
A string in the OpenSSL cipher list format. By default, the following
|
||||
is used:
|
||||
|
||||
ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20:ECDH+AESGCM:DH+AESGCM:ECDH+AES:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!eNULL:!MD5:!DSS
|
||||
|
||||
|
||||
|
||||
@ -597,4 +595,4 @@ For every \fB\,--OPTION\/\fR there is also a \fB\,--no-OPTION\/\fR that reverts
|
||||
to its default value.
|
||||
|
||||
Suggestions and bug reports are greatly appreciated:
|
||||
https://github.com/httpie/cli/issues
|
||||
https://github.com/httpie/httpie/issues
|
@ -1,5 +1,5 @@
|
||||
.\" This file is auto-generated from the parser declaration in httpie/manager/cli.py by extras/scripts/generate_man_pages.py.
|
||||
.TH httpie 1 "2022-05-06" "HTTPie 3.2.2" "HTTPie Manual"
|
||||
.TH httpie 1 "2022-05-06" "HTTPie 3.2.1" "HTTPie Manual"
|
||||
.SH NAME
|
||||
httpie
|
||||
.SH SYNOPSIS
|
||||
|
@ -1,5 +1,5 @@
|
||||
.\" This file is auto-generated from the parser declaration in httpie/cli/definition.py by extras/scripts/generate_man_pages.py.
|
||||
.TH https 1 "2022-05-06" "HTTPie 3.2.2" "HTTPie Manual"
|
||||
.TH https 1 "2022-05-06" "HTTPie 3.2.1" "HTTPie Manual"
|
||||
.SH NAME
|
||||
https
|
||||
.SH SYNOPSIS
|
||||
@ -399,7 +399,7 @@ The authentication mechanism to be used. Defaults to \[dq]basic\[dq].
|
||||
|
||||
\[dq]bearer\[dq]: Bearer HTTP Auth
|
||||
|
||||
To see all available auth types on your system, including ones installed via plugins, run:
|
||||
For finding out all available authentication types in your system, try:
|
||||
|
||||
$ http \fB\,--auth-type\/\fR
|
||||
|
||||
@ -510,12 +510,10 @@ are shown here).
|
||||
|
||||
|
||||
|
||||
A string in the OpenSSL cipher list format.
|
||||
|
||||
|
||||
See `http \fB\,--help\/\fR` for the default ciphers list on you system.
|
||||
|
||||
A string in the OpenSSL cipher list format. By default, the following
|
||||
is used:
|
||||
|
||||
ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20:ECDH+AESGCM:DH+AESGCM:ECDH+AES:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!eNULL:!MD5:!DSS
|
||||
|
||||
|
||||
|
||||
@ -597,4 +595,4 @@ For every \fB\,--OPTION\/\fR there is also a \fB\,--no-OPTION\/\fR that reverts
|
||||
to its default value.
|
||||
|
||||
Suggestions and bug reports are greatly appreciated:
|
||||
https://github.com/httpie/cli/issues
|
||||
https://github.com/httpie/httpie/issues
|
@ -7,13 +7,13 @@ This directory contains the build scripts for creating:
|
||||
- A self-contained binary executable for the HTTPie itself
|
||||
- `httpie.deb` and `httpie.rpm` packages for Debian and Fedora.
|
||||
|
||||
The process of constructing them are fully automated, and can be easily done through the [`Release as Standalone Linux Package`](https://github.com/httpie/cli/actions/workflows/release-linux-standalone.yml)
|
||||
The process of constructing them are fully automated, and can be easily done through the [`Release as Standalone Linux Package`](https://github.com/httpie/httpie/actions/workflows/release-linux-standalone.yml)
|
||||
action. Once it finishes, the release artifacts will be attached in the summary page of the triggered run.
|
||||
|
||||
|
||||
## Hacking
|
||||
|
||||
The main entry point for the package builder is the [`build.py`](https://github.com/httpie/cli/blob/master/extras/packaging/linux/build.py). It
|
||||
The main entry point for the package builder is the [`build.py`](https://github.com/httpie/httpie/blob/master/extras/packaging/linux/build.py). It
|
||||
contains 2 major methods:
|
||||
|
||||
- `build_binaries`, for the self-contained executables
|
||||
@ -39,7 +39,7 @@ Since the `httpie` depends on having a pip executable, we explicitly depend on t
|
||||
|
||||
### Docker Image
|
||||
|
||||
This directory also contains a [docker image](https://github.com/httpie/cli/blob/master/extras/packaging/linux/Dockerfile) which helps
|
||||
This directory also contains a [docker image](https://github.com/httpie/httpie/blob/master/extras/packaging/linux/Dockerfile) which helps
|
||||
building our standalone binaries in an isolated environment with the lowest possible library versions. This is important, since even though
|
||||
the executables are standalone they still depend on some main system C libraries (like `glibc`) so we need to create our executables inside
|
||||
an environment with a very old (but not deprecated) glibc version. It makes us soundproof for all active Ubuntu/Debian versions.
|
||||
|
@ -10,7 +10,7 @@ Ensure the following requirements are satisfied:
|
||||
- Python 3.7+
|
||||
- `pyperf`
|
||||
|
||||
Then, run the `extras/profiling/run.py`:
|
||||
Then, run the `extras/benchmarks/run.py`:
|
||||
|
||||
```console
|
||||
$ python extras/profiling/run.py
|
||||
@ -28,7 +28,7 @@ on both of them. It will compare the results and print it as a markdown table:
|
||||
| Geometric mean | (ref) | 1.10x faster |
|
||||
|
||||
If your `master` branch is not up-to-date, you can get a fresh clone by passing
|
||||
`--fresh` option. This way, the benchmark runner will clone the `httpie/cli`
|
||||
`--fresh` option. This way, the benchmark runner will clone the `httpie/httpie`
|
||||
repo from `GitHub` and use it as the baseline.
|
||||
|
||||
You can customize these branches by passing `--local-repo`/`--target-branch`,
|
||||
|
@ -9,11 +9,11 @@ timings.
|
||||
|
||||
The benchmarks are run through 'pyperf', which allows to
|
||||
do get very precise results. For micro-benchmarks like startup,
|
||||
please run `pyperf system tune` to get even more accurate results.
|
||||
please run `pyperf system tune` to get even more acurrate results.
|
||||
|
||||
Examples:
|
||||
|
||||
# Run everything as usual, the default is that we do 3 warm-up runs
|
||||
# Run everything as usual, the default is that we do 3 warmup runs
|
||||
# and 5 actual runs.
|
||||
$ python extras/profiling/benchmarks.py
|
||||
|
||||
@ -188,7 +188,7 @@ DownloadRunner('download', '`http --download :/big_file.txt` (3GB)', '3G')
|
||||
def main() -> None:
|
||||
# PyPerf will bring it's own argument parser, so configure the script.
|
||||
# The somewhat fast and also precise enough configuration is this. We run
|
||||
# benchmarks 3 times to warm up (e.g especially for download benchmark, this
|
||||
# benchmarks 3 times to warmup (e.g especially for download benchmark, this
|
||||
# is important). And then 5 actual runs where we record.
|
||||
sys.argv.extend(
|
||||
['--worker', '--loops=1', '--warmup=3', '--values=5', '--processes=2']
|
||||
|
@ -19,19 +19,19 @@ which would include additional dependencies like pyOpenSSL.
|
||||
Examples:
|
||||
|
||||
# Run everything as usual, and compare last commit with master
|
||||
$ python extras/profiling/run.py
|
||||
$ python extras/benchmarks/run.py
|
||||
|
||||
# Include complex environments
|
||||
$ python extras/profiling/run.py --complex
|
||||
$ python extras/benchmarks/run.py --complex
|
||||
|
||||
# Compare against a fresh copy
|
||||
$ python extras/profiling/run.py --fresh
|
||||
$ python extras/benchmarks/run.py --fresh
|
||||
|
||||
# Compare against a custom branch of a custom repo
|
||||
$ python extras/profiling/run.py --target-repo my_repo --target-branch my_branch
|
||||
$ python extras/benchmarks/run.py --target-repo my_repo --target-branch my_branch
|
||||
|
||||
# Debug changes made on this script (only run benchmarks once)
|
||||
$ python extras/profiling/run.py --debug
|
||||
$ python extras/benchmarks/run.py --debug
|
||||
"""
|
||||
|
||||
import dataclasses
|
||||
@ -50,7 +50,7 @@ from typing import (IO, Dict, Generator, Iterable, List, Optional,
|
||||
BENCHMARK_SCRIPT = Path(__file__).parent / 'benchmarks.py'
|
||||
CURRENT_REPO = Path(__file__).parent.parent.parent
|
||||
|
||||
GITHUB_URL = 'https://github.com/httpie/cli.git'
|
||||
GITHUB_URL = 'https://github.com/httpie/httpie.git'
|
||||
TARGET_BRANCH = 'master'
|
||||
|
||||
# Additional dependencies for --complex
|
||||
|
@ -1,25 +1,20 @@
|
||||
import os
|
||||
import re
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from typing import Optional, Iterator, Iterable
|
||||
|
||||
|
||||
# So that httpie.cli.definition can provide man-page-specific output. Must be set before importing httpie.
|
||||
os.environ['HTTPIE_BUILDING_MAN_PAGES'] = '1'
|
||||
|
||||
import httpie
|
||||
from httpie.cli.definition import options as core_options, IS_MAN_PAGE
|
||||
from httpie.cli.definition import options as core_options
|
||||
from httpie.cli.options import ParserSpec
|
||||
from httpie.manager.cli import options as manager_options
|
||||
from httpie.output.ui.rich_help import OptionsHighlighter, to_usage
|
||||
from httpie.output.ui.rich_utils import render_as_string
|
||||
from httpie.utils import split
|
||||
|
||||
|
||||
assert IS_MAN_PAGE, 'CLI definition does not understand we’re building man pages'
|
||||
|
||||
# Escape certain characters, so they are rendered properly on all terminals.
|
||||
# <https://man7.org/linux/man-pages/man7/groff_char.7.html>
|
||||
# Escape certain characters so they are rendered properly on
|
||||
# all terminals.
|
||||
# https://man7.org/linux/man-pages/man7/groff_char.7.html
|
||||
ESCAPE_MAP = {
|
||||
'"': '\[dq]',
|
||||
"'": '\[aq]',
|
||||
@ -37,7 +32,6 @@ OPTION_HIGHLIGHT_RE = re.compile(
|
||||
OptionsHighlighter.highlights[0]
|
||||
)
|
||||
|
||||
|
||||
class ManPageBuilder:
|
||||
def __init__(self):
|
||||
self.source = []
|
||||
@ -131,7 +125,7 @@ def to_man_page(program_name: str, spec: ParserSpec, *, is_top_level_cmd: bool =
|
||||
|
||||
with builder.section('SYNOPSIS'):
|
||||
# `http` and `https` are commands that can be directly used, so they can have
|
||||
# a valid usage. But `httpie` is a top-level command with multiple sub commands,
|
||||
# have a valid usage. But `httpie` is a top-level command with multiple sub commands,
|
||||
# so for the synopsis we'll only reference the `httpie` name.
|
||||
if is_top_level_cmd:
|
||||
synopsis = program_name
|
||||
@ -159,7 +153,7 @@ def to_man_page(program_name: str, spec: ParserSpec, *, is_top_level_cmd: bool =
|
||||
if raw_arg.get('is_positional'):
|
||||
# In case of positional arguments, metavar is always equal
|
||||
# to the list of options (e.g `METHOD`).
|
||||
metavar = None
|
||||
metavar = None
|
||||
builder.add_options(raw_arg['options'], metavar=metavar)
|
||||
|
||||
desc = builder.format_desc(raw_arg.get('description', ''))
|
||||
@ -184,5 +178,6 @@ def main() -> None:
|
||||
stream.write(to_man_page(program_name, spec, **config))
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -3,7 +3,7 @@ HTTPie: modern, user-friendly command-line HTTP client for the API era.
|
||||
|
||||
"""
|
||||
|
||||
__version__ = '3.2.2'
|
||||
__version__ = '3.2.1'
|
||||
__date__ = '2022-05-06'
|
||||
__author__ = 'Jakub Roztocil'
|
||||
__licence__ = 'BSD'
|
||||
|
@ -1,6 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import textwrap
|
||||
from argparse import FileType
|
||||
|
||||
@ -21,13 +20,7 @@ from httpie.output.formatters.colors import (AUTO_STYLE, DEFAULT_STYLE, BUNDLED_
|
||||
get_available_styles)
|
||||
from httpie.plugins.builtin import BuiltinAuthPlugin
|
||||
from httpie.plugins.registry import plugin_manager
|
||||
from httpie.ssl_ import AVAILABLE_SSL_VERSION_ARG_MAPPING, DEFAULT_SSL_CIPHERS_STRING
|
||||
|
||||
|
||||
# Man pages are static (built when making a release).
|
||||
# We use this check to not include generated, system-specific information there (e.g., default --ciphers).
|
||||
IS_MAN_PAGE = bool(os.environ.get('HTTPIE_BUILDING_MAN_PAGES'))
|
||||
|
||||
from httpie.ssl_ import AVAILABLE_SSL_VERSION_ARG_MAPPING, DEFAULT_SSL_CIPHERS
|
||||
|
||||
options = ParserSpec(
|
||||
'http',
|
||||
@ -37,11 +30,12 @@ options = ParserSpec(
|
||||
to its default value.
|
||||
|
||||
Suggestions and bug reports are greatly appreciated:
|
||||
https://github.com/httpie/cli/issues
|
||||
https://github.com/httpie/httpie/issues
|
||||
""",
|
||||
source_file=__file__
|
||||
)
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Positional arguments.
|
||||
#######################################################################
|
||||
@ -240,7 +234,6 @@ processing_options.add_argument(
|
||||
""",
|
||||
)
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Output processing
|
||||
#######################################################################
|
||||
@ -617,7 +610,6 @@ sessions.add_argument(
|
||||
""",
|
||||
)
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Authentication
|
||||
#######################################################################
|
||||
@ -638,7 +630,7 @@ def format_auth_help(auth_plugins_mapping, *, isolation_mode: bool = False):
|
||||
if issubclass(auth_plugin, BuiltinAuthPlugin)
|
||||
]
|
||||
text += '\n'
|
||||
text += 'To see all available auth types on your system, including ones installed via plugins, run:\n\n'
|
||||
text += 'For finding out all available authentication types in your system, try:\n\n'
|
||||
text += ' $ http --auth-type'
|
||||
|
||||
auth_types = '\n\n '.join(
|
||||
@ -654,7 +646,7 @@ def format_auth_help(auth_plugins_mapping, *, isolation_mode: bool = False):
|
||||
''
|
||||
if not plugin.description
|
||||
else '\n '
|
||||
+ ('\n '.join(textwrap.wrap(plugin.description)))
|
||||
+ ('\n '.join(textwrap.wrap(plugin.description)))
|
||||
),
|
||||
)
|
||||
for plugin in auth_plugins
|
||||
@ -834,36 +826,23 @@ ssl.add_argument(
|
||||
|
||||
""",
|
||||
)
|
||||
|
||||
CIPHERS_CURRENT_DEFAULTS = (
|
||||
"""
|
||||
See `http --help` for the default ciphers list on you system.
|
||||
|
||||
"""
|
||||
if IS_MAN_PAGE else
|
||||
f"""
|
||||
By default, the following ciphers are used on your system:
|
||||
|
||||
{DEFAULT_SSL_CIPHERS_STRING}
|
||||
|
||||
"""
|
||||
)
|
||||
ssl.add_argument(
|
||||
'--ciphers',
|
||||
short_help='A string in the OpenSSL cipher list format.',
|
||||
help=f"""
|
||||
|
||||
A string in the OpenSSL cipher list format.
|
||||
A string in the OpenSSL cipher list format. By default, the following
|
||||
is used:
|
||||
|
||||
{CIPHERS_CURRENT_DEFAULTS}
|
||||
{DEFAULT_SSL_CIPHERS}
|
||||
|
||||
"""
|
||||
""",
|
||||
)
|
||||
ssl.add_argument(
|
||||
'--cert',
|
||||
default=None,
|
||||
type=readable_file_arg,
|
||||
short_help='Specifies a local cert to use as the client-side SSL certificate.',
|
||||
short_help='Specifys a local cert to use as client side SSL certificate.',
|
||||
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
|
||||
|
@ -92,3 +92,7 @@ class MultipartRequestDataDict(MultiValueOrderedDict):
|
||||
|
||||
class RequestFilesDict(RequestDataDict):
|
||||
pass
|
||||
|
||||
|
||||
class NestedJSONArray(list):
|
||||
"""Denotes a top-level JSON array."""
|
||||
|
404
httpie/cli/nested_json.py
Normal file
404
httpie/cli/nested_json.py
Normal file
@ -0,0 +1,404 @@
|
||||
from enum import Enum, auto
|
||||
from typing import (
|
||||
Any,
|
||||
Iterator,
|
||||
NamedTuple,
|
||||
Optional,
|
||||
List,
|
||||
NoReturn,
|
||||
Type,
|
||||
Union,
|
||||
)
|
||||
from .dicts import NestedJSONArray
|
||||
|
||||
|
||||
EMPTY_STRING = ''
|
||||
HIGHLIGHTER = '^'
|
||||
OPEN_BRACKET = '['
|
||||
CLOSE_BRACKET = ']'
|
||||
BACKSLASH = '\\'
|
||||
|
||||
|
||||
class HTTPieSyntaxError(ValueError):
|
||||
def __init__(
|
||||
self,
|
||||
source: str,
|
||||
token: Optional['Token'],
|
||||
message: str,
|
||||
message_kind: str = 'Syntax',
|
||||
) -> None:
|
||||
self.source = source
|
||||
self.token = token
|
||||
self.message = message
|
||||
self.message_kind = message_kind
|
||||
|
||||
def __str__(self):
|
||||
lines = [f'HTTPie {self.message_kind} Error: {self.message}']
|
||||
if self.token is not None:
|
||||
lines.append(self.source)
|
||||
lines.append(
|
||||
' ' * self.token.start
|
||||
+ HIGHLIGHTER * (self.token.end - self.token.start)
|
||||
)
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
class TokenKind(Enum):
|
||||
TEXT = auto()
|
||||
NUMBER = auto()
|
||||
LEFT_BRACKET = auto()
|
||||
RIGHT_BRACKET = auto()
|
||||
|
||||
def to_name(self) -> str:
|
||||
for key, value in OPERATORS.items():
|
||||
if value is self:
|
||||
return repr(key)
|
||||
else:
|
||||
return 'a ' + self.name.lower()
|
||||
|
||||
|
||||
OPERATORS = {
|
||||
OPEN_BRACKET: TokenKind.LEFT_BRACKET,
|
||||
CLOSE_BRACKET: TokenKind.RIGHT_BRACKET,
|
||||
}
|
||||
SPECIAL_CHARS = OPERATORS.keys() | {BACKSLASH}
|
||||
LITERAL_TOKENS = [
|
||||
TokenKind.TEXT,
|
||||
TokenKind.NUMBER,
|
||||
]
|
||||
|
||||
|
||||
class Token(NamedTuple):
|
||||
kind: TokenKind
|
||||
value: Union[str, int]
|
||||
start: int
|
||||
end: int
|
||||
|
||||
|
||||
def assert_cant_happen() -> NoReturn:
|
||||
raise ValueError('Unexpected value')
|
||||
|
||||
|
||||
def check_escaped_int(value: str) -> str:
|
||||
if not value.startswith(BACKSLASH):
|
||||
raise ValueError('Not an escaped int')
|
||||
|
||||
try:
|
||||
int(value[1:])
|
||||
except ValueError as exc:
|
||||
raise ValueError('Not an escaped int') from exc
|
||||
else:
|
||||
return value[1:]
|
||||
|
||||
|
||||
def tokenize(source: str) -> Iterator[Token]:
|
||||
cursor = 0
|
||||
backslashes = 0
|
||||
buffer = []
|
||||
|
||||
def send_buffer() -> Iterator[Token]:
|
||||
nonlocal backslashes
|
||||
if not buffer:
|
||||
return None
|
||||
|
||||
value = ''.join(buffer)
|
||||
kind = TokenKind.TEXT
|
||||
if not backslashes:
|
||||
for variation, kind in [
|
||||
(int, TokenKind.NUMBER),
|
||||
(check_escaped_int, TokenKind.TEXT),
|
||||
]:
|
||||
try:
|
||||
value = variation(value)
|
||||
except ValueError:
|
||||
continue
|
||||
else:
|
||||
break
|
||||
|
||||
yield Token(
|
||||
kind, value, start=cursor - (len(buffer) + backslashes), end=cursor
|
||||
)
|
||||
buffer.clear()
|
||||
backslashes = 0
|
||||
|
||||
def can_advance() -> bool:
|
||||
return cursor < len(source)
|
||||
|
||||
while can_advance():
|
||||
index = source[cursor]
|
||||
if index in OPERATORS:
|
||||
yield from send_buffer()
|
||||
yield Token(OPERATORS[index], index, cursor, cursor + 1)
|
||||
elif index == BACKSLASH and can_advance():
|
||||
if source[cursor + 1] in SPECIAL_CHARS:
|
||||
backslashes += 1
|
||||
else:
|
||||
buffer.append(index)
|
||||
|
||||
buffer.append(source[cursor + 1])
|
||||
cursor += 1
|
||||
else:
|
||||
buffer.append(index)
|
||||
|
||||
cursor += 1
|
||||
|
||||
yield from send_buffer()
|
||||
|
||||
|
||||
class PathAction(Enum):
|
||||
KEY = auto()
|
||||
INDEX = auto()
|
||||
APPEND = auto()
|
||||
|
||||
# Pseudo action, used by the interpreter
|
||||
SET = auto()
|
||||
|
||||
def to_string(self) -> str:
|
||||
return self.name.lower()
|
||||
|
||||
|
||||
class Path:
|
||||
def __init__(
|
||||
self,
|
||||
kind: PathAction,
|
||||
accessor: Optional[Union[str, int]] = None,
|
||||
tokens: Optional[List[Token]] = None,
|
||||
is_root: bool = False,
|
||||
):
|
||||
self.kind = kind
|
||||
self.accessor = accessor
|
||||
self.tokens = tokens or []
|
||||
self.is_root = is_root
|
||||
|
||||
def reconstruct(self) -> str:
|
||||
if self.kind is PathAction.KEY:
|
||||
if self.is_root:
|
||||
return str(self.accessor)
|
||||
return OPEN_BRACKET + self.accessor + CLOSE_BRACKET
|
||||
elif self.kind is PathAction.INDEX:
|
||||
return OPEN_BRACKET + str(self.accessor) + CLOSE_BRACKET
|
||||
elif self.kind is PathAction.APPEND:
|
||||
return OPEN_BRACKET + CLOSE_BRACKET
|
||||
else:
|
||||
assert_cant_happen()
|
||||
|
||||
|
||||
def parse(source: str) -> Iterator[Path]:
|
||||
"""
|
||||
start: root_path path*
|
||||
root_path: (literal | index_path | append_path)
|
||||
literal: TEXT | NUMBER
|
||||
|
||||
path:
|
||||
key_path
|
||||
| index_path
|
||||
| append_path
|
||||
key_path: LEFT_BRACKET TEXT RIGHT_BRACKET
|
||||
index_path: LEFT_BRACKET NUMBER RIGHT_BRACKET
|
||||
append_path: LEFT_BRACKET RIGHT_BRACKET
|
||||
"""
|
||||
|
||||
tokens = list(tokenize(source))
|
||||
cursor = 0
|
||||
|
||||
def can_advance():
|
||||
return cursor < len(tokens)
|
||||
|
||||
def expect(*kinds):
|
||||
nonlocal cursor
|
||||
|
||||
assert len(kinds) > 0
|
||||
if can_advance():
|
||||
token = tokens[cursor]
|
||||
cursor += 1
|
||||
if token.kind in kinds:
|
||||
return token
|
||||
elif tokens:
|
||||
token = tokens[-1]._replace(
|
||||
start=tokens[-1].end + 0, end=tokens[-1].end + 1
|
||||
)
|
||||
else:
|
||||
token = None
|
||||
|
||||
if len(kinds) == 1:
|
||||
suffix = kinds[0].to_name()
|
||||
else:
|
||||
suffix = ', '.join(kind.to_name() for kind in kinds[:-1])
|
||||
suffix += ' or ' + kinds[-1].to_name()
|
||||
|
||||
message = f'Expecting {suffix}'
|
||||
raise HTTPieSyntaxError(source, token, message)
|
||||
|
||||
def parse_root():
|
||||
tokens = []
|
||||
if not can_advance():
|
||||
return Path(
|
||||
PathAction.KEY,
|
||||
EMPTY_STRING,
|
||||
is_root=True
|
||||
)
|
||||
|
||||
# (literal | index_path | append_path)?
|
||||
token = expect(*LITERAL_TOKENS, TokenKind.LEFT_BRACKET)
|
||||
tokens.append(token)
|
||||
|
||||
if token.kind in LITERAL_TOKENS:
|
||||
action = PathAction.KEY
|
||||
value = str(token.value)
|
||||
elif token.kind is TokenKind.LEFT_BRACKET:
|
||||
token = expect(TokenKind.NUMBER, TokenKind.RIGHT_BRACKET)
|
||||
tokens.append(token)
|
||||
if token.kind is TokenKind.NUMBER:
|
||||
action = PathAction.INDEX
|
||||
value = token.value
|
||||
tokens.append(expect(TokenKind.RIGHT_BRACKET))
|
||||
elif token.kind is TokenKind.RIGHT_BRACKET:
|
||||
action = PathAction.APPEND
|
||||
value = None
|
||||
else:
|
||||
assert_cant_happen()
|
||||
else:
|
||||
assert_cant_happen()
|
||||
|
||||
return Path(
|
||||
action,
|
||||
value,
|
||||
tokens=tokens,
|
||||
is_root=True
|
||||
)
|
||||
|
||||
yield parse_root()
|
||||
|
||||
# path*
|
||||
while can_advance():
|
||||
path_tokens = []
|
||||
path_tokens.append(expect(TokenKind.LEFT_BRACKET))
|
||||
|
||||
token = expect(
|
||||
TokenKind.TEXT, TokenKind.NUMBER, TokenKind.RIGHT_BRACKET
|
||||
)
|
||||
path_tokens.append(token)
|
||||
if token.kind is TokenKind.RIGHT_BRACKET:
|
||||
path = Path(PathAction.APPEND, tokens=path_tokens)
|
||||
elif token.kind is TokenKind.TEXT:
|
||||
path = Path(PathAction.KEY, token.value, tokens=path_tokens)
|
||||
path_tokens.append(expect(TokenKind.RIGHT_BRACKET))
|
||||
elif token.kind is TokenKind.NUMBER:
|
||||
path = Path(PathAction.INDEX, token.value, tokens=path_tokens)
|
||||
path_tokens.append(expect(TokenKind.RIGHT_BRACKET))
|
||||
else:
|
||||
assert_cant_happen()
|
||||
yield path
|
||||
|
||||
|
||||
JSON_TYPE_MAPPING = {
|
||||
dict: 'object',
|
||||
list: 'array',
|
||||
int: 'number',
|
||||
float: 'number',
|
||||
str: 'string',
|
||||
}
|
||||
|
||||
|
||||
def interpret(context: Any, key: str, value: Any) -> Any:
|
||||
cursor = context
|
||||
|
||||
paths = list(parse(key))
|
||||
paths.append(Path(PathAction.SET, value))
|
||||
|
||||
def type_check(index: int, path: Path, expected_type: Type[Any]) -> None:
|
||||
if not isinstance(cursor, expected_type):
|
||||
if path.tokens:
|
||||
pseudo_token = Token(
|
||||
None, None, path.tokens[0].start, path.tokens[-1].end
|
||||
)
|
||||
else:
|
||||
pseudo_token = None
|
||||
|
||||
cursor_type = JSON_TYPE_MAPPING.get(
|
||||
type(cursor), type(cursor).__name__
|
||||
)
|
||||
required_type = JSON_TYPE_MAPPING[expected_type]
|
||||
|
||||
message = f"Can't perform {path.kind.to_string()!r} based access on "
|
||||
message += repr(
|
||||
''.join(path.reconstruct() for path in paths[:index])
|
||||
)
|
||||
message += (
|
||||
f' which has a type of {cursor_type!r} but this operation'
|
||||
)
|
||||
message += f' requires a type of {required_type!r}.'
|
||||
raise HTTPieSyntaxError(
|
||||
key, pseudo_token, message, message_kind='Type'
|
||||
)
|
||||
|
||||
def object_for(kind: str) -> Any:
|
||||
if kind is PathAction.KEY:
|
||||
return {}
|
||||
elif kind in {PathAction.INDEX, PathAction.APPEND}:
|
||||
return []
|
||||
else:
|
||||
assert_cant_happen()
|
||||
|
||||
for index, (path, next_path) in enumerate(zip(paths, paths[1:])):
|
||||
# If there is no context yet, set it.
|
||||
if cursor is None:
|
||||
context = cursor = object_for(path.kind)
|
||||
|
||||
if path.kind is PathAction.KEY:
|
||||
type_check(index, path, dict)
|
||||
if next_path.kind is PathAction.SET:
|
||||
cursor[path.accessor] = next_path.accessor
|
||||
break
|
||||
|
||||
cursor = cursor.setdefault(
|
||||
path.accessor, object_for(next_path.kind)
|
||||
)
|
||||
elif path.kind is PathAction.INDEX:
|
||||
type_check(index, path, list)
|
||||
if path.accessor < 0:
|
||||
raise HTTPieSyntaxError(
|
||||
key,
|
||||
path.tokens[1],
|
||||
'Negative indexes are not supported.',
|
||||
message_kind='Value',
|
||||
)
|
||||
cursor.extend([None] * (path.accessor - len(cursor) + 1))
|
||||
if next_path.kind is PathAction.SET:
|
||||
cursor[path.accessor] = next_path.accessor
|
||||
break
|
||||
|
||||
if cursor[path.accessor] is None:
|
||||
cursor[path.accessor] = object_for(next_path.kind)
|
||||
|
||||
cursor = cursor[path.accessor]
|
||||
elif path.kind is PathAction.APPEND:
|
||||
type_check(index, path, list)
|
||||
if next_path.kind is PathAction.SET:
|
||||
cursor.append(next_path.accessor)
|
||||
break
|
||||
|
||||
cursor.append(object_for(next_path.kind))
|
||||
cursor = cursor[-1]
|
||||
else:
|
||||
assert_cant_happen()
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def wrap_with_dict(context):
|
||||
if context is None:
|
||||
return {}
|
||||
elif isinstance(context, list):
|
||||
return {EMPTY_STRING: NestedJSONArray(context)}
|
||||
else:
|
||||
assert isinstance(context, dict)
|
||||
return context
|
||||
|
||||
|
||||
def interpret_nested_json(pairs):
|
||||
context = None
|
||||
for key, value in pairs:
|
||||
context = interpret(context, key, value)
|
||||
|
||||
return wrap_with_dict(context)
|
@ -1,20 +0,0 @@
|
||||
"""
|
||||
A library for parsing the HTTPie nested JSON key syntax and constructing the resulting objects.
|
||||
|
||||
<https://httpie.io/docs/cli/nested-json>
|
||||
|
||||
It has no dependencies.
|
||||
|
||||
"""
|
||||
from .interpret import interpret_nested_json, unwrap_top_level_list_if_needed
|
||||
from .errors import NestedJSONSyntaxError
|
||||
from .tokens import EMPTY_STRING, NestedJSONArray
|
||||
|
||||
|
||||
__all__ = [
|
||||
'interpret_nested_json',
|
||||
'unwrap_top_level_list_if_needed',
|
||||
'EMPTY_STRING',
|
||||
'NestedJSONArray',
|
||||
'NestedJSONSyntaxError'
|
||||
]
|
@ -1,27 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from .tokens import Token, HIGHLIGHTER
|
||||
|
||||
|
||||
class NestedJSONSyntaxError(ValueError):
|
||||
def __init__(
|
||||
self,
|
||||
source: str,
|
||||
token: Optional[Token],
|
||||
message: str,
|
||||
message_kind: str = 'Syntax',
|
||||
) -> None:
|
||||
self.source = source
|
||||
self.token = token
|
||||
self.message = message
|
||||
self.message_kind = message_kind
|
||||
|
||||
def __str__(self):
|
||||
lines = [f'HTTPie {self.message_kind} Error: {self.message}']
|
||||
if self.token is not None:
|
||||
lines.append(self.source)
|
||||
lines.append(
|
||||
' ' * self.token.start
|
||||
+ HIGHLIGHTER * (self.token.end - self.token.start)
|
||||
)
|
||||
return '\n'.join(lines)
|
@ -1,129 +0,0 @@
|
||||
from typing import Type, Union, Any, Iterable, Tuple
|
||||
|
||||
from .parse import parse, assert_cant_happen
|
||||
from .errors import NestedJSONSyntaxError
|
||||
from .tokens import EMPTY_STRING, TokenKind, Token, PathAction, Path, NestedJSONArray
|
||||
|
||||
|
||||
__all__ = [
|
||||
'interpret_nested_json',
|
||||
'unwrap_top_level_list_if_needed',
|
||||
]
|
||||
|
||||
JSONType = Type[Union[dict, list, int, float, str]]
|
||||
JSON_TYPE_MAPPING = {
|
||||
dict: 'object',
|
||||
list: 'array',
|
||||
int: 'number',
|
||||
float: 'number',
|
||||
str: 'string',
|
||||
}
|
||||
|
||||
|
||||
def interpret_nested_json(pairs: Iterable[Tuple[str, str]]) -> dict:
|
||||
context = None
|
||||
for key, value in pairs:
|
||||
context = interpret(context, key, value)
|
||||
return wrap_with_dict(context)
|
||||
|
||||
|
||||
def interpret(context: Any, key: str, value: Any) -> Any:
|
||||
cursor = context
|
||||
paths = list(parse(key))
|
||||
paths.append(Path(PathAction.SET, value))
|
||||
|
||||
# noinspection PyShadowingNames
|
||||
def type_check(index: int, path: Path, expected_type: JSONType):
|
||||
if not isinstance(cursor, expected_type):
|
||||
if path.tokens:
|
||||
pseudo_token = Token(
|
||||
kind=TokenKind.PSEUDO,
|
||||
value='',
|
||||
start=path.tokens[0].start,
|
||||
end=path.tokens[-1].end,
|
||||
)
|
||||
else:
|
||||
pseudo_token = None
|
||||
cursor_type = JSON_TYPE_MAPPING.get(type(cursor), type(cursor).__name__)
|
||||
required_type = JSON_TYPE_MAPPING[expected_type]
|
||||
message = f'Cannot perform {path.kind.to_string()!r} based access on '
|
||||
message += repr(''.join(path.reconstruct() for path in paths[:index]))
|
||||
message += f' which has a type of {cursor_type!r} but this operation'
|
||||
message += f' requires a type of {required_type!r}.'
|
||||
raise NestedJSONSyntaxError(
|
||||
source=key,
|
||||
token=pseudo_token,
|
||||
message=message,
|
||||
message_kind='Type',
|
||||
)
|
||||
|
||||
def object_for(kind: PathAction) -> Any:
|
||||
if kind is PathAction.KEY:
|
||||
return {}
|
||||
elif kind in {PathAction.INDEX, PathAction.APPEND}:
|
||||
return []
|
||||
else:
|
||||
assert_cant_happen()
|
||||
|
||||
for index, (path, next_path) in enumerate(zip(paths, paths[1:])):
|
||||
# If there is no context yet, set it.
|
||||
if cursor is None:
|
||||
context = cursor = object_for(path.kind)
|
||||
if path.kind is PathAction.KEY:
|
||||
type_check(index, path, dict)
|
||||
if next_path.kind is PathAction.SET:
|
||||
cursor[path.accessor] = next_path.accessor
|
||||
break
|
||||
cursor = cursor.setdefault(path.accessor, object_for(next_path.kind))
|
||||
elif path.kind is PathAction.INDEX:
|
||||
type_check(index, path, list)
|
||||
if path.accessor < 0:
|
||||
raise NestedJSONSyntaxError(
|
||||
source=key,
|
||||
token=path.tokens[1],
|
||||
message='Negative indexes are not supported.',
|
||||
message_kind='Value',
|
||||
)
|
||||
cursor.extend([None] * (path.accessor - len(cursor) + 1))
|
||||
if next_path.kind is PathAction.SET:
|
||||
cursor[path.accessor] = next_path.accessor
|
||||
break
|
||||
if cursor[path.accessor] is None:
|
||||
cursor[path.accessor] = object_for(next_path.kind)
|
||||
cursor = cursor[path.accessor]
|
||||
elif path.kind is PathAction.APPEND:
|
||||
type_check(index, path, list)
|
||||
if next_path.kind is PathAction.SET:
|
||||
cursor.append(next_path.accessor)
|
||||
break
|
||||
cursor.append(object_for(next_path.kind))
|
||||
cursor = cursor[-1]
|
||||
else:
|
||||
assert_cant_happen()
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def wrap_with_dict(context):
|
||||
if context is None:
|
||||
return {}
|
||||
elif isinstance(context, list):
|
||||
return {
|
||||
EMPTY_STRING: NestedJSONArray(context),
|
||||
}
|
||||
else:
|
||||
assert isinstance(context, dict)
|
||||
return context
|
||||
|
||||
|
||||
def unwrap_top_level_list_if_needed(data: dict):
|
||||
"""
|
||||
Propagate the top-level list, if that’s what we got.
|
||||
|
||||
"""
|
||||
if len(data) == 1:
|
||||
key, value = list(data.items())[0]
|
||||
if isinstance(value, NestedJSONArray):
|
||||
assert key == EMPTY_STRING
|
||||
return value
|
||||
return data
|
@ -1,193 +0,0 @@
|
||||
from typing import Iterator
|
||||
|
||||
from .errors import NestedJSONSyntaxError
|
||||
from .tokens import (
|
||||
EMPTY_STRING,
|
||||
BACKSLASH,
|
||||
TokenKind,
|
||||
OPERATORS,
|
||||
SPECIAL_CHARS,
|
||||
LITERAL_TOKENS,
|
||||
Token,
|
||||
PathAction,
|
||||
Path,
|
||||
)
|
||||
|
||||
|
||||
__all__ = [
|
||||
'parse',
|
||||
'assert_cant_happen',
|
||||
]
|
||||
|
||||
|
||||
def parse(source: str) -> Iterator[Path]:
|
||||
"""
|
||||
start: root_path path*
|
||||
root_path: (literal | index_path | append_path)
|
||||
literal: TEXT | NUMBER
|
||||
|
||||
path:
|
||||
key_path
|
||||
| index_path
|
||||
| append_path
|
||||
key_path: LEFT_BRACKET TEXT RIGHT_BRACKET
|
||||
index_path: LEFT_BRACKET NUMBER RIGHT_BRACKET
|
||||
append_path: LEFT_BRACKET RIGHT_BRACKET
|
||||
|
||||
"""
|
||||
|
||||
tokens = list(tokenize(source))
|
||||
cursor = 0
|
||||
|
||||
def can_advance():
|
||||
return cursor < len(tokens)
|
||||
|
||||
# noinspection PyShadowingNames
|
||||
def expect(*kinds):
|
||||
nonlocal cursor
|
||||
assert kinds
|
||||
if can_advance():
|
||||
token = tokens[cursor]
|
||||
cursor += 1
|
||||
if token.kind in kinds:
|
||||
return token
|
||||
elif tokens:
|
||||
token = tokens[-1]._replace(
|
||||
start=tokens[-1].end + 0,
|
||||
end=tokens[-1].end + 1,
|
||||
)
|
||||
else:
|
||||
token = None
|
||||
if len(kinds) == 1:
|
||||
suffix = kinds[0].to_name()
|
||||
else:
|
||||
suffix = ', '.join(kind.to_name() for kind in kinds[:-1])
|
||||
suffix += ' or ' + kinds[-1].to_name()
|
||||
message = f'Expecting {suffix}'
|
||||
raise NestedJSONSyntaxError(source, token, message)
|
||||
|
||||
# noinspection PyShadowingNames
|
||||
def parse_root():
|
||||
tokens = []
|
||||
if not can_advance():
|
||||
return Path(
|
||||
kind=PathAction.KEY,
|
||||
accessor=EMPTY_STRING,
|
||||
is_root=True
|
||||
)
|
||||
# (literal | index_path | append_path)?
|
||||
token = expect(*LITERAL_TOKENS, TokenKind.LEFT_BRACKET)
|
||||
tokens.append(token)
|
||||
if token.kind in LITERAL_TOKENS:
|
||||
action = PathAction.KEY
|
||||
value = str(token.value)
|
||||
elif token.kind is TokenKind.LEFT_BRACKET:
|
||||
token = expect(TokenKind.NUMBER, TokenKind.RIGHT_BRACKET)
|
||||
tokens.append(token)
|
||||
if token.kind is TokenKind.NUMBER:
|
||||
action = PathAction.INDEX
|
||||
value = token.value
|
||||
tokens.append(expect(TokenKind.RIGHT_BRACKET))
|
||||
elif token.kind is TokenKind.RIGHT_BRACKET:
|
||||
action = PathAction.APPEND
|
||||
value = None
|
||||
else:
|
||||
assert_cant_happen()
|
||||
else:
|
||||
assert_cant_happen()
|
||||
# noinspection PyUnboundLocalVariable
|
||||
return Path(
|
||||
kind=action,
|
||||
accessor=value,
|
||||
tokens=tokens,
|
||||
is_root=True
|
||||
)
|
||||
|
||||
yield parse_root()
|
||||
|
||||
# path*
|
||||
while can_advance():
|
||||
path_tokens = [expect(TokenKind.LEFT_BRACKET)]
|
||||
token = expect(TokenKind.TEXT, TokenKind.NUMBER, TokenKind.RIGHT_BRACKET)
|
||||
path_tokens.append(token)
|
||||
if token.kind is TokenKind.RIGHT_BRACKET:
|
||||
path = Path(PathAction.APPEND, tokens=path_tokens)
|
||||
elif token.kind is TokenKind.TEXT:
|
||||
path = Path(PathAction.KEY, token.value, tokens=path_tokens)
|
||||
path_tokens.append(expect(TokenKind.RIGHT_BRACKET))
|
||||
elif token.kind is TokenKind.NUMBER:
|
||||
path = Path(PathAction.INDEX, token.value, tokens=path_tokens)
|
||||
path_tokens.append(expect(TokenKind.RIGHT_BRACKET))
|
||||
else:
|
||||
assert_cant_happen()
|
||||
# noinspection PyUnboundLocalVariable
|
||||
yield path
|
||||
|
||||
|
||||
def tokenize(source: str) -> Iterator[Token]:
|
||||
cursor = 0
|
||||
backslashes = 0
|
||||
buffer = []
|
||||
|
||||
def send_buffer() -> Iterator[Token]:
|
||||
nonlocal backslashes
|
||||
if not buffer:
|
||||
return None
|
||||
|
||||
value = ''.join(buffer)
|
||||
kind = TokenKind.TEXT
|
||||
if not backslashes:
|
||||
for variation, kind in [
|
||||
(int, TokenKind.NUMBER),
|
||||
(check_escaped_int, TokenKind.TEXT),
|
||||
]:
|
||||
try:
|
||||
value = variation(value)
|
||||
except ValueError:
|
||||
continue
|
||||
else:
|
||||
break
|
||||
yield Token(
|
||||
kind=kind,
|
||||
value=value,
|
||||
start=cursor - (len(buffer) + backslashes),
|
||||
end=cursor,
|
||||
)
|
||||
buffer.clear()
|
||||
backslashes = 0
|
||||
|
||||
def can_advance() -> bool:
|
||||
return cursor < len(source)
|
||||
|
||||
while can_advance():
|
||||
index = source[cursor]
|
||||
if index in OPERATORS:
|
||||
yield from send_buffer()
|
||||
yield Token(OPERATORS[index], index, cursor, cursor + 1)
|
||||
elif index == BACKSLASH and can_advance():
|
||||
if source[cursor + 1] in SPECIAL_CHARS:
|
||||
backslashes += 1
|
||||
else:
|
||||
buffer.append(index)
|
||||
buffer.append(source[cursor + 1])
|
||||
cursor += 1
|
||||
else:
|
||||
buffer.append(index)
|
||||
cursor += 1
|
||||
|
||||
yield from send_buffer()
|
||||
|
||||
|
||||
def check_escaped_int(value: str) -> str:
|
||||
if not value.startswith(BACKSLASH):
|
||||
raise ValueError('Not an escaped int')
|
||||
try:
|
||||
int(value[1:])
|
||||
except ValueError as exc:
|
||||
raise ValueError('Not an escaped int') from exc
|
||||
else:
|
||||
return value[1:]
|
||||
|
||||
|
||||
def assert_cant_happen():
|
||||
raise ValueError('Unexpected value')
|
@ -1,80 +0,0 @@
|
||||
from enum import Enum, auto
|
||||
from typing import NamedTuple, Union, Optional, List
|
||||
|
||||
EMPTY_STRING = ''
|
||||
HIGHLIGHTER = '^'
|
||||
OPEN_BRACKET = '['
|
||||
CLOSE_BRACKET = ']'
|
||||
BACKSLASH = '\\'
|
||||
|
||||
|
||||
class TokenKind(Enum):
|
||||
TEXT = auto()
|
||||
NUMBER = auto()
|
||||
LEFT_BRACKET = auto()
|
||||
RIGHT_BRACKET = auto()
|
||||
PSEUDO = auto() # Not a real token, use when representing location only.
|
||||
|
||||
def to_name(self) -> str:
|
||||
for key, value in OPERATORS.items():
|
||||
if value is self:
|
||||
return repr(key)
|
||||
else:
|
||||
return 'a ' + self.name.lower()
|
||||
|
||||
|
||||
OPERATORS = {
|
||||
OPEN_BRACKET: TokenKind.LEFT_BRACKET,
|
||||
CLOSE_BRACKET: TokenKind.RIGHT_BRACKET,
|
||||
}
|
||||
SPECIAL_CHARS = OPERATORS.keys() | {BACKSLASH}
|
||||
LITERAL_TOKENS = [
|
||||
TokenKind.TEXT,
|
||||
TokenKind.NUMBER,
|
||||
]
|
||||
|
||||
|
||||
class Token(NamedTuple):
|
||||
kind: TokenKind
|
||||
value: Union[str, int]
|
||||
start: int
|
||||
end: int
|
||||
|
||||
|
||||
class PathAction(Enum):
|
||||
KEY = auto()
|
||||
INDEX = auto()
|
||||
APPEND = auto()
|
||||
# Pseudo action, used by the interpreter
|
||||
SET = auto()
|
||||
|
||||
def to_string(self) -> str:
|
||||
return self.name.lower()
|
||||
|
||||
|
||||
class Path:
|
||||
def __init__(
|
||||
self,
|
||||
kind: PathAction,
|
||||
accessor: Optional[Union[str, int]] = None,
|
||||
tokens: Optional[List[Token]] = None,
|
||||
is_root: bool = False,
|
||||
):
|
||||
self.kind = kind
|
||||
self.accessor = accessor
|
||||
self.tokens = tokens or []
|
||||
self.is_root = is_root
|
||||
|
||||
def reconstruct(self) -> str:
|
||||
if self.kind is PathAction.KEY:
|
||||
if self.is_root:
|
||||
return str(self.accessor)
|
||||
return OPEN_BRACKET + self.accessor + CLOSE_BRACKET
|
||||
elif self.kind is PathAction.INDEX:
|
||||
return OPEN_BRACKET + str(self.accessor) + CLOSE_BRACKET
|
||||
elif self.kind is PathAction.APPEND:
|
||||
return OPEN_BRACKET + CLOSE_BRACKET
|
||||
|
||||
|
||||
class NestedJSONArray(list):
|
||||
"""Denotes a top-level JSON array."""
|
@ -18,7 +18,7 @@ from .dicts import (
|
||||
)
|
||||
from .exceptions import ParseError
|
||||
from .nested_json import interpret_nested_json
|
||||
from ..utils import get_content_type, load_json_preserve_order_and_dupe_keys, split_iterable
|
||||
from ..utils import get_content_type, load_json_preserve_order_and_dupe_keys, split
|
||||
|
||||
|
||||
class RequestItems:
|
||||
@ -78,28 +78,25 @@ class RequestItems:
|
||||
instance.data,
|
||||
),
|
||||
SEPARATOR_DATA_RAW_JSON: (
|
||||
convert_json_value_to_form_if_needed(
|
||||
in_json_mode=instance.is_json,
|
||||
processor=process_data_raw_json_embed_arg
|
||||
),
|
||||
json_only(instance, process_data_raw_json_embed_arg),
|
||||
instance.data,
|
||||
),
|
||||
SEPARATOR_DATA_EMBED_RAW_JSON_FILE: (
|
||||
convert_json_value_to_form_if_needed(
|
||||
in_json_mode=instance.is_json,
|
||||
processor=process_data_embed_raw_json_file_arg,
|
||||
),
|
||||
json_only(instance, process_data_embed_raw_json_file_arg),
|
||||
instance.data,
|
||||
),
|
||||
}
|
||||
|
||||
if instance.is_json:
|
||||
json_item_args, request_item_args = split_iterable(
|
||||
iterable=request_item_args,
|
||||
key=lambda arg: arg.sep in SEPARATOR_GROUP_NESTED_JSON_ITEMS
|
||||
json_item_args, request_item_args = split(
|
||||
request_item_args,
|
||||
lambda arg: arg.sep in SEPARATOR_GROUP_NESTED_JSON_ITEMS
|
||||
)
|
||||
if json_item_args:
|
||||
pairs = [(arg.key, rules[arg.sep][0](arg)) for arg in json_item_args]
|
||||
pairs = [
|
||||
(arg.key, rules[arg.sep][0](arg))
|
||||
for arg in json_item_args
|
||||
]
|
||||
processor_func, target_dict = rules[SEPARATOR_GROUP_NESTED_JSON_ITEMS]
|
||||
value = processor_func(pairs)
|
||||
target_dict.update(value)
|
||||
@ -162,30 +159,6 @@ def process_file_upload_arg(arg: KeyValueArg) -> Tuple[str, IO, str]:
|
||||
)
|
||||
|
||||
|
||||
def convert_json_value_to_form_if_needed(in_json_mode: bool, processor: Callable[[KeyValueArg], JSONType]) -> Callable[[], str]:
|
||||
"""
|
||||
We allow primitive values to be passed to forms via JSON key/value syntax.
|
||||
|
||||
But complex values lead to an error because there’s no clear way to serialize them.
|
||||
|
||||
"""
|
||||
if in_json_mode:
|
||||
return processor
|
||||
|
||||
@functools.wraps(processor)
|
||||
def wrapper(*args, **kwargs) -> str:
|
||||
try:
|
||||
output = processor(*args, **kwargs)
|
||||
except ParseError:
|
||||
output = None
|
||||
if isinstance(output, (str, int, float)):
|
||||
return str(output)
|
||||
else:
|
||||
raise ParseError('Cannot use complex JSON value types with --form/--multipart.')
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def process_data_item_arg(arg: KeyValueArg) -> str:
|
||||
return arg.value
|
||||
|
||||
@ -194,6 +167,29 @@ def process_data_embed_file_contents_arg(arg: KeyValueArg) -> str:
|
||||
return load_text_file(arg)
|
||||
|
||||
|
||||
def json_only(items: RequestItems, func: Callable[[KeyValueArg], JSONType]) -> str:
|
||||
if items.is_json:
|
||||
return func
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs) -> str:
|
||||
try:
|
||||
ret = func(*args, **kwargs)
|
||||
except ParseError:
|
||||
ret = None
|
||||
|
||||
# If it is a basic type, then allow it
|
||||
if isinstance(ret, (str, int, float)):
|
||||
return str(ret)
|
||||
else:
|
||||
raise ParseError(
|
||||
'Can\'t use complex JSON value types with '
|
||||
'--form/--multipart.'
|
||||
)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def process_data_embed_raw_json_file_arg(arg: KeyValueArg) -> JSONType:
|
||||
contents = load_text_file(arg)
|
||||
value = load_json(arg, contents)
|
||||
|
@ -10,14 +10,12 @@ from urllib.parse import urlparse, urlunparse
|
||||
import requests
|
||||
# noinspection PyPackageRequirements
|
||||
import urllib3
|
||||
from urllib3.util import SKIP_HEADER, SKIPPABLE_HEADERS
|
||||
|
||||
from . import __version__
|
||||
from .adapters import HTTPieHTTPAdapter
|
||||
from .cli.constants import HTTP_OPTIONS
|
||||
from .cli.dicts import HTTPHeadersDict
|
||||
from .cli.nested_json import unwrap_top_level_list_if_needed
|
||||
from .context import Environment
|
||||
from .cli.constants import HTTP_OPTIONS
|
||||
from .cli.nested_json import EMPTY_STRING
|
||||
from .cli.dicts import HTTPHeadersDict, NestedJSONArray
|
||||
from .encoding import UTF8
|
||||
from .models import RequestsMessage
|
||||
from .plugins.registry import plugin_manager
|
||||
@ -143,7 +141,7 @@ def collect_messages(
|
||||
# noinspection PyProtectedMember
|
||||
@contextmanager
|
||||
def max_headers(limit):
|
||||
# <https://github.com/httpie/cli/issues/802>
|
||||
# <https://github.com/httpie/httpie/issues/802>
|
||||
# noinspection PyUnresolvedReferences
|
||||
orig = http.client._MAXHEADERS
|
||||
http.client._MAXHEADERS = limit or float('Inf')
|
||||
@ -199,12 +197,8 @@ def finalize_headers(headers: HTTPHeadersDict) -> HTTPHeadersDict:
|
||||
# Also, requests raises `InvalidHeader` for leading spaces.
|
||||
value = value.strip()
|
||||
if isinstance(value, str):
|
||||
# See <https://github.com/httpie/cli/issues/212>
|
||||
# See <https://github.com/httpie/httpie/issues/212>
|
||||
value = value.encode()
|
||||
elif name.lower() in SKIPPABLE_HEADERS:
|
||||
# Some headers get overwritten by urllib3 when set to `None`
|
||||
# and should be replaced with the `SKIP_HEADER` constant.
|
||||
value = SKIP_HEADER
|
||||
final_headers.add(name, value)
|
||||
return final_headers
|
||||
|
||||
@ -312,13 +306,21 @@ def make_send_kwargs_mergeable_from_env(args: argparse.Namespace) -> dict:
|
||||
|
||||
|
||||
def json_dict_to_request_body(data: Dict[str, Any]) -> str:
|
||||
data = unwrap_top_level_list_if_needed(data)
|
||||
# Propagate the top-level list if there is only one
|
||||
# item in the object, with an en empty key.
|
||||
if len(data) == 1:
|
||||
[(key, value)] = data.items()
|
||||
if isinstance(value, NestedJSONArray):
|
||||
assert key == EMPTY_STRING
|
||||
data = value
|
||||
|
||||
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 = ''
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@ -381,7 +383,7 @@ def ensure_path_as_is(orig_url: str, prepped_url: str) -> str:
|
||||
untouched because other (welcome) processing on the URL might have
|
||||
taken place.
|
||||
|
||||
<https://github.com/httpie/cli/issues/895>
|
||||
<https://github.com/httpie/httpie/issues/895>
|
||||
|
||||
|
||||
<https://ec.haxx.se/http/http-basics#path-as-is>
|
||||
|
@ -145,7 +145,7 @@ class Environment:
|
||||
try:
|
||||
config.load()
|
||||
except ConfigFileError as e:
|
||||
self.log_error(e, level=LogLevel.WARNING)
|
||||
self.log_error(e, level='warning')
|
||||
return config
|
||||
|
||||
@property
|
||||
@ -174,7 +174,7 @@ class Environment:
|
||||
stderr = self._orig_stderr
|
||||
rich_console = self._make_rich_console(file=stderr, force_terminal=stderr.isatty())
|
||||
rich_console.print(
|
||||
f'\n{self.program_name}: {level.value}: {msg}\n\n',
|
||||
f'\n{self.program_name}: {level}: {msg}\n\n',
|
||||
style=LOG_LEVEL_COLORS[level],
|
||||
markup=False,
|
||||
highlight=False,
|
||||
|
@ -11,7 +11,7 @@ from requests import __version__ as requests_version
|
||||
|
||||
from . import __version__ as httpie_version
|
||||
from .cli.constants import OUT_REQ_BODY
|
||||
from .cli.nested_json import NestedJSONSyntaxError
|
||||
from .cli.nested_json import HTTPieSyntaxError
|
||||
from .client import collect_messages
|
||||
from .context import Environment, LogLevel
|
||||
from .downloads import Downloader
|
||||
@ -78,7 +78,7 @@ def raw_main(
|
||||
args=args,
|
||||
env=env,
|
||||
)
|
||||
except NestedJSONSyntaxError as exc:
|
||||
except HTTPieSyntaxError as exc:
|
||||
env.stderr.write(str(exc) + "\n")
|
||||
if include_traceback:
|
||||
raise
|
||||
|
@ -217,7 +217,7 @@ class Downloader:
|
||||
assert not self.status.time_started
|
||||
|
||||
# FIXME: some servers still might sent Content-Encoding: gzip
|
||||
# <https://github.com/httpie/cli/issues/423>
|
||||
# <https://github.com/httpie/httpie/issues/423>
|
||||
try:
|
||||
total_size = int(final_response.headers['Content-Length'])
|
||||
except (KeyError, ValueError, TypeError):
|
||||
|
@ -52,6 +52,7 @@ def program():
|
||||
try:
|
||||
exit_status = main()
|
||||
except KeyboardInterrupt:
|
||||
from httpie.status import ExitStatus
|
||||
exit_status = ExitStatus.ERROR_CTRL_C
|
||||
|
||||
return exit_status
|
||||
|
@ -43,6 +43,7 @@ def _discover_system_pip() -> List[str]:
|
||||
|
||||
|
||||
def _run_pip_subprocess(pip_executable: List[str], args: List[str]) -> bytes:
|
||||
import subprocess
|
||||
|
||||
cmd = [*pip_executable, *args]
|
||||
try:
|
||||
|
@ -1,7 +1,6 @@
|
||||
from time import monotonic
|
||||
|
||||
import requests
|
||||
from urllib3.util import SKIP_HEADER, SKIPPABLE_HEADERS
|
||||
|
||||
from enum import Enum, auto
|
||||
from typing import Iterable, Union, NamedTuple
|
||||
@ -17,6 +16,7 @@ from .cli.constants import (
|
||||
from .compat import cached_property
|
||||
from .utils import split_cookies, parse_content_type_header
|
||||
|
||||
|
||||
ELAPSED_TIME_LABEL = 'Elapsed time'
|
||||
|
||||
|
||||
@ -67,10 +67,27 @@ class HTTPResponse(HTTPMessage):
|
||||
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 = self._orig.raw
|
||||
if getattr(raw, '_original_response', None):
|
||||
raw_version = raw._original_response.version
|
||||
else:
|
||||
raw_version = raw.version
|
||||
except AttributeError:
|
||||
# Assume HTTP/1.1
|
||||
raw_version = 11
|
||||
version = {
|
||||
9: '0.9',
|
||||
10: '1.0',
|
||||
11: '1.1',
|
||||
20: '2.0',
|
||||
}[raw_version]
|
||||
|
||||
original = self._orig
|
||||
status_line = f'HTTP/{self.version} {original.status_code} {original.reason}'
|
||||
status_line = f'HTTP/{version} {original.status_code} {original.reason}'
|
||||
headers = [status_line]
|
||||
headers.extend(
|
||||
': '.join(header)
|
||||
@ -100,32 +117,6 @@ class HTTPResponse(HTTPMessage):
|
||||
for key, value in data.items()
|
||||
)
|
||||
|
||||
@property
|
||||
def version(self) -> str:
|
||||
"""
|
||||
Return the HTTP version used by the server, e.g. '1.1'.
|
||||
|
||||
Assume HTTP/1.1 if version is not available.
|
||||
|
||||
"""
|
||||
mapping = {
|
||||
9: '0.9',
|
||||
10: '1.0',
|
||||
11: '1.1',
|
||||
20: '2.0',
|
||||
}
|
||||
fallback = 11
|
||||
version = None
|
||||
try:
|
||||
raw = self._orig.raw
|
||||
if getattr(raw, '_original_response', None):
|
||||
version = raw._original_response.version
|
||||
else:
|
||||
version = raw.version
|
||||
except AttributeError:
|
||||
pass
|
||||
return mapping[version or fallback]
|
||||
|
||||
|
||||
class HTTPRequest(HTTPMessage):
|
||||
"""A :class:`requests.models.Request` wrapper."""
|
||||
@ -153,7 +144,6 @@ class HTTPRequest(HTTPMessage):
|
||||
headers = [
|
||||
f'{name}: {value if isinstance(value, str) else value.decode()}'
|
||||
for name, value in headers.items()
|
||||
if not (name.lower() in SKIPPABLE_HEADERS and value == SKIP_HEADER)
|
||||
]
|
||||
|
||||
headers.insert(0, request_line)
|
||||
|
@ -4,22 +4,23 @@ import subprocess
|
||||
import os
|
||||
from httpie.context import Environment
|
||||
|
||||
|
||||
MAN_COMMAND = 'man'
|
||||
NO_MAN_PAGES = os.getenv('HTTPIE_NO_MAN_PAGES', False)
|
||||
|
||||
# On some systems, HTTP(n) might exist, but we are only interested in HTTP(1).
|
||||
# For more information on man page sections: <https://unix.stackexchange.com/a/138643>
|
||||
# On some systems, HTTP(n) might exist but we are only
|
||||
# interested in HTTP(1).
|
||||
#
|
||||
# For more information on man page sections: https://unix.stackexchange.com/a/138643
|
||||
|
||||
MAN_PAGE_SECTION = '1'
|
||||
|
||||
|
||||
def is_available(program: str) -> bool:
|
||||
"""
|
||||
Check whether `program`'s man pages are available on this system.
|
||||
"""Check whether HTTPie's man pages are available in this system."""
|
||||
|
||||
"""
|
||||
if NO_MAN_PAGES or os.system == 'nt':
|
||||
return False
|
||||
|
||||
try:
|
||||
process = subprocess.run(
|
||||
[MAN_COMMAND, MAN_PAGE_SECTION, program],
|
||||
@ -28,7 +29,7 @@ def is_available(program: str) -> bool:
|
||||
stderr=subprocess.DEVNULL
|
||||
)
|
||||
except Exception:
|
||||
# There might be some errors outside the process, e.g
|
||||
# There might be some errors outside of the process, e.g
|
||||
# a permission error to execute something that is not an
|
||||
# executable.
|
||||
return False
|
||||
@ -37,10 +38,8 @@ def is_available(program: str) -> bool:
|
||||
|
||||
|
||||
def display_for(env: Environment, program: str) -> None:
|
||||
"""
|
||||
Open the system man page for the given command (http/https/httpie).
|
||||
"""Display the man page for the given command (http/https)."""
|
||||
|
||||
"""
|
||||
subprocess.run(
|
||||
[MAN_COMMAND, MAN_PAGE_SECTION, program],
|
||||
stdout=env.stdout,
|
||||
|
@ -24,7 +24,7 @@ def enable_highlighter(
|
||||
console: Console,
|
||||
highlighter: Highlighter,
|
||||
) -> Iterator[Console]:
|
||||
"""Enable a highlighter temporarily."""
|
||||
"""Enable a higlighter temporarily."""
|
||||
|
||||
original_highlighter = console.highlighter
|
||||
try:
|
||||
|
@ -19,7 +19,7 @@ class HTTPBasicAuth(requests.auth.HTTPBasicAuth):
|
||||
"""
|
||||
Override username/password serialization to allow unicode.
|
||||
|
||||
See https://github.com/httpie/cli/issues/212
|
||||
See https://github.com/httpie/httpie/issues/212
|
||||
|
||||
"""
|
||||
# noinspection PyTypeChecker
|
||||
|
@ -4,11 +4,12 @@ from typing import NamedTuple, Optional
|
||||
from httpie.adapters import HTTPAdapter
|
||||
# noinspection PyPackageRequirements
|
||||
from urllib3.util.ssl_ import (
|
||||
create_urllib3_context,
|
||||
DEFAULT_CIPHERS, create_urllib3_context,
|
||||
resolve_ssl_version,
|
||||
)
|
||||
|
||||
|
||||
DEFAULT_SSL_CIPHERS = DEFAULT_CIPHERS
|
||||
SSL_VERSION_ARG_MAPPING = {
|
||||
'ssl2.3': 'PROTOCOL_SSLv23',
|
||||
'ssl3': 'PROTOCOL_SSLv3',
|
||||
@ -80,10 +81,6 @@ class HTTPieHTTPSAdapter(HTTPAdapter):
|
||||
cert_reqs=ssl.CERT_REQUIRED if verify else ssl.CERT_NONE
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_default_ciphers_names(cls):
|
||||
return [cipher['name'] for cipher in cls._create_ssl_context(verify=False).get_ciphers()]
|
||||
|
||||
|
||||
def _is_key_file_encrypted(key_file):
|
||||
"""Detects if a key file is encrypted or not.
|
||||
@ -97,9 +94,3 @@ def _is_key_file_encrypted(key_file):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
# We used to import the default set of TLS ciphers from urllib3, but they removed it.
|
||||
# Instead, now urllib3 uses the list of ciphers configured by the system.
|
||||
# <https://github.com/httpie/cli/pull/1501>
|
||||
DEFAULT_SSL_CIPHERS_STRING = ':'.join(HTTPieHTTPSAdapter.get_default_ciphers_names())
|
||||
|
@ -245,7 +245,7 @@ def get_site_paths(path: Path) -> Iterable[Path]:
|
||||
yield as_site(path)
|
||||
|
||||
|
||||
def split_iterable(iterable: Iterable[T], key: Callable[[T], bool]) -> Tuple[List[T], List[T]]:
|
||||
def split(iterable: Iterable[T], key: Callable[[T], bool]) -> Tuple[List[T], List[T]]:
|
||||
left, right = [], []
|
||||
for item in iterable:
|
||||
if key(item):
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Please keep all characters in this file in ASCII
|
||||
# distutils uses system's locale to interpret it and not everybody
|
||||
# uses UTF-8. See https://github.com/httpie/cli/issues/1039
|
||||
# uses UTF-8. See https://github.com/httpie/httpie/issues/1039
|
||||
# for an example
|
||||
[wheel]
|
||||
|
||||
|
4
setup.py
4
setup.py
@ -77,7 +77,7 @@ setup(
|
||||
long_description=long_description(),
|
||||
long_description_content_type='text/markdown',
|
||||
url='https://httpie.io/',
|
||||
download_url=f'https://github.com/httpie/cli/archive/{httpie.__version__}.tar.gz',
|
||||
download_url=f'https://github.com/httpie/httpie/archive/{httpie.__version__}.tar.gz',
|
||||
author=httpie.__author__,
|
||||
author_email='jakub@roztocil.co',
|
||||
license=httpie.__licence__,
|
||||
@ -108,7 +108,7 @@ setup(
|
||||
'Topic :: Utilities'
|
||||
],
|
||||
project_urls={
|
||||
'GitHub': 'https://github.com/httpie/cli',
|
||||
'GitHub': 'https://github.com/httpie/httpie',
|
||||
'Twitter': 'https://twitter.com/httpie',
|
||||
'Discord': 'https://httpie.io/discord',
|
||||
'Documentation': 'https://httpie.io/docs',
|
||||
|
@ -31,7 +31,7 @@ description: |
|
||||
Links
|
||||
- Documentation: https://httpie.io/docs
|
||||
- Try in browser: https://httpie.io/run
|
||||
- GitHub: https://github.com/httpie/cli
|
||||
- GitHub: https://github.com/httpie/httpie
|
||||
- Twitter: https://twitter.com/httpie
|
||||
- Discord: https://httpie.io/chat
|
||||
license: BSD-3-Clause-LBNL
|
||||
|
@ -1,3 +1,3 @@
|
||||
# HTTPie Test Suite
|
||||
|
||||
Please see [CONTRIBUTING](https://github.com/httpie/cli/blob/master/CONTRIBUTING.md) for contribution and testing guidelines.
|
||||
Please see [CONTRIBUTING](https://github.com/httpie/httpie/blob/master/CONTRIBUTING.md) for contribution and testing guidelines.
|
||||
|
@ -71,7 +71,7 @@ def test_credentials_in_url_auth_flag_has_priority(httpbin_both):
|
||||
])
|
||||
def test_only_username_in_url(url):
|
||||
"""
|
||||
https://github.com/httpie/cli/issues/242
|
||||
https://github.com/httpie/httpie/issues/242
|
||||
|
||||
"""
|
||||
args = httpie.cli.definition.parser.parse_args(args=[url], env=MockEnvironment())
|
||||
|
@ -11,7 +11,7 @@ from .fixtures import FILE_PATH
|
||||
|
||||
def test_default_headers_case_insensitive(httpbin):
|
||||
"""
|
||||
<https://github.com/httpie/cli/issues/644>
|
||||
<https://github.com/httpie/httpie/issues/644>
|
||||
"""
|
||||
r = http(
|
||||
'--debug',
|
||||
@ -68,7 +68,7 @@ class TestAutoContentTypeAndAcceptHeaders:
|
||||
"""
|
||||
|
||||
def test_GET_no_data_no_auto_headers(self, httpbin):
|
||||
# https://github.com/httpie/cli/issues/62
|
||||
# https://github.com/httpie/httpie/issues/62
|
||||
r = http('GET', httpbin.url + '/headers')
|
||||
assert HTTP_OK in r
|
||||
assert r.json['headers']['Accept'] == '*/*'
|
||||
@ -99,7 +99,7 @@ class TestAutoContentTypeAndAcceptHeaders:
|
||||
assert HTTP_OK in r
|
||||
assert r.json['headers']['Accept'] == JSON_ACCEPT
|
||||
# Make sure Content-Type gets set even with no data.
|
||||
# https://github.com/httpie/cli/issues/137
|
||||
# https://github.com/httpie/httpie/issues/137
|
||||
assert 'application/json' in r.json['headers']['Content-Type']
|
||||
|
||||
def test_GET_explicit_JSON_explicit_headers(self, httpbin):
|
||||
|
@ -36,7 +36,7 @@ def test_debug():
|
||||
def test_help():
|
||||
r = http('--help', tolerate_error_exit_status=True)
|
||||
assert r.exit_status == ExitStatus.SUCCESS
|
||||
assert 'https://github.com/httpie/cli/issues' in r
|
||||
assert 'https://github.com/httpie/httpie/issues' in r
|
||||
|
||||
|
||||
def test_version():
|
||||
@ -124,7 +124,7 @@ def test_POST_file(httpbin_both):
|
||||
|
||||
def test_form_POST_file_redirected_stdin(httpbin):
|
||||
"""
|
||||
<https://github.com/httpie/cli/issues/840>
|
||||
<https://github.com/httpie/httpie/issues/840>
|
||||
|
||||
"""
|
||||
with open(FILE_PATH, encoding=UTF8):
|
||||
@ -196,14 +196,6 @@ def test_unset_host_header(httpbin_both):
|
||||
assert 'Host' not in r.json['headers'] # default Host unset
|
||||
|
||||
|
||||
def test_unset_useragent_header(httpbin_both):
|
||||
r = http('GET', httpbin_both + '/headers')
|
||||
assert 'User-Agent' in r.json['headers'] # default User-Agent present
|
||||
|
||||
r = http('GET', httpbin_both + '/headers', 'User-Agent:')
|
||||
assert 'User-Agent' not in r.json['headers'] # default User-Agent unset
|
||||
|
||||
|
||||
def test_headers_empty_value(httpbin_both):
|
||||
r = http('GET', httpbin_both + '/headers')
|
||||
assert r.json['headers']['Accept'] # default Accept has value
|
||||
|
@ -5,7 +5,7 @@ import responses
|
||||
|
||||
from httpie.cli.constants import PRETTY_MAP
|
||||
from httpie.cli.exceptions import ParseError
|
||||
from httpie.cli.nested_json import NestedJSONSyntaxError
|
||||
from httpie.cli.nested_json import HTTPieSyntaxError
|
||||
from httpie.output.formatters.colors import ColorFormatter
|
||||
from httpie.utils import JsonDictPreservingDuplicateKeys
|
||||
|
||||
@ -157,7 +157,7 @@ def test_complex_json_arguments_with_non_json(httpbin, request_type, value):
|
||||
f'option:={json.dumps(value)}',
|
||||
)
|
||||
|
||||
cm.match('Cannot use complex JSON value types')
|
||||
cm.match("Can't use complex JSON value types")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@ -508,23 +508,23 @@ def test_nested_json_syntax(input_json, expected_json, httpbin):
|
||||
),
|
||||
(
|
||||
['foo=1', 'foo[key]:=2'],
|
||||
"HTTPie Type Error: Cannot perform 'key' based access on 'foo' which has a type of 'string' but this operation requires a type of 'object'.\nfoo[key]\n ^^^^^",
|
||||
"HTTPie Type Error: Can't perform 'key' based access on 'foo' which has a type of 'string' but this operation requires a type of 'object'.\nfoo[key]\n ^^^^^",
|
||||
),
|
||||
(
|
||||
['foo=1', 'foo[0]:=2'],
|
||||
"HTTPie Type Error: Cannot perform 'index' based access on 'foo' which has a type of 'string' but this operation requires a type of 'array'.\nfoo[0]\n ^^^",
|
||||
"HTTPie Type Error: Can't perform 'index' based access on 'foo' which has a type of 'string' but this operation requires a type of 'array'.\nfoo[0]\n ^^^",
|
||||
),
|
||||
(
|
||||
['foo=1', 'foo[]:=2'],
|
||||
"HTTPie Type Error: Cannot perform 'append' based access on 'foo' which has a type of 'string' but this operation requires a type of 'array'.\nfoo[]\n ^^",
|
||||
"HTTPie Type Error: Can't perform 'append' based access on 'foo' which has a type of 'string' but this operation requires a type of 'array'.\nfoo[]\n ^^",
|
||||
),
|
||||
(
|
||||
['data[key]=value', 'data[key 2]=value 2', 'data[0]=value'],
|
||||
"HTTPie Type Error: Cannot perform 'index' based access on 'data' which has a type of 'object' but this operation requires a type of 'array'.\ndata[0]\n ^^^",
|
||||
"HTTPie Type Error: Can't perform 'index' based access on 'data' which has a type of 'object' but this operation requires a type of 'array'.\ndata[0]\n ^^^",
|
||||
),
|
||||
(
|
||||
['data[key]=value', 'data[key 2]=value 2', 'data[]=value'],
|
||||
"HTTPie Type Error: Cannot perform 'append' based access on 'data' which has a type of 'object' but this operation requires a type of 'array'.\ndata[]\n ^^",
|
||||
"HTTPie Type Error: Can't perform 'append' based access on 'data' which has a type of 'object' but this operation requires a type of 'array'.\ndata[]\n ^^",
|
||||
),
|
||||
(
|
||||
[
|
||||
@ -532,7 +532,7 @@ def test_nested_json_syntax(input_json, expected_json, httpbin):
|
||||
'foo[bar][baz][5][]:=4',
|
||||
'foo[bar][baz][key][]:=5',
|
||||
],
|
||||
"HTTPie Type Error: Cannot perform 'key' based access on 'foo[bar][baz]' which has a type of 'array' but this operation requires a type of 'object'.\nfoo[bar][baz][key][]\n ^^^^^",
|
||||
"HTTPie Type Error: Can't perform 'key' based access on 'foo[bar][baz]' which has a type of 'array' but this operation requires a type of 'object'.\nfoo[bar][baz][key][]\n ^^^^^",
|
||||
),
|
||||
(
|
||||
['foo[-10]:=[1,2]'],
|
||||
@ -540,32 +540,32 @@ def test_nested_json_syntax(input_json, expected_json, httpbin):
|
||||
),
|
||||
(
|
||||
['foo[0]:=1', 'foo[]:=2', 'foo[\\2]:=3'],
|
||||
"HTTPie Type Error: Cannot perform 'key' based access on 'foo' which has a type of 'array' but this operation requires a type of 'object'.\nfoo[\\2]\n ^^^^",
|
||||
"HTTPie Type Error: Can't perform 'key' based access on 'foo' which has a type of 'array' but this operation requires a type of 'object'.\nfoo[\\2]\n ^^^^",
|
||||
),
|
||||
(
|
||||
['foo[\\1]:=2', 'foo[5]:=3'],
|
||||
"HTTPie Type Error: Cannot perform 'index' based access on 'foo' which has a type of 'object' but this operation requires a type of 'array'.\nfoo[5]\n ^^^",
|
||||
"HTTPie Type Error: Can't perform 'index' based access on 'foo' which has a type of 'object' but this operation requires a type of 'array'.\nfoo[5]\n ^^^",
|
||||
),
|
||||
(
|
||||
['x=y', '[]:=2'],
|
||||
"HTTPie Type Error: Cannot perform 'append' based access on '' which has a type of 'object' but this operation requires a type of 'array'.",
|
||||
"HTTPie Type Error: Can't perform 'append' based access on '' which has a type of 'object' but this operation requires a type of 'array'.",
|
||||
),
|
||||
(
|
||||
['[]:=2', 'x=y'],
|
||||
"HTTPie Type Error: Cannot perform 'key' based access on '' which has a type of 'array' but this operation requires a type of 'object'.",
|
||||
"HTTPie Type Error: Can't perform 'key' based access on '' which has a type of 'array' but this operation requires a type of 'object'.",
|
||||
),
|
||||
(
|
||||
[':=[1,2,3]', '[]:=4'],
|
||||
"HTTPie Type Error: Cannot perform 'append' based access on '' which has a type of 'object' but this operation requires a type of 'array'.",
|
||||
"HTTPie Type Error: Can't perform 'append' based access on '' which has a type of 'object' but this operation requires a type of 'array'.",
|
||||
),
|
||||
(
|
||||
['[]:=4', ':=[1,2,3]'],
|
||||
"HTTPie Type Error: Cannot perform 'key' based access on '' which has a type of 'array' but this operation requires a type of 'object'.",
|
||||
"HTTPie Type Error: Can't perform 'key' based access on '' which has a type of 'array' but this operation requires a type of 'object'.",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_nested_json_errors(input_json, expected_error, httpbin):
|
||||
with pytest.raises(NestedJSONSyntaxError) as exc:
|
||||
with pytest.raises(HTTPieSyntaxError) as exc:
|
||||
http(httpbin + '/post', *input_json)
|
||||
|
||||
exc_lines = str(exc.value).splitlines()
|
||||
|
@ -199,7 +199,7 @@ class TestVerboseFlag:
|
||||
assert 'foo bar' in r
|
||||
|
||||
def test_verbose_form(self, httpbin):
|
||||
# https://github.com/httpie/cli/issues/53
|
||||
# https://github.com/httpie/httpie/issues/53
|
||||
r = http('--verbose', '--form', 'POST', httpbin.url + '/post',
|
||||
'A=B', 'C=D')
|
||||
assert HTTP_OK in r
|
||||
|
@ -117,8 +117,6 @@ def test_plugins_double_uninstall(httpie_plugins, httpie_plugins_success, dummy_
|
||||
)
|
||||
|
||||
|
||||
# TODO: Make this work on CI (stopped working at some point)
|
||||
@pytest.mark.skip(reason='Doesn’t work in CI')
|
||||
@pytest.mark.requires_installation
|
||||
def test_plugins_upgrade(httpie_plugins, httpie_plugins_success, dummy_plugin):
|
||||
httpie_plugins_success("install", dummy_plugin.path)
|
||||
|
@ -26,7 +26,7 @@ def test_follow_without_all_redirects_hidden(httpbin, follow_flag):
|
||||
assert HTTP_OK in r
|
||||
|
||||
|
||||
@pytest.mark.xfail(True, reason="https://github.com/httpie/cli/issues/1082")
|
||||
@pytest.mark.xfail(True, reason="https://github.com/httpie/httpie/issues/1082")
|
||||
def test_follow_output_options_used_for_redirects(httpbin):
|
||||
r = http('--follow', '--print=H', httpbin.url + '/redirect/2')
|
||||
assert r.count('GET /') == 1
|
||||
|
@ -1,14 +1,17 @@
|
||||
"""Miscellaneous regression tests"""
|
||||
import pytest
|
||||
|
||||
from httpie.cli.argtypes import KeyValueArgType
|
||||
from httpie.cli.constants import SEPARATOR_HEADER, SEPARATOR_QUERY_PARAM, SEPARATOR_DATA_STRING
|
||||
from httpie.cli.requestitems import RequestItems
|
||||
from httpie.compat import is_windows
|
||||
from .utils.matching import assert_output_matches, Expect
|
||||
from .utils import HTTP_OK, MockEnvironment, http
|
||||
from .utils.matching import assert_output_matches, Expect
|
||||
|
||||
|
||||
def test_Host_header_overwrite(httpbin):
|
||||
"""
|
||||
https://github.com/httpie/cli/issues/235
|
||||
https://github.com/httpie/httpie/issues/235
|
||||
|
||||
"""
|
||||
host = 'pie.dev'
|
||||
@ -22,7 +25,7 @@ def test_Host_header_overwrite(httpbin):
|
||||
@pytest.mark.skipif(is_windows, reason='Unix-only')
|
||||
def test_output_devnull(httpbin):
|
||||
"""
|
||||
https://github.com/httpie/cli/issues/252
|
||||
https://github.com/httpie/httpie/issues/252
|
||||
|
||||
"""
|
||||
http('--output=/dev/null', httpbin + '/get')
|
||||
@ -31,7 +34,7 @@ def test_output_devnull(httpbin):
|
||||
def test_verbose_redirected_stdout_separator(httpbin):
|
||||
"""
|
||||
|
||||
<https://github.com/httpie/cli/issues/1006>
|
||||
<https://github.com/httpie/httpie/issues/1006>
|
||||
"""
|
||||
r = http(
|
||||
'-v',
|
||||
@ -47,3 +50,21 @@ def test_verbose_redirected_stdout_separator(httpbin):
|
||||
Expect.RESPONSE_HEADERS,
|
||||
Expect.BODY,
|
||||
])
|
||||
|
||||
|
||||
@pytest.mark.parametrize(['separator', 'target'], [
|
||||
(SEPARATOR_HEADER, 'headers'),
|
||||
(SEPARATOR_QUERY_PARAM, 'params'),
|
||||
(SEPARATOR_DATA_STRING, 'data'),
|
||||
])
|
||||
def test_initial_backslash_number(separator, target):
|
||||
"""
|
||||
<https://github.com/httpie/httpie/issues/1408>
|
||||
"""
|
||||
back_digit = r'\0'
|
||||
raw_arg = back_digit + separator + back_digit
|
||||
expected_parsed_data = {back_digit: back_digit}
|
||||
parsed_arg = KeyValueArgType(separator)(raw_arg)
|
||||
items = RequestItems.from_args([parsed_arg])
|
||||
parsed_data = getattr(items, target)
|
||||
assert parsed_data == expected_parsed_data
|
||||
|
@ -203,7 +203,7 @@ class TestSession(SessionTestBase):
|
||||
|
||||
def test_session_with_cookie_followed_by_another_header(self, httpbin):
|
||||
"""
|
||||
Make sure headers don’t get mutated — <https://github.com/httpie/cli/issues/1126>
|
||||
Make sure headers don’t get mutated — <https://github.com/httpie/httpie/issues/1126>
|
||||
"""
|
||||
self.start_session(httpbin)
|
||||
session_data = {
|
||||
@ -239,7 +239,7 @@ class TestSession(SessionTestBase):
|
||||
|
||||
def test_session_default_header_value_overwritten(self, httpbin):
|
||||
self.start_session(httpbin)
|
||||
# https://github.com/httpie/cli/issues/180
|
||||
# https://github.com/httpie/httpie/issues/180
|
||||
r1 = http('--session=test',
|
||||
httpbin.url + '/headers', 'User-Agent:custom',
|
||||
env=self.env())
|
||||
@ -251,7 +251,7 @@ class TestSession(SessionTestBase):
|
||||
assert r2.json['headers']['User-Agent'] == 'custom'
|
||||
|
||||
def test_download_in_session(self, tmp_path, httpbin):
|
||||
# https://github.com/httpie/cli/issues/412
|
||||
# https://github.com/httpie/httpie/issues/412
|
||||
self.start_session(httpbin)
|
||||
cwd = os.getcwd()
|
||||
os.chdir(tmp_path)
|
||||
@ -335,7 +335,7 @@ class TestSession(SessionTestBase):
|
||||
assert HTTP_OK in r1
|
||||
assert HTTP_OK in r2
|
||||
|
||||
# additional test for issue: https://github.com/httpie/cli/issues/1098
|
||||
# additional test for issue: https://github.com/httpie/httpie/issues/1098
|
||||
with open(session_path) as session_file:
|
||||
session_file_lines = ''.join(session_file.readlines())
|
||||
assert "\"type\": \"test-prompted\"" in session_file_lines
|
||||
@ -427,7 +427,7 @@ class TestExpiredCookies(CookieTestBase):
|
||||
),
|
||||
(
|
||||
# Checks we gracefully ignore expires date in invalid format.
|
||||
# <https://github.com/httpie/cli/issues/963>
|
||||
# <https://github.com/httpie/httpie/issues/963>
|
||||
'pfg=; Expires=Sat, 19-Sep-2020 06:58:14 GMT+0000; Max-Age=0; path=/; domain=.tumblr.com; secure; HttpOnly',
|
||||
None,
|
||||
[]
|
||||
@ -446,7 +446,7 @@ class TestExpiredCookies(CookieTestBase):
|
||||
class TestCookieStorage(CookieTestBase):
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
['specified_cookie_header', 'new_cookies_dict', 'expected_effective_cookie_header'],
|
||||
'new_cookies, new_cookies_dict, expected',
|
||||
[(
|
||||
'new=bar',
|
||||
{'new': 'bar'},
|
||||
@ -463,9 +463,9 @@ class TestCookieStorage(CookieTestBase):
|
||||
'chocolate=milk; cookie1=foo; cookie2=foo; new=bar'
|
||||
),
|
||||
(
|
||||
'new=bar; chocolate=milk',
|
||||
'new=bar;; chocolate=milk;;;',
|
||||
{'new': 'bar', 'chocolate': 'milk'},
|
||||
'cookie1=foo; cookie2=foo; new=bar; chocolate=milk'
|
||||
'cookie1=foo; cookie2=foo; new=bar'
|
||||
),
|
||||
(
|
||||
'new=bar; chocolate=milk;;;',
|
||||
@ -474,35 +474,20 @@ class TestCookieStorage(CookieTestBase):
|
||||
)
|
||||
]
|
||||
)
|
||||
def test_existing_and_new_cookies_sent_in_request(
|
||||
self,
|
||||
specified_cookie_header,
|
||||
new_cookies_dict,
|
||||
expected_effective_cookie_header,
|
||||
httpbin,
|
||||
):
|
||||
def test_existing_and_new_cookies_sent_in_request(self, new_cookies, new_cookies_dict, expected, httpbin):
|
||||
r = http(
|
||||
'--session', str(self.session_path),
|
||||
'--print=H',
|
||||
httpbin.url,
|
||||
'Cookie:' + specified_cookie_header,
|
||||
'Cookie:' + new_cookies,
|
||||
)
|
||||
parsed_request_headers = { # noqa
|
||||
name: value for name, value in [
|
||||
line.split(': ', 1)
|
||||
for line in r.splitlines()
|
||||
if line and ':' in line
|
||||
]
|
||||
}
|
||||
# Note: cookies in the request are in an undefined order.
|
||||
expected_request_cookie_set = set(expected_effective_cookie_header.split('; '))
|
||||
actual_request_cookie_set = set(parsed_request_headers['Cookie'].split('; '))
|
||||
assert actual_request_cookie_set == expected_request_cookie_set
|
||||
# Note: cookies in response are in alphabetical order
|
||||
assert f'Cookie: {expected}' in r
|
||||
|
||||
updated_session = json.loads(self.session_path.read_text(encoding=UTF8))
|
||||
assert 'Cookie' not in updated_session['headers']
|
||||
for name, value in new_cookies_dict.items():
|
||||
assert updated_session['cookies'][name]['value'] == value
|
||||
assert name, value in updated_session['cookies']
|
||||
assert 'Cookie' not in updated_session['headers']
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'cli_cookie, set_cookie, expected',
|
||||
|
@ -7,7 +7,7 @@ import urllib3
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from httpie.ssl_ import AVAILABLE_SSL_VERSION_ARG_MAPPING, DEFAULT_SSL_CIPHERS_STRING
|
||||
from httpie.ssl_ import AVAILABLE_SSL_VERSION_ARG_MAPPING, DEFAULT_SSL_CIPHERS
|
||||
from httpie.status import ExitStatus
|
||||
|
||||
from .utils import HTTP_OK, TESTS_ROOT, IS_PYOPENSSL, http
|
||||
@ -15,7 +15,7 @@ from .utils import HTTP_OK, TESTS_ROOT, IS_PYOPENSSL, http
|
||||
|
||||
try:
|
||||
# Handle OpenSSL errors, if installed.
|
||||
# See <https://github.com/httpie/cli/issues/729>
|
||||
# See <https://github.com/httpie/httpie/issues/729>
|
||||
# noinspection PyUnresolvedReferences
|
||||
import OpenSSL.SSL
|
||||
ssl_errors = (
|
||||
@ -146,7 +146,7 @@ def test_ciphers(httpbin_secure):
|
||||
r = http(
|
||||
httpbin_secure.url + '/get',
|
||||
'--ciphers',
|
||||
DEFAULT_SSL_CIPHERS_STRING,
|
||||
DEFAULT_SSL_CIPHERS,
|
||||
)
|
||||
assert HTTP_OK in r
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user