Rewrite and condense documentation, fix factual errors

Condense most pages to concise reference format. Add Import.md.
Fix: history file is history.json not session.json, import uses
URL input not file picker, getVariable() returns null not undefined.
Pavel Baksy 2026-05-18 17:37:35 +02:00
parent f92677d207
commit f034dc5a9e
13 changed files with 346 additions and 2172 deletions

@ -1,575 +1,86 @@
# API Reference # API Reference
Complete JavaScript API reference for Roster preprocessing and postprocessing scripts. JavaScript API available in Roster [[Scripts]].
## Overview **Language:** JavaScript (ES5+) via GJS
**Execution:** Synchronous, sandboxed
Roster provides a JavaScript API accessible from [[Scripts]] for automating request modifications and response processing. ## Request Object (preprocessing only)
**Language:** JavaScript (ES5+) | Property | Type | Description |
**Runtime:** GJS (GNOME JavaScript) |----------|------|-------------|
**Context:** Sandboxed, synchronous execution | `request.method` | string | `"GET"`, `"POST"`, `"PUT"`, `"DELETE"` |
| `request.url` | string | Full URL |
| `request.headers` | object | Header key-value pairs |
| `request.body` | string | Request body |
## Global Objects All properties are writable.
### Preprocessing Script Context ## Response Object (postprocessing only)
Available in preprocessing scripts only: | Property | Type | Description |
|----------|------|-------------|
| `response.body` | string | Response body |
| `response.headers` | object | Header key-value pairs |
| `response.statusCode` | number | HTTP status code |
| `response.statusText` | string | Status text (`"OK"`, ...) |
| `response.responseTime` | number | Response time in ms |
```javascript All properties are read-only.
request // Modifiable request object
roster // Roster API (with getVariable)
console // Console output
```
### Postprocessing Script Context ## Roster API (both contexts)
Available in postprocessing scripts only: | Method | Available in | Description |
|--------|-------------|-------------|
| `roster.getVariable(name)` | preprocessing | Returns string or `null` |
| `roster.setVariable(name, value)` | both | Creates or updates variable |
| `roster.setVariables({...})` | both | Batch set |
| `roster.project.name` | preprocessing | Current project name |
| `roster.project.environments` | preprocessing | Array of environment names |
```javascript Variable names must match `/^\w+$/` (alphanumeric + underscore). Values are always strings. Sensitive variables are automatically routed to/from GNOME Keyring.
response // Read-only response object
roster // Roster API (without getVariable)
console // Console output
```
## Request Object ## Console
**Available in:** Preprocessing scripts only `console.log(...)` and `console.error(...)` — output appears in the Preprocessing/Postprocessing results tab.
**Type:** Mutable
### Properties ## Available Built-ins
#### `request.method` Standard JS built-ins: `Date`, `JSON`, `Math`, `String`, `Array`, `Object`, etc.
**Type:** `string` No `fetch`, `setTimeout`, `require`, or file system access.
**Values:** `"GET"`, `"POST"`, `"PUT"`, `"DELETE"`
**Description:** HTTP method for the request
**Example:** ## Type Notes
```javascript
// Change method from GET to POST
request.method = "POST";
console.log('Method changed to:', request.method);
```
#### `request.url` Variables are always strings. Convert when needed:
**Type:** `string`
**Description:** Complete URL for the request
**Example:**
```javascript
// Add query parameter
request.url = request.url + '?timestamp=' + Date.now();
// Replace placeholder
const userId = roster.getVariable('user_id');
request.url = request.url.replace('{userId}', userId);
// Change domain
request.url = request.url.replace('localhost', 'api.example.com');
```
#### `request.headers`
**Type:** `object`
**Description:** HTTP headers as key-value pairs
**Example:**
```javascript
// Add header
request.headers['Authorization'] = 'Bearer ' + token;
// Modify existing header
request.headers['Content-Type'] = 'application/json';
// Delete header
delete request.headers['X-Old-Header'];
// Read header
const contentType = request.headers['Content-Type'];
```
#### `request.body`
**Type:** `string`
**Description:** Request body content
**Example:**
```javascript
// Set body
request.body = JSON.stringify({ name: "John", age: 30 });
// Modify existing body
const data = JSON.parse(request.body);
data.timestamp = new Date().toISOString();
request.body = JSON.stringify(data);
// Clear body
request.body = "";
```
## Response Object
**Available in:** Postprocessing scripts only
**Type:** Immutable (read-only)
### Properties
#### `response.body`
**Type:** `string`
**Description:** Response body content
**Example:**
```javascript
// Parse JSON response
const data = JSON.parse(response.body);
console.log('User name:', data.name);
// Check if response contains text
if (response.body.includes('error')) {
console.error('Response contains error');
}
// Get response length
console.log('Response size:', response.body.length, 'bytes');
```
#### `response.headers`
**Type:** `object`
**Description:** Response headers as key-value pairs (read-only)
**Example:**
```javascript
// Read header
const contentType = response.headers['Content-Type'];
console.log('Content type:', contentType);
// Check if header exists
if (response.headers['X-Rate-Limit-Remaining']) {
const remaining = response.headers['X-Rate-Limit-Remaining'];
console.log('Rate limit remaining:', remaining);
}
// List all headers
for (const key in response.headers) {
console.log(key + ':', response.headers[key]);
}
```
#### `response.statusCode`
**Type:** `number`
**Description:** HTTP status code (200, 404, 500, etc.)
**Example:**
```javascript
// Check if successful
if (response.statusCode === 200) {
console.log('Success!');
} else if (response.statusCode >= 400 && response.statusCode < 500) {
console.error('Client error:', response.statusCode);
} else if (response.statusCode >= 500) {
console.error('Server error:', response.statusCode);
}
// Handle specific status codes
switch (response.statusCode) {
case 200:
console.log('OK');
break;
case 201:
console.log('Created');
break;
case 401:
console.error('Unauthorized');
break;
case 404:
console.error('Not found');
break;
default:
console.log('Status:', response.statusCode);
}
```
#### `response.statusText`
**Type:** `string`
**Description:** HTTP status text ("OK", "Not Found", etc.)
**Example:**
```javascript
console.log('Response:', response.statusCode, response.statusText);
// Output: "Response: 200 OK"
if (response.statusText === "OK") {
// Process successful response
}
```
#### `response.responseTime`
**Type:** `number`
**Description:** Response time in milliseconds
**Example:**
```javascript
console.log('Response took', response.responseTime, 'ms');
if (response.responseTime > 1000) {
console.warn('Slow response:', response.responseTime, 'ms');
}
// Store for monitoring
roster.setVariable('last_response_time', response.responseTime.toString());
```
## Roster API
**Available in:** Both preprocessing and postprocessing scripts
**Namespace:** `roster`
### Methods
#### `roster.getVariable(name)`
**Available in:** Preprocessing scripts only
**Returns:** `string` or `undefined`
**Description:** Get variable value from selected environment
**Parameters:**
- `name` (string): Variable name
**Example:**
```javascript
// Get variable
const apiKey = roster.getVariable('api_key');
if (apiKey) {
request.headers['X-API-Key'] = apiKey;
} else {
console.error('API key not defined');
}
// Get with default value
const timeout = roster.getVariable('timeout') || '30';
console.log('Using timeout:', timeout);
```
**Notes:**
- Returns `undefined` if variable doesn't exist
- Gets value from selected environment
- Sensitive variables are automatically decrypted
#### `roster.setVariable(name, value)`
**Available in:** Both preprocessing and postprocessing scripts
**Returns:** `undefined`
**Description:** Set or update variable in selected environment
**Parameters:**
- `name` (string): Variable name (must match `/^\w+$/`)
- `value` (string): Variable value
**Example:**
```javascript
// Set variable
roster.setVariable('user_id', '12345');
console.log('Saved user ID');
// Update existing variable
const token = data.access_token;
roster.setVariable('auth_token', token);
// Create new variable (auto-created if doesn't exist)
roster.setVariable('session_id', generateSessionId());
```
**Notes:**
- Creates variable if it doesn't exist
- Updates value in selected environment
- Variable name must be alphanumeric + underscore
- Sensitive variables automatically routed to keyring
- Value converted to string
#### `roster.setVariables(object)`
**Available in:** Both preprocessing and postprocessing scripts
**Returns:** `undefined`
**Description:** Set or update multiple variables at once (batch operation)
**Parameters:**
- `object` (object): Key-value pairs of variable names and values
**Example:**
```javascript
// Set multiple variables
roster.setVariables({
user_id: data.user.id,
user_name: data.user.name,
user_email: data.user.email,
session_id: data.session_id
});
// Extract response data
const data = JSON.parse(response.body);
roster.setVariables({
access_token: data.access_token,
refresh_token: data.refresh_token,
expires_at: data.expires_at
});
console.log('Saved authentication tokens');
```
**Notes:**
- More efficient than multiple `setVariable()` calls
- Same validation rules as `setVariable()`
### Properties
#### `roster.project.name`
**Available in:** Preprocessing scripts only
**Type:** `string`
**Description:** Current project name
**Example:**
```javascript
const projectName = roster.project.name;
console.log('Project:', projectName);
// Add project name to request
request.headers['X-Project'] = projectName;
```
#### `roster.project.environments`
**Available in:** Preprocessing scripts only
**Type:** `string[]` (array of strings)
**Description:** Array of environment names in current project
**Example:**
```javascript
const envs = roster.project.environments;
console.log('Available environments:', envs.join(', '));
// Output: "Available environments: Production, Staging, Development"
// Check if environment exists
if (envs.includes('Production')) {
console.log('Production environment available');
}
// Log count
console.log('Environment count:', envs.length);
```
## Console API
**Available in:** Both preprocessing and postprocessing scripts
**Namespace:** `console`
### Methods
#### `console.log(...args)`
**Returns:** `undefined`
**Description:** Print message to script output
**Example:**
```javascript
console.log('Simple message');
console.log('User ID:', userId);
console.log('Request sent to', request.url);
console.log('Response status:', response.statusCode, response.statusText);
// Multiple arguments
const name = 'John';
const age = 30;
console.log('User:', name, 'Age:', age);
```
**Output location:**
- Preprocessing: "Preprocessing" tab in request panel
- Postprocessing: "Postprocessing" tab in request panel
#### `console.error(...args)`
**Returns:** `undefined`
**Description:** Print error message to script output
**Example:**
```javascript
if (response.statusCode !== 200) {
console.error('Request failed with status:', response.statusCode);
}
if (!data.access_token) {
console.error('No access token in response');
}
try {
const data = JSON.parse(response.body);
} catch (e) {
console.error('JSON parse error:', e.message);
}
```
**Visual difference:**
- May be styled differently than `console.log()` in output
- Indicates errors or warnings
## Built-in JavaScript Objects
Standard JavaScript objects available in GJS:
### Date
```javascript
// Current timestamp
const now = new Date();
console.log('Current time:', now.toISOString());
// Unix timestamp
const timestamp = Date.now();
console.log('Timestamp:', timestamp);
// Date arithmetic
const expiresAt = new Date(Date.now() + 3600000); // +1 hour
roster.setVariable('token_expires', expiresAt.toISOString());
```
### JSON
```javascript
// Parse JSON
const data = JSON.parse(response.body);
console.log('Parsed data:', data.name);
// Stringify JSON
const body = { name: "John", age: 30 };
request.body = JSON.stringify(body);
// Pretty print
request.body = JSON.stringify(body, null, 2);
```
### Math
```javascript
// Random number
const requestId = Math.floor(Math.random() * 1000000);
roster.setVariable('request_id', requestId.toString());
// Rounding
const responseTimeSeconds = Math.round(response.responseTime / 1000);
console.log('Response time:', responseTimeSeconds, 'seconds');
```
### String
```javascript
// String manipulation
const url = request.url.replace('http://', 'https://');
const uppercase = data.name.toUpperCase();
const trimmed = data.description.trim();
// String methods
if (response.body.includes('error')) {
console.error('Response contains error');
}
const parts = request.url.split('/');
const lastPart = parts[parts.length - 1];
```
### Array
```javascript
// Array methods
const data = JSON.parse(response.body);
const itemIds = data.items.map(item => item.id);
console.log('Item IDs:', itemIds.join(', '));
// Filter
const active = data.items.filter(item => item.active);
console.log('Active items:', active.length);
// Find
const firstItem = data.items.find(item => item.id === '123');
if (firstItem) {
console.log('Found item:', firstItem.name);
}
```
### Object
```javascript
// Object methods
const headers = Object.keys(response.headers);
console.log('Header count:', headers.length);
// Merge objects
const defaults = { timeout: 30, retries: 3 };
const config = Object.assign({}, defaults, userConfig);
// Check property
if (data.hasOwnProperty('access_token')) {
roster.setVariable('auth_token', data.access_token);
}
```
## Error Handling
Scripts should handle errors gracefully:
```javascript
// Try-catch for parsing
try {
const data = JSON.parse(response.body);
roster.setVariable('user_id', data.user.id);
} catch (e) {
console.error('Failed to parse JSON:', e.message);
console.error('Response body:', response.body);
}
// Check before accessing
if (data && data.user && data.user.id) {
roster.setVariable('user_id', data.user.id);
} else {
console.error('Invalid response structure');
}
// Validate response status
if (response.statusCode === 200) {
const data = JSON.parse(response.body);
// Process data
} else {
console.error('Request failed:', response.statusCode);
}
```
## Limitations
Scripts run in a sandboxed, synchronous environment:
- No async operations (setTimeout, Promises, async/await)
- No external libraries or npm packages
- No file system or shell access
- No network requests (use Roster's request system)
- Only built-in JavaScript objects available
## Type Reference
**Variable names** must match `/^\w+$/` (alphanumeric + underscore only).
**Variables are always strings**. Convert numbers and booleans when setting/getting:
```javascript ```javascript
roster.setVariable('count', data.count.toString()); roster.setVariable('count', data.count.toString());
const count = parseInt(roster.getVariable('count'), 10); const count = parseInt(roster.getVariable('count'), 10);
``` ```
## Next Steps ## Examples
- [[Scripts]] - Practical examples and workflows ### Authentication flow
- [[Variables]] - Learn about environment variables
- [[Sensitive-Variables]] - Secure credential storage **POST /auth/login — postprocessing:**
```javascript
const data = JSON.parse(response.body);
roster.setVariables({
access_token: data.access_token,
refresh_token: data.refresh_token,
user_id: data.user_id
});
```
**Authenticated request — preprocessing:**
```javascript
const token = roster.getVariable('access_token');
request.headers['Authorization'] = 'Bearer ' + token;
```
### Dynamic headers
```javascript
request.headers['X-Request-ID'] = Math.random().toString(36).slice(2);
request.headers['X-Timestamp'] = new Date().toISOString();
```

@ -89,14 +89,14 @@ Postprocessing Script → Display Response → Save to History
``` ```
~/.local/share/cz.bugsy.roster/ ~/.local/share/cz.bugsy.roster/
├── requests.json # Projects, environments, regular variables ├── requests.json # Projects, environments, regular variables
└── session.json # History, window state └── history.json # Request history
``` ```
**Flatpak:** **Flatpak:**
``` ```
~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/ ~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/
├── requests.json ├── requests.json
└── session.json └── history.json
``` ```
### Data Format ### Data Format
@ -104,18 +104,23 @@ Postprocessing Script → Display Response → Save to History
**requests.json:** **requests.json:**
```json ```json
{ {
"version": 1,
"projects": [ "projects": [
{ {
"id": "uuid", "id": "uuid",
"name": "Project Name", "name": "Project Name",
"icon": "icon-name", "icon": "icon-name",
"created_at": "2025-01-01T00:00:00+00:00",
"variable_names": ["base_url", "api_key"],
"sensitive_variables": ["api_key"],
"environments": [ "environments": [
{ {
"id": "uuid", "id": "uuid",
"name": "Production", "name": "Production",
"created_at": "2025-01-01T00:00:00+00:00",
"variables": { "variables": {
"base_url": "https://api.example.com", "base_url": "https://api.example.com",
"api_key": "" // Empty if sensitive "api_key": ""
} }
} }
], ],
@ -123,12 +128,19 @@ Postprocessing Script → Display Response → Save to History
{ {
"id": "uuid", "id": "uuid",
"name": "Get Users", "name": "Get Users",
"created_at": "2025-01-01T00:00:00+00:00",
"modified_at": "2025-01-01T00:00:00+00:00",
"request": {
"method": "GET", "method": "GET",
"url": "{{base_url}}/users", "url": "{{base_url}}/users",
"headers": {}, "headers": {},
"body": "", "body": "",
"preprocessing_script": "", "syntax": "RAW"
"postprocessing_script": "" },
"scripts": {
"preprocessing": "",
"postprocessing": ""
}
} }
] ]
} }
@ -136,6 +148,8 @@ Postprocessing Script → Display Response → Save to History
} }
``` ```
Note: sensitive variable values are stored in GNOME Keyring (empty string in JSON is a placeholder).
### Sensitive Variables ### Sensitive Variables
Stored in GNOME Keyring with schema: Stored in GNOME Keyring with schema:

147
Export.md

@ -1,12 +1,8 @@
# Export # Export
Roster can export requests to other formats for use with command-line tools or other HTTP clients. Click the **Export** button (toolbar) to copy the current request as a cURL command to clipboard.
## Supported Formats Variables are substituted with values from the selected environment before export.
### cURL
Export requests as cURL commands for use in terminal or scripts.
**Example output:** **Example output:**
```bash ```bash
@ -16,141 +12,4 @@ curl -X POST 'https://api.example.com/users' \
-d '{"name":"John","email":"john@example.com"}' -d '{"name":"John","email":"john@example.com"}'
``` ```
### Other Formats Sensitive variable values are included in plain text — review before sharing.
Additional export formats (HTTPie, wget, etc.) may be added in future releases.
## How to Export
### Export Current Request
1. Configure your request in the request editor
2. Click the **Export** button in the toolbar
3. Select export format (e.g., "cURL")
4. Exported command is copied to clipboard
### Export from History
1. Open a request from [[History]]
2. Click the **Export** button
3. Select format
4. Command copied to clipboard
### Export Saved Requests
1. Open a saved request from project
2. Click the **Export** button
3. Select format
4. Command copied to clipboard
## Variable Substitution
When exporting requests that contain variables:
**Variables are substituted with current environment values:**
- `{{base_url}}` replaced with actual URL
- `{{api_key}}` replaced with actual key value
- All `{{variable}}` placeholders resolved
The exported command contains the final values, not the placeholder syntax.
### Sensitive Variables
[[Sensitive-Variables]] are exported with their actual decrypted values. Be careful when sharing exported commands containing sensitive data.
**Security note:** Exported cURL commands may contain:
- API keys in headers
- Passwords in request body
- Tokens in authorization headers
Review exported commands before sharing.
## Using Exported Commands
### cURL
Paste the exported cURL command in your terminal:
```bash
curl -X GET 'https://api.example.com/users' \
-H 'Authorization: Bearer token123'
```
### Scripts
Use exported commands in shell scripts:
```bash
#!/bin/bash
# exported_request.sh
curl -X POST 'https://api.example.com/users' \
-H 'Content-Type: application/json' \
-d '{"name":"John"}'
```
### Documentation
Include exported commands in API documentation or tutorials.
## Export Features
### Headers
All request headers are included in export:
- Custom headers
- Content-Type
- Authorization
- User-Agent
- etc.
### Request Body
Request body is included with appropriate flags:
- `-d` for POST data
- Properly escaped JSON
- Multiline bodies formatted correctly
### Method
HTTP method included with `-X` flag:
- `-X GET`
- `-X POST`
- `-X PUT`
- `-X DELETE`
## Limitations
- Only cURL format currently supported
- No batch export of multiple requests
- Exported to clipboard only (no file export)
- Scripts (preprocessing/postprocessing) are not exported
## Tips
**Test exported commands:**
Always test exported cURL commands in a safe environment before using in production.
**Redact sensitive data:**
Remove or replace sensitive values before sharing exported commands:
```bash
# Original export
curl -H 'Authorization: Bearer abc123xyz'
# Redacted for sharing
curl -H 'Authorization: Bearer YOUR_TOKEN_HERE'
```
**Save to file:**
Redirect clipboard content to file:
```bash
# Paste from clipboard and save
pbpaste > request.sh # macOS
xclip -o > request.sh # Linux with xclip
```
## Next Steps
- [[Getting-Started]] - Learn to create requests
- [[Variables]] - Use variables in requests
- [[History]] - Review past requests

249
FAQ.md

@ -2,243 +2,66 @@
## General ## General
### What is Roster? **What is Roster?**
A native GNOME HTTP client for testing APIs, built with GTK 4 and libadwaita.
Roster is a native GNOME HTTP client for testing and debugging APIs. It provides a clean interface for sending HTTP requests, viewing responses, and automating workflows. **What platforms does it support?**
Linux with GNOME 40+. Not available for Windows or macOS.
### Is Roster free? **Is it free?**
Yes, GPL-3.0-or-later.
Yes! Roster is free and open-source software licensed under GPL-3.0-or-later.
### What platforms does Roster support?
Roster is designed for the GNOME desktop environment on Linux. It works on any Linux distribution with GNOME 40+.
### Can I use Roster on Windows or macOS?
Roster is specifically built for GNOME/Linux and is not currently available for Windows or macOS.
## Installation ## Installation
### How do I install Roster? **How do I install Roster?**
From Flathub (recommended): `flatpak install flathub cz.bugsy.roster`
Or see [[Installation]] to build from source.
See [[Installation]] for complete instructions. You can: **Is Roster on Flathub?**
- Build from source Yes. Install with `flatpak install flathub cz.bugsy.roster` or find it in GNOME Software.
- Install via Flatpak
- Use GNOME Builder
### Will Roster be on Flathub? ## Variables
Support for Flathub is planned for future releases. **What's the difference between regular and sensitive variables?**
Regular variables are stored in plain-text JSON. Sensitive variables are encrypted in GNOME Keyring. Use sensitive variables for API keys, tokens, and passwords — see [[Sensitive-Variables]].
### What dependencies does Roster need? **Can I use variables in the request body?**
Yes — `{{variable_name}}` works in URL, headers, and body.
GTK 4, libadwaita 1, Python 3, libsoup3, libsecret, and GJS. See [[Installation]] for details. **Can variables be shared between projects?**
No, variables are scoped to their project.
## Variables and Environments
### What's the difference between regular and sensitive variables?
**Regular variables** are stored in plain text JSON files. Use for non-sensitive data like URLs.
**Sensitive variables** are encrypted and stored in GNOME Keyring. Use for API keys, passwords, and tokens.
See [[Sensitive-Variables]] for details.
### Can I use variables in the request body?
Yes! Use `{{variable_name}}` syntax in:
- URL
- Headers
- Request body
### How do I switch between environments?
Use the environment dropdown at the top of the request panel. Switching environments updates all variable values.
### Can variables from one project be used in another?
No. Variables are scoped to projects and cannot be shared between projects.
## Security ## Security
### Is it safe to store API keys in Roster? **Is it safe to store API keys?**
Yes, if you mark them as sensitive (lock icon). Regular variables are plain text.
**If you use sensitive variables: Yes.** **Where are secrets stored?**
In GNOME Keyring (`~/.local/share/keyrings/`), same as browser passwords and WiFi credentials. Visible in Seahorse under "Login" keyring.
Mark variables as sensitive (click the lock icon), and values are encrypted in GNOME Keyring.
**If you use regular variables: No.**
Regular variables are stored in plain text. Always mark secrets as sensitive!
### Where are my secrets stored?
Sensitive variables are encrypted in GNOME Keyring (`~/.local/share/keyrings/`) using your login password. Same security as browser passwords and WiFi credentials.
### Can I view my keyring secrets?
Yes! Open "Passwords and Keys" application (Seahorse), navigate to "Login" keyring, and look for entries starting with "Roster:".
### What happens if I forget to mark a variable as sensitive?
You can click the lock icon at any time to mark it as sensitive. Values will be moved from JSON to keyring automatically.
## Scripts ## Scripts
### What language do scripts use? **What language?**
JavaScript (ES5+) via GJS.
JavaScript (ES5+), executed via GJS (GNOME JavaScript runtime). **Can I use npm packages / async / file system?**
No — scripts are sandboxed and synchronous. See [[Scripts]] for full limitations.
### Can I use npm packages in scripts?
No. Scripts run in a sandboxed environment without access to external libraries or npm packages.
### Can scripts access the file system?
No. Scripts cannot read/write files, execute shell commands, or access system resources.
### Why can't I use async/await?
Scripts execute synchronously. No async operations (setTimeout, Promises, async/await, fetch) are available.
### Can I make HTTP requests from scripts?
No. Use Roster's request system and chain requests using variables instead.
See [[Scripts]] for complete documentation.
## Requests and Responses
### Where is request history stored?
**Native:** `~/.local/share/cz.bugsy.roster/session.json`
**Flatpak:** `~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/session.json`
### How long is history kept?
History persists across sessions until you clear it manually.
### Can I export requests?
Yes! Click the export button and choose a format:
- cURL
- More formats may be added in future versions
### Does Roster support file uploads?
Multipart form uploads are not currently supported. Planned for future releases.
### Can I test WebSocket connections?
WebSocket support is not currently available.
## Troubleshooting ## Troubleshooting
### Roster won't start **Roster won't start**
Check dependencies: `pkg-config --modversion gtk4 libadwaita-1`
**Check dependencies:** **Keyring not accessible**
```bash Ensure GNOME Keyring is unlocked. For Flatpak, verify `--talk-name=org.freedesktop.secrets` permission.
# Verify GTK 4 and libadwaita are installed
pkg-config --modversion gtk4 libadwaita-1
```
**Check logs:** **Variables not substituting**
```bash Check: environment is selected, variable name matches exactly (case-sensitive), syntax is `{{name}}`.
# Native
roster
# Flatpak **How do I reset Roster?**
flatpak run cz.bugsy.roster Delete `~/.local/share/cz.bugsy.roster/` (native) or `~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/` (Flatpak). Keyring entries must be removed separately via Seahorse.
```
### Cannot access GNOME Keyring
**Ensure keyring is unlocked:**
1. Open "Passwords and Keys" (Seahorse)
2. Right-click "Login" keyring
3. Select "Unlock"
**For Flatpak, check permissions:**
```bash
flatpak info --show-permissions cz.bugsy.roster
# Should include: --talk-name=org.freedesktop.secrets
```
### Variables not substituting
**Check:**
1. Environment is selected (dropdown at top of request)
2. Variable names match exactly (case-sensitive)
3. Syntax is correct: `{{variable_name}}`
4. Variable is defined in selected environment
### Scripts not executing
**Check:**
1. Script has no syntax errors
2. Check script output panels for errors
3. GJS (gjs package) is installed
### Request failing with SSL errors
**For self-signed certificates:**
Roster uses system SSL certificates. Add your certificate to the system trust store or use development environments without SSL validation.
## Data and Privacy
### Does Roster collect any data?
No. Roster does not collect, transmit, or share any data. All information stays on your local machine.
### Can I backup my projects?
Yes! Backup these files:
- `~/.local/share/cz.bugsy.roster/requests.json` (projects and variables)
- `~/.local/share/keyrings/` (sensitive variables)
### How do I reset Roster?
Delete the data directory:
```bash
# Native
rm -rf ~/.local/share/cz.bugsy.roster/
# Flatpak
rm -rf ~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/
```
**Warning:** This deletes all projects, requests, and history!
Sensitive variables in keyring must be deleted separately via Seahorse.
## Contributing ## Contributing
### How can I contribute? Report bugs and request features: https://git.bugsy.cz/beval/roster/issues
See [[Contributing]] for contribution guidelines.
Contributions welcome! See [[Contributing]] for guidelines.
### Where do I report bugs?
Report issues at: https://git.bugsy.cz/beval/roster/issues
### Can I request features?
Yes! Open an issue with the "enhancement" label.
## Comparison
### How is Roster different from Postman/Insomnia?
Roster is a lightweight, native GNOME application focused on simplicity. Unlike Postman/Insomnia (Electron-based with cloud features), Roster is Linux-only with no cloud dependencies.
### How is Roster different from HTTPie?
Roster provides a GUI with project management, while HTTPie is a command-line tool.
## Still Have Questions?
- Check the [[Home|Wiki]] for more documentation
- Open an issue: https://git.bugsy.cz/beval/roster/issues
- Read the source: https://git.bugsy.cz/beval/roster

@ -1,156 +1,35 @@
# Getting Started # Getting Started
This guide walks you through sending your first HTTP request with Roster. After [[Installation]], launch Roster from the application menu or run `roster` (Flatpak: `flatpak run cz.bugsy.roster`).
## Launch Roster ## Sending a Request
After [[Installation]], launch Roster from: 1. The app opens with a new request tab
- Your application menu (search for "Roster") 2. Set the URL (e.g. `https://api.github.com/users/octocat`) and method (`GET`)
- Command line: `roster` (or `flatpak run cz.bugsy.roster` for Flatpak) 3. Optionally add headers in the **Headers** tab
4. Press **Ctrl+Return** (or click **Send**)
5. The response appears in the right panel — status, headers, body with syntax highlighting
## Your First Request ## Saving a Request
### Step 1: Configure the Request Click **Save** (or **Ctrl+S**), enter a name, and select a project. Unsaved changes show a dot (•) on the tab label.
Roster starts with a new request tab. ## History
**Set the URL:** Every sent request is automatically saved to history (bottom panel). Click any entry to open it in a new tab.
```
https://api.github.com/users/octocat
```
**Set the Method:** ## Tabs
- Use the dropdown menu (default is `GET`)
**Add Headers (Optional):** | Action | Shortcut |
1. Click the **"Headers"** tab |--------|----------|
2. Add a header: | New tab | **Ctrl+T** |
- Key: `User-Agent` | Close tab | **Ctrl+W** |
- Value: `Roster/0.6.0` | Switch tabs | **Ctrl+Tab** / **Ctrl+Shift+Tab** |
### Step 2: Send the Request
Click the **"Send"** button (or press **Ctrl+Return**)
### Step 3: View the Response
The response appears in the right panel:
**Status Line:**
```
200 OK 123 ms 1.2 KB
```
**Response Headers:**
Click the **"Headers"** tab to view all response headers.
**Response Body:**
The JSON response from GitHub API showing user information.
## Saving Requests
### Save for Later
1. Click the **"Save"** button in the header
2. Select project
2. Enter a name: `Get GitHub User`
3. Click **"Save"**
The request is now saved to your project.
### Access Saved Requests
1. Click the project
2. Your project shows saved requests
3. Click a request to open it in a new tab
## Request History
Every request you send is automatically saved to history.
**View History:**
1. Navigate to bottom history panel
2. Browse past requests
3. Click any entry to open it in a new tab
## Working with Tabs
### Multiple Tabs
Open multiple requests simultaneously:
- **Ctrl+T** - New request tab
- **Ctrl+W** - Close current tab
- **Ctrl+Tab** / **Ctrl+Shift+Tab** - Switch between tabs
### Modified Indicator
Unsaved changes are marked with a dot (•) on the tab label.
## Common Request Types
### GET Request
```
Method: GET
URL: https://api.example.com/users
Headers: (optional)
Body: (none)
```
### POST Request
```
Method: POST
URL: https://api.example.com/users
Headers: Content-Type: application/json
Body: {"name": "John", "email": "john@example.com"}
```
### PUT Request
```
Method: PUT
URL: https://api.example.com/users/123
Headers: Content-Type: application/json
Body: {"name": "John Updated"}
```
### DELETE Request
```
Method: DELETE
URL: https://api.example.com/users/123
Headers: (optional)
Body: (none)
```
## Response Features
### Syntax Highlighting
Roster automatically detects and highlights JSON, XML, and HTML responses.
### Response Metrics
The status line shows status code, response time, and total size including headers:
```
200 OK 123 ms 5.4 KB
```
## Keyboard Shortcuts
Essential shortcuts to speed up your workflow:
See [[Keyboard-Shortcuts]] for the complete list.
## Next Steps ## Next Steps
Now that you know the basics, explore more advanced features: - [[Projects-and-Environments]] — organize requests
- [[Variables]] — avoid repeating URLs and headers
- [[Projects-and-Environments]] - Organize requests and manage environments - [[Sensitive-Variables]] — store API keys securely
- [[Variables]] - Use variables to avoid repetition - [[Scripts]] — automate with JavaScript
- [[Sensitive-Variables]] - Store API keys securely - [[Import]] — import from OpenAPI/Swagger or WSDL
- [[Scripts]] - Automate workflows with JavaScript
- [[Export]] - Export requests to cURL and other formats
## Tips
- Use `httpbin.org` endpoints for testing (e.g., `https://httpbin.org/get`)
- Save frequently used requests with descriptive names
- Check history panel to review and compare past responses

@ -1,124 +1,22 @@
# History # History
Roster automatically saves every HTTP request you send to history, allowing you to review and replay past requests. Every request you send is automatically saved to history and persists across sessions.
## What is History? ## Accessing History
History captures complete request and response data for every request sent: History appears in the **bottom panel** of the main window. Each entry shows method, URL, status code, timestamp, and response time, sorted newest first.
- Request method, URL, headers, body
- Response status, headers, body, timing
- Timestamp of when request was sent
- Environment used (if applicable)
History persists across sessions and survives application restarts. Click any entry to open it in a new tab — you can modify and resend it.
## Viewing History ## Storage
### Access History Panel - Native: `~/.local/share/cz.bugsy.roster/history.json`
- Flatpak: `~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/history.json`
History appears in the bottom panel of the main window.
### History Entries
Each entry shows:
- Request method and URL
- Response status code
- Timestamp (relative or absolute)
- Response time
Entries are sorted by timestamp (most recent first).
### Open from History
Click any history entry to open it in a new tab with:
- Complete request details
- Full response
- All headers
This creates a new editable request tab - you can modify and resend.
## Replaying Requests
To replay a request from history:
1. Click the history entry
2. Request opens in new tab with original configuration
3. Click **"Send"** to execute again
The replayed request:
- Uses current environment variables (not original values)
- Can be modified before sending
- Creates a new history entry when sent
## Using History
### Compare Responses
Open multiple history entries in tabs to compare responses across time or different environments.
### Debug Issues
Review past requests to:
- See what was actually sent
- Check response timing trends
- Verify header values
- Examine error responses
### Create New Requests
Use history entries as templates:
1. Open history entry
2. Modify URL, headers, or body
3. Save as new request
## History Storage
**Native:**
```
~/.local/share/cz.bugsy.roster/session.json
```
**Flatpak:**
```
~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/session.json
```
History is stored in JSON format with full request/response data.
## Clearing History ## Clearing History
Currently, history can be cleared by deleting the `session.json` file: No built-in UI — delete `history.json` and restart the app.
```bash ## Privacy
# Native
rm ~/.local/share/cz.bugsy.roster/session.json
# Flatpak History contains full request and response data in plaintext, including headers and bodies. Clear it periodically if requests contain sensitive data.
rm ~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/session.json
```
Then restart Roster.
## Privacy Note
History contains complete request and response data, including:
- URLs and query parameters
- Request/response headers
- Request/response bodies
If requests contain sensitive data:
- Use [[Sensitive-Variables]] for credentials
- Be aware history file contains plaintext data
- Clear history periodically if needed
## Limitations
- History is stored locally only (no cloud sync)
- No built-in UI to clear history (must delete file manually)
- No search/filter functionality (planned for future releases)
- No export functionality for history entries
## Next Steps
- [[Getting-Started]] - Learn to send requests
- [[Export]] - Export requests to other tools

@ -11,6 +11,7 @@ Roster is a native GNOME application for testing and debugging HTTP APIs with su
- Secure credential storage using GNOME Keyring - Secure credential storage using GNOME Keyring
- JavaScript preprocessing and postprocessing scripts - JavaScript preprocessing and postprocessing scripts
- Request history and export to cURL - Request history and export to cURL
- Import from OpenAPI/Swagger (2.0 + 3.x) and WSDL
## Quick Links ## Quick Links
@ -25,6 +26,7 @@ Roster is a native GNOME application for testing and debugging HTTP APIs with su
- [[Scripts]] - Preprocessing and postprocessing automation - [[Scripts]] - Preprocessing and postprocessing automation
- [[Export]] - Export requests to other tools - [[Export]] - Export requests to other tools
- [[History]] - Track and replay requests - [[History]] - Track and replay requests
- [[Import]] - Import from OpenAPI/Swagger and WSDL
### Reference ### Reference
- [[API-Reference]] - Complete JavaScript API documentation - [[API-Reference]] - Complete JavaScript API documentation

62
Import.md Normal file

@ -0,0 +1,62 @@
# Import
Roster can import API definitions from OpenAPI/Swagger and WSDL endpoints, automatically creating saved requests for all discovered operations.
## Supported Formats
### OpenAPI / Swagger
- **OpenAPI 2.0** (Swagger) — JSON or YAML
- **OpenAPI 3.x** — JSON or YAML
Imports all defined API operations as separate saved requests, including:
- HTTP method and path
- Base URL from `host`/`servers` field
- Request headers (`Content-Type`, `Accept`)
- JSON body template generated from the request schema
### WSDL (Web Services Description Language)
- **WSDL 1.1**
- **WSDL 2.0**
Imports all defined operations as SOAP requests, including:
- Endpoint URL from the WSDL binding
- `Content-Type: text/xml` header
- XML body template generated from the input message schema
## How to Import
### OpenAPI / Swagger
1. Click the **Import** button (papyrus icon) in the sidebar toolbar
2. Select **"Import from OpenAPI / Swagger"**
3. Enter the **Spec URL** of the OpenAPI/Swagger definition (must start with `http://` or `https://`)
4. Click **Fetch** — Roster downloads and parses the spec
5. Select the operations you want to import (or select all)
6. Choose or create a **project** to import into
7. Click **"Import"**
### WSDL
1. Click the **Import** button (papyrus icon) in the sidebar toolbar
2. Select **"Import from WSDL"**
3. Enter the **WSDL URL** of the service description (WSDL 1.1 or 2.0)
4. Click **Fetch WSDL** — Roster downloads and parses the service description
5. Select the operations you want to import (or select all)
6. Choose or create a **project** to import into
7. Click **"Import"**
The imported requests are saved to the selected project and ready to send.
## Tips
- Imported requests use placeholder values from the schema (e.g., empty strings for required fields). Fill in actual values before sending.
- Variable substitution works in imported requests — add `{{variable_name}}` to the URL or body after importing.
- For OpenAPI imports with `{{server}}` or similar base URL variables, set up an environment with the actual server URL.
## Next Steps
- [[Projects-and-Environments]] - Organize imported requests into projects
- [[Variables]] - Add environment variables to imported requests
- [[Getting-Started]] - Learn how to send requests

@ -1,34 +1,19 @@
# Installation # Installation
This guide covers how to build and install Roster from source. ## Flathub (recommended)
## Dependencies ```bash
flatpak install flathub cz.bugsy.roster
```
Roster requires the following dependencies: Or search for "Roster" in GNOME Software.
### Runtime Dependencies ## Build from Source
- **GTK 4** (>= 4.0)
- **libadwaita 1** (>= 1.0)
- **Python 3** (>= 3.8)
- **libsoup3** - HTTP client library (provided by GNOME Platform)
- **libsecret** - Secure credential storage (provided by GNOME Platform)
- **GJS** - GNOME JavaScript runtime for script execution
### Build Dependencies **Dependencies:**
- **Meson** (>= 1.0.0)
- **Ninja**
- **pkg-config**
- **gettext** - For internationalization
- **glib-compile-schemas**
- **glib-compile-resources**
## Installation Methods - Meson >= 1.0, Ninja, pkg-config, gettext
- GTK 4, libadwaita 1, libsoup3, libsecret, GJS, PyGObject
### Method 1: Build from Source (Native)
This method builds and installs Roster directly on your system.
#### Step 1: Install Dependencies
**Fedora:** **Fedora:**
```bash ```bash
@ -40,152 +25,44 @@ sudo dnf install meson ninja-build gtk4-devel libadwaita-devel libsoup3-devel li
sudo apt install meson ninja-build libgtk-4-dev libadwaita-1-dev libsoup-3.0-dev libsecret-1-dev gjs python3 gettext desktop-file-utils appstream sudo apt install meson ninja-build libgtk-4-dev libadwaita-1-dev libsoup-3.0-dev libsecret-1-dev gjs python3 gettext desktop-file-utils appstream
``` ```
**Arch Linux:** **Arch:**
```bash ```bash
sudo pacman -S meson ninja gtk4 libadwaita libsoup3 libsecret gjs python3 gettext sudo pacman -S meson ninja gtk4 libadwaita libsoup3 libsecret gjs python gettext
``` ```
#### Step 2: Clone Repository
```bash ```bash
git clone https://git.bugsy.cz/beval/roster.git git clone https://git.bugsy.cz/beval/roster.git
cd roster cd roster
```
#### Step 3: Build
```bash
meson setup builddir meson setup builddir
meson compile -C builddir meson compile -C builddir
```
#### Step 4: Install
```bash
sudo meson install -C builddir sudo meson install -C builddir
``` ```
#### Step 5: Run ## Build Flatpak Locally
```bash
roster
```
Or launch from your application menu.
### Method 2: Build with Flatpak (Recommended)
Flatpak provides a sandboxed environment with all dependencies included.
#### Step 1: Install Flatpak Builder
**Fedora:**
```bash
sudo dnf install flatpak-builder
```
**Ubuntu/Debian:**
```bash
sudo apt install flatpak-builder
```
#### Step 2: Add Flathub Remote
```bash
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
```
#### Step 3: Install GNOME SDK
```bash ```bash
flatpak install flathub org.gnome.Platform//49 org.gnome.Sdk//49 flatpak install flathub org.gnome.Platform//49 org.gnome.Sdk//49
```
#### Step 4: Build Flatpak
```bash
git clone https://git.bugsy.cz/beval/roster.git
cd roster
flatpak-builder --user --install --force-clean build-dir cz.bugsy.roster.json flatpak-builder --user --install --force-clean build-dir cz.bugsy.roster.json
```
#### Step 5: Run
```bash
flatpak run cz.bugsy.roster flatpak run cz.bugsy.roster
``` ```
### Method 3: GNOME Builder (For Development) ## GNOME Builder
GNOME Builder provides an integrated development environment. Clone `https://git.bugsy.cz/beval/roster.git` in GNOME Builder and hit Run.
#### Step 1: Install GNOME Builder
```bash
flatpak install flathub org.gnome.Builder
```
#### Step 2: Open Project
1. Launch GNOME Builder
2. Click "Clone Repository"
3. Enter: `https://git.bugsy.cz/beval/roster.git`
4. Click "Clone"
#### Step 3: Build and Run
1. Click the "Build" button (hammer icon)
2. Click the "Run" button (play icon)
## Uninstallation
### Native Installation
```bash
cd roster/builddir
sudo ninja uninstall
```
### Flatpak Installation
```bash
flatpak uninstall cz.bugsy.roster
```
## File Locations ## File Locations
### Native Installation | | Native | Flatpak |
|---|---|---|
| Data | `~/.local/share/cz.bugsy.roster/` | `~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/` |
| Sensitive vars | GNOME Keyring | GNOME Keyring |
- **Binary**: `/usr/local/bin/roster` (or `/usr/bin/roster`) ## Uninstall
- **Application data**: `~/.local/share/cz.bugsy.roster/`
- **Requests/Projects**: `~/.local/share/cz.bugsy.roster/requests.json`
- **Session state**: `~/.local/share/cz.bugsy.roster/session.json`
- **Sensitive variables**: GNOME Keyring (encrypted)
### Flatpak Installation ```bash
# Source build
sudo ninja -C builddir uninstall
- **Binary**: Managed by Flatpak # Flatpak
- **Application data**: `~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/` flatpak uninstall cz.bugsy.roster
- **Requests/Projects**: `~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/requests.json` ```
- **Session state**: `~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/session.json`
- **Sensitive variables**: GNOME Keyring (encrypted)
## Troubleshooting
**Build errors:**
- "meson: command not found" → Install Meson
- "Package not found" errors → Install missing development packages
**Runtime errors:**
- "Failed to access Secret Service" → Ensure GNOME Keyring is unlocked
- "Module 'gi' not found" → Install PyGObject
**Flatpak:**
- "Nothing matches org.gnome.Platform" → Add Flathub remote and install GNOME SDK
- No network access → Verify `--share=network` permission
## Next Steps
- [[Getting-Started]] - Learn how to use Roster
- [[Projects-and-Environments]] - Organize your API testing
- [[Variables]] - Use variables in requests

@ -1,141 +1,28 @@
# Projects and Environments # Projects and Environments
Projects help organize related HTTP requests, while environments allow you to manage different configurations (development, staging, production).
## Projects ## Projects
### What is a Project? A project groups saved requests, variables, and environments together. Projects appear in the left sidebar.
A project is a container for: - **Create:** click **+** in the sidebar header
- **Saved requests** - Your HTTP requests - **Edit / Delete:** click **⋯** next to the project name
- **Variables** - Shared variables across requests - **Icon:** editable in the project edit dialog
- **Environments** - Different configurations (dev, prod, etc.)
Example projects:
- "GitHub API"
- "My App Backend"
- "Payment Integration"
- "Authentication Service"
### Creating a Project
1. Click the "+" icon in top-left
2. Enter project name
3. Click **"Create"**
A default "Default" environment is automatically created.
### Accessing Projects
Projects appear in the sidebar on the left side:
- Click a project to expand/collapse
- Shows saved requests within the project
- Active project highlighted
### Editing a Project
1. Click the "three-dots" symbol near the project name in sidebar
2. Select **"Edit Project"**
3. Enter new name or click icon to choose from grid
4. Click **"Save"**
### Deleting a Project
1. Right-click the project in sidebar
2. Select **"Delete"**
3. Confirm deletion
**Warning:** This deletes all requests, environments, and variables in the project!
## Environments
### What is an Environment?
An environment is a set of variable values. Common environments:
- **Production** - Live API with real credentials
- **Staging** - Pre-production testing
- **Development** - Local development server
- **Testing** - Automated test environment
### Managing Environments
See [[Variables]] for complete environment and variable management documentation.
**Quick access:**
1. Select a project
2. Click the "three-dots" symbol near the project name in sidebar
3. Click **"Manage Environments"
3. Manage environments and variables in dialog
### Default Environment
Each project starts with a "Default" environment. You can:
- Rename it
- Add more environments
- Delete it (if you have at least one other environment)
## Saved Requests ## Saved Requests
### Saving a Request - **Save:** **Ctrl+S**, enter name and select project
- **Open:** click request name in the sidebar → opens in a new tab
- **Delete:** click **×** next to the request name in sidebar
1. Configure your request (URL, method, headers, body) Unsaved changes show a dot (•) on the tab label.
2. Click **"Save"** button in header
3. Enter request name (e.g., "Get User Profile")
4. Select a project
5. Click **"Save"**
### Opening a Saved Request ## Environments and Variables
1. Navigate to your project See [[Variables]] for full documentation. Quick access: **⋯ → Manage Environments** next to the project name.
2. Click on a saved request
3. Request opens in a new tab
### Editing a Saved Request
1. Open the request
2. Make changes
3. Click **"Save"** (or Ctrl+S)
4. Select Project and enter request name
5. Click Save
**Modified indicator:** Unsaved changes show a dot (•) on the tab label.
### Deleting a Saved Request
1. Click "x" icon near the request name in sidebar
2. Confirm deletion
Requests can have preprocessing and postprocessing scripts attached. See [[Scripts]] for details.
## Data Storage ## Data Storage
### File Location Projects and variables: `~/.local/share/cz.bugsy.roster/requests.json`
(Flatpak: `~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/requests.json`)
**Native:** Sensitive variables: GNOME Keyring — see [[Sensitive-Variables]].
```
~/.local/share/cz.bugsy.roster/requests.json
```
**Flatpak:**
```
~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/requests.json
```
### Sensitive Variables
Regular variables stored in JSON.
Sensitive variables stored in GNOME Keyring (encrypted).
See [[Sensitive-Variables]] for details.
### Backup
To backup your projects:
1. Copy the `requests.json` file
2. For sensitive variables: backup your GNOME Keyring (see [[Sensitive-Variables]])
## Next Steps
- [[Variables]] - Learn about variables and environments
- [[Sensitive-Variables]] - Secure credential storage
- [[Scripts]] - Automate workflows

@ -1,393 +1,78 @@
# Scripts # Scripts
Roster supports JavaScript preprocessing and postprocessing scripts to automate request modifications and response data extraction. Roster supports JavaScript preprocessing and postprocessing scripts via **GJS** (GNOME JavaScript).
## Overview **Preprocessing** — runs before the request is sent; can modify `request`.
**Postprocessing** — runs after the response; can read `response` and set variables.
Scripts allow you to: Open the **Scripts** tab in the request editor. Save with **Ctrl+S**.
- **Modify requests** before they're sent (preprocessing)
- **Extract data** from responses after they're received (postprocessing)
- **Chain requests** together by passing data between them
- **Automate workflows** like authentication flows
Scripts are executed using **GJS** (GNOME JavaScript), the same JavaScript runtime used throughout GNOME.
## Script Types
### Preprocessing Scripts
**Run BEFORE the HTTP request is sent.**
Use cases:
- Modify request headers, URL, body, or method
- Add dynamic values (timestamps, request IDs, signatures)
- Read environment variables
- Set/update environment variables
- Add authentication headers
### Postprocessing Scripts
**Run AFTER receiving the HTTP response.**
Use cases:
- Extract data from response body
- Parse JSON/XML responses
- Store values in environment variables for use in subsequent requests
- Validate response data
- Chain requests together
## Adding Scripts to Requests
### Step 1: Open Script Editor
Use the Scripts tab in the request editor
The script editor tab contains two panels:
- **Preprocessing** panel
- **Postprocessing** panel
### Step 2: Write Your Script
1. Select the appropriate panel
2. Write JavaScript code
3. Click **"Save"** or **Ctrl+S**
### Step 3: Run Request with Scripts
1. Open the request
2. Click **"Send"**
3. Preprocessing script runs first (if present)
4. HTTP request sent
5. Postprocessing script runs after response received (if present)
## Preprocessing API ## Preprocessing API
### Available Objects
#### Request Object (Modifiable)
```javascript ```javascript
request.method // String: "GET", "POST", "PUT", "DELETE" request.method // "GET", "POST", "PUT", "DELETE"
request.url // String: Full URL request.url // Full URL string
request.headers // Object: Header key-value pairs request.headers // Header key-value object
request.body // String: Request body request.body // Request body string
roster.getVariable(name)
roster.setVariable(name, value)
roster.setVariables({key: value})
roster.project.name
roster.project.environments // string[]
console.log(...) / console.error(...)
``` ```
All properties can be modified. **Example:**
#### Roster API
```javascript
// Variables
roster.getVariable(name) // Get variable from selected environment
roster.setVariable(name, value) // Set/update variable
roster.setVariables({key: value}) // Batch set variables
// Project Information
roster.project.name // Current project name
roster.project.environments // Array of environment names
```
#### Console Output
```javascript
console.log(message) // Output shown in preprocessing results tab
console.error(message) // Error output
```
### Examples
#### Example 1: Add Dynamic Authentication Header
```javascript ```javascript
const token = roster.getVariable('auth_token'); const token = roster.getVariable('auth_token');
request.headers['Authorization'] = 'Bearer ' + token; request.headers['Authorization'] = 'Bearer ' + token;
request.headers['X-Request-Time'] = new Date().toISOString(); request.headers['X-Request-Time'] = new Date().toISOString();
console.log('Added auth header');
```
#### Example 2: Modify Request Based on Environment
```javascript
const env = roster.getVariable('environment_name');
if (env === 'production') {
request.url = request.url.replace('localhost', 'api.example.com');
console.log('Switched to production URL');
} else {
console.log('Using development URL');
}
```
#### Example 3: Generate Request Signature
```javascript
const apiKey = roster.getVariable('api_key');
const timestamp = Date.now().toString();
const requestId = Math.random().toString(36).substring(7);
request.headers['X-API-Key'] = apiKey;
request.headers['X-Timestamp'] = timestamp;
request.headers['X-Request-ID'] = requestId;
// Save for later reference
roster.setVariable('last_request_id', requestId);
console.log('Request ID:', requestId);
```
#### Example 4: Add HMAC Signature
```javascript
// Note: GJS doesn't have crypto module, this is pseudocode
const apiKey = roster.getVariable('api_key');
const secretKey = roster.getVariable('secret_key');
const timestamp = Date.now().toString();
// You would use a crypto library here
const signature = generateHMAC(request.body + timestamp, secretKey);
request.headers['X-API-Key'] = apiKey;
request.headers['X-Timestamp'] = timestamp;
request.headers['X-Signature'] = signature;
```
#### Example 5: Modify Request Body
```javascript
// Parse existing body
const body = JSON.parse(request.body);
// Add dynamic fields
body.timestamp = new Date().toISOString();
body.requestId = Math.random().toString(36).substring(7);
body.version = '2.0';
// Update request body
request.body = JSON.stringify(body, null, 2);
console.log('Modified request body');
``` ```
## Postprocessing API ## Postprocessing API
### Available Objects
#### Response Object (Read-Only)
```javascript ```javascript
response.body // String: Response body response.body // string, read-only
response.headers // Object: Header key-value pairs response.headers // object, read-only
response.statusCode // Number: HTTP status code (200, 404, etc.) response.statusCode // number
response.statusText // String: Status text ("OK", "Not Found", etc.) response.statusText // string
response.responseTime // Number: Response time in milliseconds response.responseTime // number (ms)
roster.setVariable(name, value)
roster.setVariables({key: value})
// roster.getVariable() is NOT available here
console.log(...) / console.error(...)
``` ```
All properties are read-only. **Example:**
#### Roster API
```javascript
// Variables
roster.setVariable(name, value) // Set/update variable
roster.setVariables({key: value}) // Batch set variables
```
Note: `roster.getVariable()` is NOT available in postprocessing.
#### Console Output
```javascript
console.log(message) // Output shown in postprocessing results tab
console.error(message) // Error output
```
### Examples
#### Example 1: Extract Authentication Token
```javascript
const data = JSON.parse(response.body);
if (data.access_token) {
roster.setVariable('auth_token', data.access_token);
console.log('Saved auth token');
} else {
console.error('No access token in response');
}
```
#### Example 2: Extract Multiple Values
```javascript ```javascript
const data = JSON.parse(response.body); const data = JSON.parse(response.body);
roster.setVariables({ roster.setVariables({
user_id: data.user.id,
user_name: data.user.name,
user_email: data.user.email,
session_id: data.session.id
});
console.log('Extracted user:', data.user.name);
```
#### Example 3: Validate and Store Response
```javascript
const data = JSON.parse(response.body);
if (response.statusCode === 200 && data.items) {
roster.setVariable('item_count', data.items.length.toString());
if (data.items.length > 0) {
roster.setVariable('first_item_id', data.items[0].id);
roster.setVariable('first_item_name', data.items[0].name);
}
console.log('Found', data.items.length, 'items');
} else {
console.error('Error: Invalid response or no items');
}
```
#### Example 4: Extract Pagination Token
```javascript
const data = JSON.parse(response.body);
if (data.next_page_token) {
roster.setVariable('next_page', data.next_page_token);
console.log('Next page token saved');
} else {
roster.setVariable('next_page', '');
console.log('No more pages');
}
```
#### Example 5: Parse Response Headers
```javascript
// Extract rate limit information from headers
const rateLimit = response.headers['X-RateLimit-Limit'];
const rateRemaining = response.headers['X-RateLimit-Remaining'];
const rateReset = response.headers['X-RateLimit-Reset'];
if (rateLimit && rateRemaining && rateReset) {
roster.setVariables({
rate_limit: rateLimit,
rate_remaining: rateRemaining,
rate_reset: rateReset
});
console.log('Rate limit:', rateRemaining, '/', rateLimit);
} else {
console.log('No rate limit headers');
}
```
## Complete Workflows
### Workflow 1: OAuth Token Flow
**Request 1: Login (POST /auth/login)**
Postprocessing:
```javascript
// Extract and store tokens from login response
const data = JSON.parse(response.body);
if (response.statusCode === 200) {
roster.setVariables({
access_token: data.access_token, access_token: data.access_token,
refresh_token: data.refresh_token, user_id: data.user_id
user_id: data.user_id, });
expires_at: data.expires_at
});
console.log('Logged in as user:', data.user_id);
} else {
console.error('Login failed:', response.statusText);
}
``` ```
**Request 2: Get User Profile (GET /users/{userId})** ## Execution Order
Preprocessing: 1. Preprocessing script
```javascript 2. Variable substitution (`{{variable_name}}`)
// Use stored token and user ID in request 3. HTTP request
const token = roster.getVariable('access_token'); 4. Postprocessing script
const userId = roster.getVariable('user_id'); 5. Response displayed and saved to history
// Add authentication ## Limitations
request.headers['Authorization'] = 'Bearer ' + token;
// Substitute user ID in URL - Synchronous only — no `async/await`, `setTimeout`, `fetch`
request.url = request.url.replace('{userId}', userId); - No file system, shell, or external library access
console.log('Making authenticated request for user:', userId);
```
### Workflow 2: Paginated API Requests
**Request: Get Items with Pagination**
Preprocessing:
```javascript
const nextPage = roster.getVariable('next_page');
if (nextPage) {
request.url = request.url + '?page_token=' + nextPage;
console.log('Fetching next page');
} else {
console.log('Fetching first page');
}
```
Postprocessing:
```javascript
const data = JSON.parse(response.body);
// Store items count
roster.setVariable('items_count', data.items.length.toString());
// Store next page token for subsequent request
if (data.next_page_token) {
roster.setVariable('next_page', data.next_page_token);
console.log('Page loaded. More pages available.');
} else {
roster.setVariable('next_page', '');
console.log('Page loaded. No more pages.');
}
```
### Workflow 3: Dynamic API Versioning
**Preprocessing:**
```javascript
const apiVersion = roster.getVariable('api_version') || 'v1';
request.url = request.url.replace('/api/', '/api/' + apiVersion + '/');
request.headers['X-API-Version'] = apiVersion;
console.log('Using API version:', apiVersion);
```
**Postprocessing:**
```javascript
// Check if server suggests upgrading API version
const suggestedVersion = response.headers['X-Suggested-API-Version'];
if (suggestedVersion) {
console.log('Server suggests API version:', suggestedVersion);
roster.setVariable('suggested_api_version', suggestedVersion);
}
```
## Script Execution Flow
When sending a request with scripts:
1. Execute preprocessing script (if present) - can modify request
2. Apply variable substitution (`{{variable_name}}`)
3. Send HTTP request
4. Execute postprocessing script (if present) - can read response, set variables
5. Display response and save to history
## Error Handling ## Error Handling
If a script throws an error, the error is shown in the script output panel. The request still executes (preprocessing) or response still displays (postprocessing). Variable changes before the error are preserved. Script errors are shown in the output panel; the request still executes.
Always use try-catch for JSON parsing:
```javascript ```javascript
try { try {
const data = JSON.parse(response.body); const data = JSON.parse(response.body);
@ -397,46 +82,4 @@ try {
} }
``` ```
## Best Practices See [[API-Reference]] for the full API reference.
- **Keep scripts simple** - One clear purpose per script
- **Handle errors** - Use try-catch for JSON parsing and check status codes
- **Use logging** - Track execution with console.log for debugging
- **Never log secrets** - Log confirmations, not actual token/key values
## Limitations
### No External Libraries
GJS environment is sandboxed:
- Cannot import npm packages
- Cannot require() external modules
- Standard JavaScript built-ins available
### No Asynchronous Operations
Scripts execute synchronously:
- No setTimeout/setInterval
- No async/await
- No fetch() or XMLHttpRequest
- Use Roster's request system instead
### Security Restrictions
Scripts cannot:
- Access file system directly
- Make network requests (other than the main request)
- Execute shell commands
- Access system resources
## Debugging Scripts
- Use console.log liberally to track script execution
- Check Preprocessing/Postprocessing panels for output and errors
- Start with simple test scripts and build up complexity
## Next Steps
- [[API-Reference]] - Complete API documentation
- [[Variables]] - Learn about environment variables
- [[Sensitive-Variables]] - Secure storage for tokens and keys

@ -1,153 +1,40 @@
# Sensitive Variables # Sensitive Variables
Sensitive variables provide secure storage for API keys, passwords, and tokens using GNOME Keyring encryption instead of plain text files. Sensitive variables store their values in **GNOME Keyring** (encrypted) instead of plain-text JSON. Use them for API keys, passwords, and tokens.
## Overview ## Marking a Variable as Sensitive
Regular [[Variables]] are stored in plain text JSON files at `~/.local/share/cz.bugsy.roster/requests.json`. This is fine for non-sensitive data like base URLs or timeout values, but **dangerous for secrets**. In the Environments dialog, click the **lock icon** on a variable row. The icon toggles between locked (keyring) and unlocked (JSON). Existing values are automatically migrated when you toggle.
**Sensitive variables** solve this by storing values encrypted in GNOME Keyring, the same secure storage used by: Sensitive variable values display as bullets (••••) in the dialog.
- Firefox and GNOME Web for passwords
- Evolution for email credentials
- Network Manager for WiFi passwords
- SSH for key passphrases
## How It Works ## Usage in Requests
### Storage Comparison Works exactly like regular variables — use `{{variable_name}}` syntax. Roster retrieves and decrypts the value transparently before sending.
**Regular Variable (Insecure):** ## Script Access
```
File: ~/.local/share/cz.bugsy.roster/requests.json Scripts access sensitive variables the same way as regular ones:
Format: Plain text (anyone can read)
Content: "api_key": "secret-abc123-visible-to-all" ```javascript
// Preprocessing
const key = roster.getVariable('api_key'); // decrypted automatically
// Postprocessing — if 'access_token' is marked sensitive, it goes to keyring
roster.setVariable('access_token', data.access_token);
``` ```
**Sensitive Variable (Secure):** ## Keyring Schema
```
File: ~/.local/share/cz.bugsy.roster/requests.json
Format: Plain text
Content: "api_key": "" (empty placeholder)
Keyring: GNOME Keyring (encrypted) - **Schema:** `cz.bugsy.roster.EnvironmentVariable`
Format: Encrypted with your login password - **Attributes:** `project_id`, `environment_id`, `variable_name`
Content: "secret-abc123-visible-to-all" (encrypted at rest)
```
## Usage Secrets are visible in **Passwords and Keys** (Seahorse) under the Login keyring.
### Mark Variable as Sensitive
Open the Environments dialog for your project.
Each variable row has a **lock icon** to toggle between secure/insecure storage.
**Before entering secrets (recommended):**
1. Create variable (e.g., `api_key`)
2. Click the **lock icon** - it changes to locked state
3. Variable name becomes bold and colored
4. Enter your secret value
**After entering secrets (migration):**
1. Click the lock icon on existing variable
2. Values automatically move from JSON to keyring
### Enter Secret Values
Values in sensitive variables:
- Display as bullets (••••••) instead of characters
- Automatically save to GNOME Keyring (encrypted)
### Use in Requests
Sensitive variables work exactly like regular variables:
```
GET {{base_url}}/users
Authorization: Bearer {{api_key}}
```
When you send the request:
1. Roster retrieves `api_key` from GNOME Keyring
2. Decrypts it using your login password
3. Substitutes it into the request
4. Sends the request with the real value
## Viewing Secrets in Keyring
Open "Passwords and Keys" (Seahorse) and navigate to "Login" keyring. Look for entries labeled `Roster: ProjectName/EnvironmentName/VariableName`.
You can view, edit, or delete secrets from Seahorse (requires authentication).
## Making Variables Non-Sensitive
If you marked a variable as sensitive by mistake:
1. Click the lock icon again
2. Icon changes from locked to unlocked
3. Values move from keyring back to JSON
4. You can now see values in plain text
**Warning:** Only do this for non-sensitive data! Once moved to JSON, the values are visible to anyone who can read your files.
## Security
- Encrypted at rest with your GNOME login password
- Keyring unlocks automatically on login
- Only accessible by your user account
- Flatpak requires explicit permission
## Automatic Cleanup ## Automatic Cleanup
Roster automatically removes keyring secrets when you delete variables, environments, or projects. Renamed variables are also automatically updated in the keyring. Roster removes keyring entries when you delete or rename variables, environments, or projects.
## Script Integration ## Flatpak
Scripts can access sensitive variables transparently: Requires D-Bus permission `--talk-name=org.freedesktop.secrets` in the Flatpak manifest.
### Reading Sensitive Variables
```javascript
// Preprocessing script
const apiKey = roster.getVariable('api_key'); // Retrieved from keyring
request.headers['X-API-Key'] = apiKey;
console.log('Using API key'); // DON'T log the actual value!
```
### Writing Sensitive Variables
```javascript
// Postprocessing script
const data = JSON.parse(response.body);
// If 'access_token' is marked as sensitive, it goes to keyring
roster.setVariable('access_token', data.access_token);
console.log('Saved access token to keyring');
```
Scripts don't need to know whether variables are sensitive - storage is handled automatically.
## Troubleshooting
**Keyring not unlocked:**
- Ensure you're logged into GNOME (keyring unlocks automatically)
- Manual unlock: Open Seahorse, right-click "Login", select "Unlock"
**Flatpak permission denied:**
- Verify `cz.bugsy.roster.json` includes `--talk-name=org.freedesktop.secrets`
- Check: `flatpak info --show-permissions cz.bugsy.roster`
**Secrets missing after reinstall:**
- Keyring persists across installs - check Seahorse under "Login" keyring
## Platform Notes
Both native and Flatpak installations use the same system keyring. Secrets work across install methods.
Flatpak requires D-Bus permission: `--talk-name=org.freedesktop.secrets`
## Next Steps
- [[Variables]] - Learn about regular variables
- [[Scripts]] - Use variables in automation scripts
- [[API-Reference]] - Complete JavaScript API documentation

@ -1,216 +1,48 @@
# Variables # Variables
Variables allow you to reuse values across multiple requests and switch between different environments (development, staging, production) with ease. Variables let you reuse values across requests and switch between environments (dev, staging, prod) with one click.
## What are Variables? ## Syntax
Variables are placeholder values that you can reference in your requests using the `{{variable_name}}` syntax. When you send a request, Roster automatically replaces these placeholders with the actual values from your selected environment. Use `{{variable_name}}` in URL, headers, or body. When sending, Roster replaces placeholders with values from the selected environment.
**Example:**
``` ```
URL: {{base_url}}/users GET {{base_url}}/users
Headers: Authorization: Bearer {{api_token}}
Authorization: Bearer {{api_token}}
``` ```
When sent with the "Production" environment: ## Managing Environments and Variables
```
URL: https://api.example.com/users
Headers:
Authorization: Bearer prod-token-abc123
```
## Environments Open via **⋯ → Manage Environments** next to the project name in the sidebar.
Environments are collections of variable values. Common environment names: - **Add environment:** click **+** next to the environment list
- **Production** - Live API credentials - **Add variable:** click **+** at the bottom of the variable list
- **Staging** - Pre-production testing - **Delete:** click **×** on the variable row or environment header
- **Development** - Local development server - **Rename:** click the name inline
Each project can have multiple environments, and each environment has its own set of variable values. Values are entered in the table cells per environment. Close the dialog to save.
## Creating Environments ## Selecting an Environment
### Step 1: Open Environments Dialog Use the environment dropdown at the top of the request panel. All `{{...}}` placeholders resolve to values from the selected environment.
1. Select a project from the sidebar Undefined variables are highlighted with a warning color; the literal `{{variable_name}}` is sent as-is.
2. Click the "Three-Dots" button near the project name
3. Select **"Manage Environments"**
### Step 2: Add Environment ## Script Access
1. Click **+** button near Environments
2. Enter name (e.g., "Production", "Development")
3. Click **"Add"**
The environment appears as a new column in the table.
### Step 3: Add Variables
1. Click the **"+"** button at the bottom of the variable list
2. Enter variable name (e.g., `base_url`)
3. Click **"Add"**
The variable appears as a new row in the table.
### Step 4: Set Values
Click in the cells to enter values for each environment:
| Variable | Production | Development |
|----------|-----------|-------------|
| base_url | `https://api.example.com` | `http://localhost:3000` |
| timeout | `30` | `60` |
Close Manage Environments table to save.
## Using Variables in Requests
### Variable Syntax
Use double curly braces: `{{variable_name}}`
Variables work in:
- **URL**: `{{base_url}}/users`
- **Headers**: `Authorization: Bearer {{token}}`
- **Request Body**: `{"api_key": "{{api_key}}"}`
### Select Environment
1. Open a request tab
2. Use the **environment dropdown** (top of request panel)
3. Select environment (e.g., "Production")
4. All variables in the request will use values from this environment
### Visual Indicators
**Defined variables** - Normal appearance
**Undefined variables** - Highlighted with a warning color
- Variable name exists in `{{...}}` syntax
- But not defined in current environment
## Managing Variables
### Rename Variable
1. Open **Manage Environments** dialog
2. Click on variable name
3. Edit the name
The variable is renamed across all environments automatically.
### Delete Variable
1. Open **Environments** dialog
2. Click the **x** next to variable name
3. Confirm deletion
The variable is removed from all environments.
### Rename Environment
1. Open **Environments** dialog
2. Click the **edit icon** on environment column header
3. Enter new name
4. Click **"Save"**
### Delete Environment
1. Open **Environments** dialog
2. Click the **trash icon** on environment column header
3. Confirm deletion
All variable values for that environment are deleted.
**Note:** Each project must have at least one environment.
## Common Variable Patterns
Common variables to define across environments:
- `base_url` - API base URL (e.g., `https://api.example.com` vs `http://localhost:3000`)
- `api_version` - API version (e.g., `v2` vs `v2-beta`)
- `timeout` - Request timeout values
- `env` - Environment identifier for headers
- `test_user_id` - Test data IDs
## Script Integration
Variables can be accessed and modified from [[Scripts]]:
### Reading Variables (Preprocessing)
```javascript ```javascript
const baseUrl = roster.getVariable('base_url'); // Preprocessing
const apiKey = roster.getVariable('api_key'); const url = roster.getVariable('base_url');
console.log('Using base URL:', baseUrl); // Preprocessing or postprocessing
request.headers['X-API-Key'] = apiKey;
```
### Writing Variables (Postprocessing)
```javascript
// Extract token from response and save for next request
const data = JSON.parse(response.body);
roster.setVariable('auth_token', data.access_token); roster.setVariable('auth_token', data.access_token);
roster.setVariable('user_id', data.user_id); roster.setVariables({ token: data.token, user_id: data.id });
console.log('Saved token for user:', data.user_id);
``` ```
### Batch Updates ## Sensitive Variables
```javascript For API keys and passwords, use [[Sensitive-Variables]] — values are stored in GNOME Keyring instead of plain-text JSON.
// Update multiple variables at once
roster.setVariables({
access_token: data.access_token,
refresh_token: data.refresh_token,
user_id: data.user.id,
user_name: data.user.name
});
```
Scripts automatically update variables in the currently selected environment. ## Storage
## Variable Scoping Regular variables: `~/.local/share/cz.bugsy.roster/requests.json` (Flatpak: `~/.var/app/cz.bugsy.roster/data/cz.bugsy.roster/requests.json`)
**Project Level:**
- Variables are defined at the project level
- All requests in the project can access these variables
**Environment Level:**
- Variable values are specific to each environment
- Switching environments switches all values at once
**Not Global:**
- Variables from one project cannot be used in another project
- Each project has its own isolated set of variables
## Best Practices
- **Keep environments consistent** - All environments should have the same variable names with different values
- **Use sensitive variables for secrets** - Never store API keys, passwords, or tokens in regular variables (they're plain text). Use [[Sensitive-Variables]] instead
## Undefined Variables
When `{{variable_name}}` is not defined in the current environment:
- Entry field is highlighted with warning color
- The literal text `{{variable_name}}` is sent in the request
To fix, add the variable in the Environments dialog.
## Environment Switching
Use the environment dropdown to test the same request against different targets. For example, `GET {{base_url}}/users` will hit `localhost:3000/users` in Development or `api.example.com/users` in Production.
## Advanced Topics
- **Variables in JSON body** - Use `{{variable}}` syntax. Remove quotes for numeric values
- **Nested variables** - Variables can reference other variables (e.g., `{{base_url}}/{{api_version}}`)
- **Script-created variables** - Scripts can create variables with `roster.setVariable()`
## Next Steps
- [[Sensitive-Variables]] - Store API keys and secrets securely
- [[Scripts]] - Automate variable management with JavaScript
- [[API-Reference]] - Complete API for working with variables