Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- **Compression**: automatic gzip and zstd response body decompression
- **Authentication**: support for Basic Auth, Bearer Token, and AWS Signature V4
- **Form body**: send multipart or urlencoded form bodies
- **gRPC support**: make gRPC calls with automatic JSON-to-protobuf conversion
- **Editor integration**: use an editor to modify the request body
- **Configuration**: global and per-host configuration
- _and more!_
Expand Down
20 changes: 20 additions & 0 deletions docs/CONFIG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ option = host_specific_value
### Auto-Update Options

#### `auto-update`

**Type**: Boolean or duration interval
**Default**: `false` (disabled)

Expand All @@ -66,6 +67,7 @@ auto-update = 1d
### Output Control Options

#### `color` / `colour`

**Type**: String
**Values**: `auto`, `off`, `on`
**Default**: `auto`
Expand All @@ -84,6 +86,7 @@ color = on
```

#### `format`

**Type**: String
**Values**: `auto`, `off`, `on`
**Default**: `auto`
Expand All @@ -102,6 +105,7 @@ format = on
```

#### `image`

**Type**: String
**Values**: `auto`, `native`, `off`
**Default**: `auto`
Expand All @@ -120,6 +124,7 @@ image = off
```

#### `no-pager`

**Type**: Boolean
**Default**: `false`

Expand All @@ -134,6 +139,7 @@ no-pager = false
```

#### `silent`

**Type**: Boolean
**Default**: `false`

Expand All @@ -148,6 +154,7 @@ silent = false
```

#### `verbosity`

**Type**: Integer
**Values**: `0` or greater
**Default**: `0`
Expand All @@ -171,6 +178,7 @@ verbosity = 3
### Network Options

#### `ca-cert`

**Type**: CA certificate path
**Default**: System default

Expand All @@ -182,6 +190,7 @@ ca-cert = ca-cert.pem
```

#### `dns-server`

**Type**: IP address with optional port, or HTTPS URL
**Default**: System default

Expand All @@ -203,6 +212,7 @@ dns-server = https://dns.google/dns-query
```

#### `proxy`

**Type**: URL
**Default**: None

Expand All @@ -220,6 +230,7 @@ proxy = socks5://localhost:1080
```

#### `timeout`

**Type**: Number (seconds)
**Default**: System default

Expand All @@ -234,6 +245,7 @@ timeout = 2.5
```

#### `redirects`

**Type**: Integer
**Default**: System default

Expand All @@ -248,6 +260,7 @@ redirects = 10
```

#### `http`

**Type**: String
**Values**: `1`, `2`, `3`

Expand All @@ -262,6 +275,7 @@ http = 2
```

#### `tls`

**Type**: String
**Values**: `1.0`, `1.1`, `1.2`, `1.3`
**Default**: System default
Expand All @@ -277,6 +291,7 @@ tls = 1.3
```

#### `insecure`

**Type**: Boolean
**Default**: `false`

Expand All @@ -291,6 +306,7 @@ insecure = false
```

#### `no-encode`

**Type**: Boolean
**Default**: `false`

Expand All @@ -307,6 +323,7 @@ no-encode = false
### Request Options

#### `header`

**Type**: String (name:value format)
**Repeatable**: Yes

Expand All @@ -323,6 +340,7 @@ header = User-Agent: MyApp/1.0
```

#### `query`

**Type**: String (key=value format)
**Repeatable**: Yes

Expand All @@ -339,6 +357,7 @@ query = sort=name
```

#### `ignore-status`

**Type**: Boolean
**Default**: `false`

Expand Down Expand Up @@ -453,6 +472,7 @@ config file '/home/user/.config/fetch/config': line 15: invalid option: 'invalid
```

Common validation errors include:

- Invalid option names
- Invalid values for specific options (e.g., `color = invalid`)
- Malformed key=value pairs
Expand Down
139 changes: 139 additions & 0 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ fetch --timeout 2.5 example.com
**Flag**: `--dns-server IP[:PORT]|URL`

Use a custom DNS server. Can be either:

- IP address with optional port for UDP DNS
- HTTPS URL for DNS-over-HTTPS

Expand Down Expand Up @@ -333,6 +334,7 @@ fetch --colour on example.com
Set whether output should be formatted. Options: `auto`, `off`, `on`.

