Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0d8cc69
Merge pull request #3 from viminizer/master
viminizer Feb 15, 2026
fce8e6f
feat(storage): add Postman v2.1 auth data model
viminizer Feb 15, 2026
80ae06d
feat(app): add in-memory auth state model with TextArea editors
viminizer Feb 15, 2026
db63d6f
feat(app): add Auth tab to request panel navigation
viminizer Feb 15, 2026
7d8ec6f
feat(ui): render auth tab with type selector and per-type field layout
viminizer Feb 15, 2026
e0a3210
feat(app): add auth type popup and field editing interactions
viminizer Feb 15, 2026
f8c6717
feat(http): inject auth into requests and persist to Postman collection
viminizer Feb 15, 2026
0ecb096
docs(auth): add authentication feature documentation
viminizer Feb 15, 2026
1368d19
Merge pull request #4 from viminizer/feat/authentication-support
viminizer Feb 15, 2026
e089faf
feat(storage): add environment variable data model and file I/O
viminizer Feb 15, 2026
636b5bc
feat(app): load environments at startup and track active environment
viminizer Feb 15, 2026
f61d3f0
feat(env): add Ctrl+N environment switcher popup, status bar indicato…
viminizer Feb 15, 2026
4886a01
docs(env): add environment variables feature documentation
viminizer Feb 15, 2026
73958c7
Merge pull request #6 from viminizer/feat/environment-variables
viminizer Feb 15, 2026
54973c7
feat(storage): extend Postman body model for all body types
viminizer Feb 15, 2026
59efc15
feat(app): add body mode state model with form pairs and multipart fi…
viminizer Feb 15, 2026
23c13d2
feat(app): add body type selector popup and mode switching
viminizer Feb 15, 2026
9f73cba
feat(http): add Content-Type auto-injection for JSON and XML body modes
viminizer Feb 15, 2026
81c5711
feat(app): add key-value pair editor with vim integration
viminizer Feb 15, 2026
fd9d6f8
feat(app): reset body mode state on request switch and mode change
viminizer Feb 15, 2026
65fa9ee
Merge pull request #8 from viminizer/feat/request-body-types
viminizer Feb 15, 2026
d568581
docs: add request body types documentation and planning files
viminizer Feb 15, 2026
2d255c9
feat(response): add size display, copy, and save-to-file
viminizer Feb 17, 2026
b545138
feat(response): add vim-style body search with highlighting
viminizer Feb 17, 2026
f4d2999
feat(response): add search functionality for response body
viminizer Feb 17, 2026
afa4bb2
feat(ui): update help overlay and status bar for new response features
viminizer Feb 17, 2026
4ba3760
fix: resolve all clippy warnings across codebase
viminizer Feb 17, 2026
cc6cf8c
docs: update plan with completed acceptance criteria
viminizer Feb 17, 2026
669ae8a
docs: add comprehensive response panel documentation
viminizer Feb 17, 2026
45541cc
chore(todos): mark all p1 issues as completed
viminizer Feb 18, 2026
91c9a3d
chore(todos): mark all p2 issues as completed
viminizer Feb 18, 2026
7caccb9
chore(todos): resolve all p3 issues
viminizer Feb 18, 2026
b464375
chore(todos): remove all resolved todo files
viminizer Feb 18, 2026
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
55 changes: 55 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ edition = "2021"
ratatui = "0.29"
crossterm = "0.28"
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.12", features = ["json", "native-tls"] }
reqwest = { version = "0.12", features = ["json", "native-tls", "multipart", "stream"] }
futures-util = "0.3"
anyhow = "1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
Expand Down
222 changes: 222 additions & 0 deletions docs/authentication.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
# Authentication

Perseus supports per-request authentication, allowing you to attach credentials to individual API requests. Auth settings are configured through a dedicated **Auth tab** in the request panel and are automatically injected into outgoing requests.

## Supported Auth Types

| Type | Description | How it's sent |
|------|-------------|---------------|
| **No Auth** | No authentication (default) | Nothing added to the request |
| **Bearer Token** | OAuth 2.0 / JWT token | `Authorization: Bearer <token>` header |
| **Basic Auth** | Username and password | `Authorization: Basic <base64>` header |
| **API Key** | Custom key-value pair | Header or query parameter (configurable) |

## Getting Started

### Opening the Auth Tab

The Auth tab sits between the Headers and Body tabs in the request panel:

```
Headers | Auth | Body
```

Navigate to the Auth tab using:

- `Ctrl+L` or `Ctrl+H` to cycle between request tabs (Headers, Auth, Body)
- `Tab` to switch panels, then navigate to the Auth tab

The tab label dynamically reflects the active auth type (e.g., `Auth (Bearer)`, `Auth (Basic)`).

### Selecting an Auth Type

1. Navigate to the Auth tab — the `Type: [No Auth]` selector is at the top
2. Press `Enter` on the type selector to open the auth type popup
3. Use `j`/`k` or arrow keys to highlight a type
4. Press `Enter` to confirm, or `Esc` to cancel

When you select a new auth type, the previous type's fields are cleared and the cursor moves to the first editable field.

## Auth Type Details

### No Auth

The default state. Displays "No authentication configured" and sends no auth-related headers or parameters. Use this to explicitly disable authentication for a request.

### Bearer Token

For OAuth 2.0 access tokens, JWTs, or any token-based authentication.

**Fields:**

| Field | Description |
|-------|-------------|
| Token | The bearer token value |

