forked from extern/httpie-cli
Formalize @ suffix for all operators (#1225)
* Formalize @ suffix for all operators * Separate the section * Address suggestions
This commit is contained in:
parent
e09401b81a
commit
be87da8bbd
@ -518,6 +518,12 @@ $ http https://api.github.com/search/repositories q==httpie per_page==1
|
||||
GET /search/repositories?q=httpie&per_page=1 HTTP/1.1
|
||||
```
|
||||
|
||||
You can even retrieve the `value` from a file by using the `param==@file` syntax. This would also effectively strip the newlines from the end. See [#file-based-separators] for more examples.
|
||||
|
||||
```bash
|
||||
$ http pie.dev/get text==@files/text.txt
|
||||
```
|
||||
|
||||
### URL shortcuts for `localhost`
|
||||
|
||||
Additionally, curl-like shorthand for localhost is supported.
|
||||
@ -596,21 +602,48 @@ GET /../../etc/password HTTP/1.1
|
||||
|
||||
## Request items
|
||||
|
||||
There are a few different *request item* types that provide a convenient mechanism for specifying HTTP headers, simple JSON and form data, files, and URL parameters.
|
||||
There are a few different *request item* types that provide a convenient
|
||||
mechanism for specifying HTTP headers, JSON and form data, files,
|
||||
and URL parameters. This is a very practical way of constructing
|
||||
HTTP requests from scratch on the CLI.
|
||||
|
||||
They are key/value pairs specified after the URL. All have in common that they become part of the actual request that is sent and that their type is distinguished only by the separator used: `:`, `=`, `:=`, `==`, `@`, `=@`, `:=@` and `==@`. The ones with an `@` expect a file path as value.
|
||||
Each *request item* is simply a key/value pair separated with the following
|
||||
characters: `:` (headers), `=` (data field, e.g JSON, Form), `:=` (raw data field)
|
||||
`==` (query parameters), `@` (file upload).
|
||||
|
||||
```bash
|
||||
$ http PUT pie.dev/put \
|
||||
X-Date:today \ # Header
|
||||
token==secret \ # Query parameter
|
||||
name=John \ # Data field
|
||||
age:=29 # Raw JSON
|
||||
```
|
||||
|
||||
| Item Type | Description |
|
||||
| -----------------------------------------------------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| HTTP Headers `Name:Value` | Arbitrary HTTP header, e.g. `X-API-Token:123` |
|
||||
| URL parameters `name==value` | Appends the given name/value pair as a querystring parameter to the URL. The `==` separator is used. For reading the value from a file, use `==@`. |
|
||||
| Data Fields `field=value`, `field=@file.txt` | Request data fields to be serialized as a JSON object (default), to be form-encoded (with `--form, -f`), or to be serialized as `multipart/form-data` (with `--multipart`) |
|
||||
| URL parameters `name==value` | Appends the given name/value pair as a querystring parameter to the URL. The `==` separator is used. |
|
||||
| Data Fields `field=value` | Request data fields to be serialized as a JSON object (default), to be form-encoded (with `--form, -f`), or to be serialized as `multipart/form-data` (with `--multipart`) |
|
||||
| Raw JSON fields `field:=json` | Useful when sending JSON and one or more fields need to be a `Boolean`, `Number`, nested `Object`, or an `Array`, e.g., `meals:='["ham","spam"]'` or `pies:=[1,2,3]` (note the quotes) |
|
||||
| File upload fields `field@/dir/file`, `field@file;type=mime` | Only available with `--form`, `-f` and `--multipart`. For example `screenshot@~/Pictures/img.png`, or `'cv@cv.txt;type=text/markdown'`. With `--form`, the presence of a file field results in a `--multipart` request |
|
||||
|
||||
Note that the structured data fields aren’t the only way to specify request data:
|
||||
[raw request body](#raw-request-body) is a mechanism for passing arbitrary request data.
|
||||
|
||||
### File based separators
|
||||
|
||||
Using file contents as values for specific fields is a very common use case, which can be achieved through adding the `@` suffix to
|
||||
the operators above. For example instead of using a static string as the value for some header, you can use `:@` operator
|
||||
to pass the desired value from a file.
|
||||
|
||||
```bash
|
||||
$ http POST pie.dev/post \
|
||||
X-Data:@files/text.txt # Read a header from a file
|
||||
token==@files/text.txt # Read a query parameter from a file
|
||||
name=@files/text.txt # Read a data field's value from a file
|
||||
bookmarks:=@files/data.json # Embed a JSON object from a file
|
||||
```
|
||||
|
||||
### Escaping rules
|
||||
|
||||
You can use `\` to escape characters that shouldn’t be used as separators (or parts thereof). For instance, `foo\==bar` will become a data key/value pair (`foo=` and `bar`) instead of a URL parameter.
|
||||
@ -1108,6 +1141,14 @@ Host: <taken-from-URL>
|
||||
|
||||
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] for more examples.
|
||||
|
||||
```bash
|
||||
$ http pie.dev/headers X-Data:@files/text.txt
|
||||
```
|
||||
|
||||
### Empty headers and header un-setting
|
||||
|
||||
To unset a previously specified header (such a one of the default headers), use `Header:`:
|
||||
|
@ -15,6 +15,7 @@ SEPARATOR_HEADER = ':'
|
||||
SEPARATOR_HEADER_EMPTY = ';'
|
||||
SEPARATOR_CREDENTIALS = ':'
|
||||
SEPARATOR_PROXY = ':'
|
||||
SEPARATOR_HEADER_EMBED = ':@'
|
||||
SEPARATOR_DATA_STRING = '='
|
||||
SEPARATOR_DATA_RAW_JSON = ':='
|
||||
SEPARATOR_FILE_UPLOAD = '@'
|
||||
@ -41,6 +42,7 @@ SEPARATORS_GROUP_MULTIPART = frozenset({
|
||||
|
||||
# Separators for items whose value is a filename to be embedded
|
||||
SEPARATOR_GROUP_DATA_EMBED_ITEMS = frozenset({
|
||||
SEPARATOR_HEADER_EMBED,
|
||||
SEPARATOR_QUERY_EMBED_FILE,
|
||||
SEPARATOR_DATA_EMBED_FILE_CONTENTS,
|
||||
SEPARATOR_DATA_EMBED_RAW_JSON_FILE,
|
||||
@ -56,6 +58,7 @@ SEPARATOR_GROUP_NESTED_JSON_ITEMS = frozenset([
|
||||
SEPARATOR_GROUP_ALL_ITEMS = frozenset({
|
||||
SEPARATOR_HEADER,
|
||||
SEPARATOR_HEADER_EMPTY,
|
||||
SEPARATOR_HEADER_EMBED,
|
||||
SEPARATOR_QUERY_PARAM,
|
||||
SEPARATOR_QUERY_EMBED_FILE,
|
||||
SEPARATOR_DATA_STRING,
|
||||
|
@ -8,7 +8,8 @@ from .constants import (
|
||||
SEPARATOR_DATA_EMBED_RAW_JSON_FILE, SEPARATOR_GROUP_NESTED_JSON_ITEMS,
|
||||
SEPARATOR_DATA_RAW_JSON, SEPARATOR_DATA_STRING, SEPARATOR_FILE_UPLOAD,
|
||||
SEPARATOR_FILE_UPLOAD_TYPE, SEPARATOR_HEADER, SEPARATOR_HEADER_EMPTY,
|
||||
SEPARATOR_QUERY_PARAM, SEPARATOR_QUERY_EMBED_FILE, RequestType
|
||||
SEPARATOR_HEADER_EMBED, SEPARATOR_QUERY_PARAM,
|
||||
SEPARATOR_QUERY_EMBED_FILE, RequestType
|
||||
)
|
||||
from .dicts import (
|
||||
BaseMultiDict, MultipartRequestDataDict, RequestDataDict,
|
||||
@ -48,6 +49,10 @@ class RequestItems:
|
||||
process_empty_header_arg,
|
||||
instance.headers,
|
||||
),
|
||||
SEPARATOR_HEADER_EMBED: (
|
||||
process_embed_header_arg,
|
||||
instance.headers,
|
||||
),
|
||||
SEPARATOR_QUERY_PARAM: (
|
||||
process_query_param_arg,
|
||||
instance.params,
|
||||
@ -119,6 +124,10 @@ def process_header_arg(arg: KeyValueArg) -> Optional[str]:
|
||||
return arg.value or None
|
||||
|
||||
|
||||
def process_embed_header_arg(arg: KeyValueArg) -> str:
|
||||
return load_text_file(arg).rstrip('\n')
|
||||
|
||||
|
||||
def process_empty_header_arg(arg: KeyValueArg) -> str:
|
||||
if not arg.value:
|
||||
return arg.value
|
||||
|
@ -85,6 +85,7 @@ class TestItemParsing:
|
||||
self.key_value_arg('bool:=true'),
|
||||
self.key_value_arg('file@' + FILE_PATH_ARG),
|
||||
self.key_value_arg('query==value'),
|
||||
self.key_value_arg('Embedded-Header:@' + FILE_PATH_ARG),
|
||||
self.key_value_arg('string-embed=@' + FILE_PATH_ARG),
|
||||
self.key_value_arg('param-embed==@' + FILE_PATH_ARG),
|
||||
self.key_value_arg('raw-json-embed:=@' + JSON_FILE_PATH_ARG),
|
||||
@ -96,7 +97,8 @@ class TestItemParsing:
|
||||
assert headers == {
|
||||
'Header': 'value',
|
||||
'Unset-Header': None,
|
||||
'Empty-Header': ''
|
||||
'Empty-Header': '',
|
||||
'Embedded-Header': FILE_CONTENT.rstrip('\n')
|
||||
}
|
||||
|
||||
# Parsed data
|
||||
|
Loading…
Reference in New Issue
Block a user