Supported formats for automatic formatting and syntax highlighting:

- JSON (`application/json`)
- HTML (`text/html`)
- XML (`application/xml`, `text/xml`)
Expand Down Expand Up @@ -519,6 +521,143 @@ fetch -j '{"message": "Hello \"World\""}' example.com
fetch -H 'Authorization: Bearer token-with-$pecial-chars' example.com
```

## gRPC Support

`fetch` supports making gRPC calls with automatic protocol handling, JSON-to-protobuf conversion, and response formatting.

### Basic gRPC Request

**Flag**: `--grpc`

Enable gRPC mode. This flag:

- Uses the HTTP/2 protocol
- Sets the method to `POST`
- Adds gRPC headers (`Content-Type: application/grpc+proto`, `TE: trailers`, etc.)
- Applies gRPC framing to the request body
- Handles gRPC framing on the response

The service and method are specified in the URL path in the format `/package.Service/Method`:

```sh
fetch https://localhost:50051/mypackage.MyService/MyMethod --grpc --insecure
```

### Proto Schema Options

To enable JSON-to-protobuf conversion for request bodies and rich protobuf formatting for responses, provide a proto schema using one of these options:

**Flag**: `--proto-file PATH`

Compile `.proto` file(s) using `protoc`. Requires `protoc` to be installed. Can be specified multiple times or with comma-separated paths.

```sh
fetch https://localhost:50051/echo.EchoService/Echo \
--grpc \
--proto-file service.proto \
-j '{"message": "hello", "count": 42}' \
--insecure
```

**Flag**: `--proto-desc PATH`

Use a pre-compiled descriptor set file. This is useful when `protoc` isn't available at runtime or to avoid recompilation.

Generate a descriptor set with:

```sh
protoc --descriptor_set_out=service.pb --include_imports service.proto
```

Then use it:

```sh
fetch https://localhost:50051/echo.EchoService/Echo \
--grpc \
--proto-desc service.pb \
-j '{"message": "hello", "count": 42}' \
--insecure
```

**Flag**: `--proto-import PATH`

Add import paths for proto compilation. Use with `--proto-file` when your proto files have imports.

```sh
fetch https://localhost:50051/mypackage.MyService/MyMethod \
--grpc \
--proto-file service.proto \
--proto-import ./proto \
--proto-import /usr/local/include \
-j '{"field": "value"}' \
--insecure
```

### How It Works

When `--grpc` is used with a proto schema (`--proto-file` or `--proto-desc`):

1. The service and method are extracted from the URL path
2. The method's input/output message types are looked up in the schema
3. JSON request bodies are automatically converted to protobuf
4. Protobuf responses are formatted with field names from the schema

Without a proto schema, `fetch` still handles gRPC framing but:

- Request bodies must be raw protobuf (not JSON)
- Responses are formatted using generic protobuf parsing (field numbers instead of names)

### Examples

**Simple gRPC call with JSON body:**

```sh
fetch https://api.example.com/package.Service/Method \
--grpc \
--proto-file service.proto \
-j '{"name": "test", "value": 123}'
```

**gRPC call with verbose output:**

```sh
fetch https://api.example.com/package.Service/Method \
--grpc \
--proto-file service.proto \
-j '{"request": "data"}' \
-vv
```

**gRPC call to local server with self-signed certificate:**

```sh
fetch https://localhost:50051/echo.EchoService/Echo \
--grpc \
--proto-desc echo.pb \
-j '{"message": "hello"}' \
--insecure
```

**Dry run to inspect the request:**

```sh
fetch https://api.example.com/package.Service/Method \
--grpc \
--proto-file service.proto \
-j '{"field": "value"}' \
--dry-run
```

**Use an editor to modify the request body:**

```sh
fetch https://api.example.com/package.Service/Method \
--grpc \
--proto-file service.proto \
-j '{"field": "value"}' \
--edit
```

## Advanced Usage

### Combining Options
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ github.com/clipperhouse/uax29/v2 v2.2.0 h1:ChwIKnQN3kcZteTXMgb1wztSgaU+ZemkgWdoh
github.com/clipperhouse/uax29/v2 v2.2.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
Expand Down
Loading