diff --git a/README.md b/README.md index dbc0b811..e28ec58f 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Slumber is a TUI (terminal user interface) HTTP client. Define, execute, and sha - Source-first configuration, for easy persistence and sharing - [Import from external formats (e.g. Insomnia)](https://slumber.lucaspickering.me/book/user_guide/import.html) - [Build requests dynamically from other requests, files, and shell commands](https://slumber.lucaspickering.me/book/user_guide/templates.html) -- [Browse response data using JSONPath selectors](https://slumber.lucaspickering.me/book/user_guide/filter_query.html) +- [Browse response data using JSONPath selectors](https://slumber.lucaspickering.me/book/user_guide/tui/filter_query.html) - Switch between different environments easily using [profiles](https://slumber.lucaspickering.me/book/api/request_collection/profile.html) - And more! diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 7cec1556..204d8982 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -9,11 +9,11 @@ - [Key Concepts](./user_guide/key_concepts.md) - [Terminal User Interface (TUI)](./user_guide/tui/index.md) - [In-App Editing & File Viewing](./user_guide/tui/editor.md) + - [Data Filtering & Querying](./user_guide/tui/filter_query.md) - [Command Line Interface (CLI)](./user_guide/cli.md) - [Templates](./user_guide/templates.md) - [Chains - Complex Template Values](./user_guide/chains.md) - [Collection Reuse & Inheritance](./user_guide/inheritance.md) -- [Data Filtering & Querying](./user_guide/filter_query.md) - [Importing External Collections](./user_guide/import.md) # CLI Commands diff --git a/docs/src/api/configuration/index.md b/docs/src/api/configuration/index.md index e4956986..380ca5a9 100644 --- a/docs/src/api/configuration/index.md +++ b/docs/src/api/configuration/index.md @@ -40,7 +40,7 @@ The following fields are available in `config.yml`: **Default:** `[sh, -c]` (Unix), `[cmd, /S, /C]` (Windows) -Shell used to execute commands within the TUI. [More info](#commands) +Shell used to execute commands within the TUI. Use `[]` for no shell (commands will be parsed and executed directly). [More info](../../user_guide/tui/filter_query.md) ### `commands.query_default` @@ -48,7 +48,7 @@ Shell used to execute commands within the TUI. [More info](#commands) **Default:** `""` -Default query command for all responses. [More info](#commands) +Default query command for all responses. [More info](../../user_guide/tui/filter_query.md) ### `debug` diff --git a/docs/src/api/request_collection/chain.md b/docs/src/api/request_collection/chain.md index 4bb91bac..d3d965f9 100644 --- a/docs/src/api/request_collection/chain.md +++ b/docs/src/api/request_collection/chain.md @@ -6,6 +6,8 @@ To use a chain in a template, reference it as `{{chains.}}`. ## Fields + + | Field | Type | Description | Default | | --------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | | `source` | [`ChainSource`](./chain_source.md) | Source of the chained value | Required | diff --git a/docs/src/api/request_collection/content_type.md b/docs/src/api/request_collection/content_type.md index 7a1610c2..fbc565e4 100644 --- a/docs/src/api/request_collection/content_type.md +++ b/docs/src/api/request_collection/content_type.md @@ -1,6 +1,6 @@ # Content Type -Content type defines the various data formats that Slumber recognizes and can manipulate. Slumber is capable of displaying any text-based data format, but only specific formats support additional features such as [querying](../../user_guide/filter_query.md) and formatting. +Content type defines the various data formats that Slumber recognizes and can manipulate. Slumber is capable of displaying any text-based data format, but only specific formats support additional features such as [querying](../../user_guide/tui/filter_query.md) and formatting. ## Auto-detection diff --git a/docs/src/images/query.gif b/docs/src/images/query.gif deleted file mode 100644 index 8c7d73dd..00000000 Binary files a/docs/src/images/query.gif and /dev/null differ diff --git a/docs/src/images/query_error.gif b/docs/src/images/query_error.gif new file mode 100644 index 00000000..f7f5e535 Binary files /dev/null and b/docs/src/images/query_error.gif differ diff --git a/docs/src/images/query_jq.gif b/docs/src/images/query_jq.gif new file mode 100644 index 00000000..e2b8d4d5 Binary files /dev/null and b/docs/src/images/query_jq.gif differ diff --git a/docs/src/images/query_pipe.gif b/docs/src/images/query_pipe.gif new file mode 100644 index 00000000..a3d5364b Binary files /dev/null and b/docs/src/images/query_pipe.gif differ diff --git a/docs/src/user_guide/chains.md b/docs/src/user_guide/chains.md index b10c8d84..40089475 100644 --- a/docs/src/user_guide/chains.md +++ b/docs/src/user_guide/chains.md @@ -1,5 +1,7 @@ # Chains + + Chains are Slumber's most powerful feature. They allow you to dynamically build requests based on other responses, shell commands, and more. ## Chains in Practice @@ -36,6 +38,7 @@ requests: authentication: !bearer "{{chains.auth_token}}" ``` + > For more info on the `selector` field, see [Data Filtering & Querying](./filter_query.md) ### Automatically Executing the Upstream Request diff --git a/docs/src/user_guide/filter_query.md b/docs/src/user_guide/filter_query.md deleted file mode 100644 index d36f5faf..00000000 --- a/docs/src/user_guide/filter_query.md +++ /dev/null @@ -1,107 +0,0 @@ -# Data Filtering & Querying - -Slumber supports querying data structures to transform or reduce response data. - -There are two main use cases for querying: - -- In [chained template values](../api/request_collection/chain.md), to extract data - - Provided via chain's `selector` argument -- In the TUI response body browser, to limit the response data shown - -**Regardless of data format, querying is done via [JSONPath](https://www.ietf.org/archive/id/draft-goessner-dispatch-jsonpath-00.html).** For non-JSON formats, the data will be converted to JSON, queried, and converted back. This keeps querying simple and uniform across data types. - -## Querying Chained Values - -Here's some examples of using queries to extract data from a chained value. Let's say you have two chained value sources. The first is a JSON file, called `creds.json`. It has the following contents: - -```json -{ "user": "fishman", "pw": "hunter2" } -``` - -We'll use these credentials to log in and get an API token, so the second data source is the login response, which looks like so: - -```json -{ "token": "abcdef123" } -``` - -```yaml -chains: - username: - # Slumber knows how to query this file based on its extension - source: !file - path: ./creds.json - selector: $.user - password: - source: !file - path: ./creds.json - selector: $.pw - auth_token: - source: !request - recipe: login - selector: $.token - -requests: - login: !request - method: POST - url: "https://myfishes.fish/anything/login" - body: - !json { - "username": "{{chains.username}}", - "password": "{{chains.password}}", - } - - get_user: !request - method: GET - url: "https://myfishes.fish/anything/current-user" - query: - - auth={{chains.auth_token}} -``` - -While this example simple extracts inner fields, JSONPath can be used for much more powerful transformations. See the [JSONPath docs](https://www.ietf.org/archive/id/draft-goessner-dispatch-jsonpath-00.html) or [this JSONPath editor](https://jsonpath.com/) for more examples. - -### More Powerful Querying with Nested Chains - -If JSONPath isn't enough for the data extraction you need, you can use nested chains to filter with whatever external programs you want. For example, if you want to use `jq` instead: - -```yaml -chains: - username: - source: !file - path: ./creds.json - selector: $.user - password: - source: !file - path: ./creds.json - selector: $.pw - auth_token_raw: - source: !request - recipe: login - auth_token: - source: !command - command: [ "jq", ".token" ] - stdin: "{{chains.auth_token_raw}} - -requests: - login: !request - method: POST - url: "https://myfishes.fish/anything/login" - body: !json - { - "username": "{{chains.username}}", - "password": "{{chains.password}}" - } - - get_user: !request - method: GET - url: "https://myfishes.fish/anything/current-user" - query: - - auth={{chains.auth_token}} -``` - -You can use this capability to manipulate responses via `grep`, `awk`, or any other program you like. - -## Querying Response in TUI - -You can visually query a response body using the filter box at the bottom: - -![Querying response via JSONPath](../images/query.gif) diff --git a/docs/src/user_guide/tui/filter_query.md b/docs/src/user_guide/tui/filter_query.md new file mode 100644 index 00000000..b00ae992 --- /dev/null +++ b/docs/src/user_guide/tui/filter_query.md @@ -0,0 +1,32 @@ +# Data Filtering & Querying + +When browsing an HTTP response in Slumber, you may want to filter, query, or otherwise transform the response to make it easier to view. Slumber supports this via embedded shell commands. The query box at the bottom of the response pane allows you to execute any shell command, which will be passed the response body via stdin and its output will be shown in the response pane. You can use `grep`, `jq`, `sed`, or any other text processing tool. + +![Querying response via jq](../../images/query_jq.gif) + +_Example of querying with jq_ + +![Querying response with pipes](../../images/query_pipe.gif) + +_Example of using pipes in a query command_ + +## Side Effects + +Keep in mind that your queries are being executed as shell commands on your system. You should avoid running any commands that interact with the file system, such as using `>` or `<` to pipe to/from files. TODO add more about side-effect commands once implemented + +## Errors + +We can't all be perfect. Sometimes you run a command that fails. To view the error, press `?` (make sure you exit the text box first!). + +![View query error](../../images/query_error.gif) + +## Which shell does Slumber use? + +By default, Slumber executes your command via `sh -c` on Unix and `cmd /S /C` on Windows. You can customize this via the [`commands.shell` configuration field](../../api/configuration/index.md#commandsshell). For example, to use `fish` instead of `sh`: + +```yaml +commands: + shell: [fish, -c] +``` + +If you don't want to execute via _any_ shell, you can set it to `[]`. In this case, query commands will be parsed via [shell-words](https://docs.rs/shell-words/latest/shell_words/) and executed directly. For example, `jq .args` will be parsed into `["jq", ".args"]`, then `jq` will be executed with a single argument: `.args`. diff --git a/gifs.py b/gifs.py index 92050b05..e4b75f27 100755 --- a/gifs.py +++ b/gifs.py @@ -35,9 +35,6 @@ def generate_all(tapes: list[str]) -> None: tapes = get_tapes() print(f"Generating GIFs for: {tapes}") - print("Deleting data/") - shutil.rmtree("data/") - run(["cargo", "build"]) for tape in tapes: generate(tape) @@ -45,8 +42,8 @@ def generate_all(tapes: list[str]) -> None: def generate(tape: str) -> None: - gif = get_gif_path(tape) - print(f"Generating {tape} -> {gif}") + print("Deleting data/") + shutil.rmtree("data/") run(["vhs", tape]) diff --git a/tapes/query_error.tape b/tapes/query_error.tape new file mode 100644 index 00000000..e7e49877 --- /dev/null +++ b/tapes/query_error.tape @@ -0,0 +1,29 @@ +Output "docs/src/images/query_error.gif" +Set Shell bash +Set Width 1200 +Set Height 800 +Set FontSize 18 +Set Framerate 24 +Set Margin 0 +Set Padding 10 +Set Theme "MaterialDark" + +Hide +Type "cargo run" +Enter +Sleep 2s + +Enter # Send login request +Type "hunter2" +Enter +Sleep 2s +Type "rf" # Fullscreen response pane +Show + +Type "/" +Sleep 1s +Type "jq error!" +Enter +Sleep 1s +Type "?" +Sleep 3s diff --git a/tapes/query.tape b/tapes/query_jq.tape similarity index 85% rename from tapes/query.tape rename to tapes/query_jq.tape index 06530ee0..db6f9564 100644 --- a/tapes/query.tape +++ b/tapes/query_jq.tape @@ -1,4 +1,4 @@ -Output "docs/src/images/query.gif" +Output "docs/src/images/query_jq.gif" Set Shell bash Set Width 1200 Set Height 800 @@ -12,6 +12,7 @@ Hide Type "cargo run" Enter Sleep 2s + Enter # Send login request Type "hunter2" Enter @@ -22,7 +23,7 @@ Show Sleep 1s Type "/" Sleep 1s -Type "$.args" +Type "jq .args" Sleep 2s Type ".fast" Sleep 2s diff --git a/tapes/query_pipe.tape b/tapes/query_pipe.tape new file mode 100644 index 00000000..a5d9266b --- /dev/null +++ b/tapes/query_pipe.tape @@ -0,0 +1,26 @@ +Output "docs/src/images/query_pipe.gif" +Set Shell bash +Set Width 1200 +Set Height 800 +Set FontSize 18 +Set Framerate 24 +Set Margin 0 +Set Padding 10 +Set Theme "MaterialDark" + +Hide +Type "cargo run" +Enter +Sleep 2s + +Enter # Send login request +Type "hunter2" +Enter +Sleep 2s +Type "rf" # Fullscreen response pane +Show + +Type "/" +Sleep 1s +Type "jq .args | head -n 3" +Sleep 2s