**What happens at send time:**

Perseus adds the header:
```
Authorization: Bearer <your-token>
```

**Example usage:** Authenticating with a GitHub API personal access token, an OAuth 2.0 access token, or a JWT issued by your auth server.

### Basic Auth

For HTTP Basic authentication using a username and password.

**Fields:**

| Field | Description |
|-------|-------------|
| Username | The authentication username |
| Password | The authentication password |

**What happens at send time:**

Perseus Base64-encodes the `username:password` pair and adds the header:
```
Authorization: Basic <base64-encoded-credentials>
```

**Example usage:** Authenticating with APIs that require HTTP Basic auth, such as private package registries, legacy REST APIs, or services behind basic auth proxies.

### API Key

For services that authenticate via a custom key-value pair sent as a header or query parameter.

**Fields:**

| Field | Description |
|-------|-------------|
| Key | The parameter name (e.g., `X-API-Key`, `api_key`) |
| Value | The parameter value (your API key) |
| Add to | Where to send the key — `Header` or `Query Param` |

**What happens at send time:**

- **Header mode:** Perseus adds a custom header with your key and value:
```
X-API-Key: your-api-key-value
```
- **Query Param mode:** Perseus appends the key-value pair to the URL query string:
```
https://api.example.com/data?api_key=your-api-key-value
```

To toggle the location between Header and Query Param, navigate to the `Add to: [Header]` field and press `Enter`.

**Example usage:** Authenticating with services like OpenAI (`Authorization` header), Google Maps (`key` query param), or any API that uses custom API key headers.

## Navigation and Editing

### Navigating Auth Fields

Within the Auth tab, fields are arranged vertically. Navigate between them using:

| Key | Action |
|-----|--------|
| `j` / `Down` | Move to the next field |
| `k` / `Up` | Move to the previous field |

Navigation wraps at the boundaries: pressing `k` on the type selector moves focus to the URL bar above; pressing `j` past the last field moves focus to the response panel below.

### Editing Text Fields

Auth text fields (Token, Username, Password, Key, Value) use the same vim-based editing as the rest of Perseus:

1. Navigate to a text field (it highlights green when focused)
2. Press `Enter` or `i` to enter editing mode
3. Edit using vim keybindings (insert mode, normal mode, visual mode)
4. Press `Esc` to exit back to navigation mode

All standard vim operations work in auth fields: word motions (`w`, `b`, `e`), text objects (`ciw`, `diw`), yank/paste (`y`, `p`), visual selection (`v`), and clipboard integration (`Ctrl+C` to copy, `Ctrl+V` to paste).

### The Type Selector and Location Toggle

The `Type: [...]` selector and `Add to: [...]` toggle are not text fields — they open popups or cycle values when you press `Enter`:

- **Type selector:** Opens a popup list to choose the auth type
- **Location toggle:** Cycles between `Header` and `Query Param`

## Persistence

Auth settings are saved as part of the Postman Collection v2.1 format used by Perseus for request storage. When you save a request, its auth configuration is persisted alongside the method, URL, headers, and body.

### Storage Format

Auth data is stored in the `auth` field of each request in the collection JSON file:

**Bearer Token:**
```json
{
"auth": {
"type": "bearer",
"bearer": [
{ "key": "token", "value": "your-token-here", "type": "string" }
]
}
}
```

**Basic Auth:**
```json
{
"auth": {
"type": "basic",
"basic": [
{ "key": "username", "value": "your-username", "type": "string" },
{ "key": "password", "value": "your-password", "type": "string" }
]
}
}
```

**API Key:**
```json
{
"auth": {
"type": "apikey",
"apikey": [
{ "key": "key", "value": "X-API-Key", "type": "string" },
{ "key": "value", "value": "your-api-key", "type": "string" },
{ "key": "in", "value": "header", "type": "string" }
]
}
}
```

The `"in"` field for API Key auth accepts `"header"` or `"queryparams"`.

### Postman Compatibility

The auth storage format is fully compatible with Postman Collection v2.1. This means:

- Collections exported from Postman with auth settings are correctly loaded by Perseus
- Collections saved by Perseus with auth settings can be imported into Postman
- Auth type, credentials, and API key location are preserved in both directions

## Keyboard Reference

Quick reference for all auth-related keybindings:

| Context | Key | Action |
|---------|-----|--------|
| Request panel | `Ctrl+L` / `Ctrl+H` | Switch between Headers / Auth / Body tabs |
| Auth tab (navigation) | `j` / `Down` | Next auth field |
| Auth tab (navigation) | `k` / `Up` | Previous auth field |
| Auth tab (navigation) | `Enter` | Open type popup, toggle location, or enter editing |
| Auth tab (navigation) | `i` | Enter vim insert mode on text fields |
| Auth type popup | `j` / `Down` | Highlight next type |
| Auth type popup | `k` / `Up` | Highlight previous type |
| Auth type popup | `Enter` | Confirm selection |
| Auth type popup | `Esc` | Cancel and close popup |
| Auth field (editing) | `Esc` | Exit editing, return to navigation |
| Any mode | `Ctrl+R` | Send request (auth is auto-injected) |

## Auth and Manual Headers

Auth credentials are injected **before** custom headers are applied. If you set auth to Bearer Token and also manually add an `Authorization` header in the Headers tab, the manual header will take precedence (reqwest appends both, and servers typically use the last value).

To avoid conflicts, use either the Auth tab or manual headers for authentication — not both.
Loading