193 lines
5.6 KiB
Markdown
193 lines
5.6 KiB
Markdown
# Roster
|
|
|
|
A modern HTTP client for GNOME, built with GTK 4 and libadwaita.
|
|
|
|
## Features
|
|
|
|
- Send HTTP requests (GET, POST, PUT, DELETE)
|
|
- Configure custom headers and request bodies
|
|
- View response headers and bodies
|
|
- Track request history with persistence
|
|
- **JavaScript preprocessing and postprocessing scripts**
|
|
- **Project environments with variables**
|
|
- Beautiful GNOME-native UI
|
|
|
|
## Dependencies
|
|
|
|
- GTK 4
|
|
- libadwaita 1
|
|
- Python 3
|
|
- libsoup3 (provided by GNOME Platform)
|
|
- gjs (GNOME JavaScript) - for script execution
|
|
|
|
## Building
|
|
|
|
```bash
|
|
meson setup builddir
|
|
meson compile -C builddir
|
|
sudo meson install -C builddir
|
|
```
|
|
|
|
## Usage
|
|
|
|
Roster uses libsoup3 (from GNOME Platform) for making HTTP requests - no external dependencies required.
|
|
|
|
Run Roster from your application menu or with the `roster` command.
|
|
|
|
## Scripts
|
|
|
|
Roster supports JavaScript preprocessing and postprocessing scripts to automate request modifications and response data extraction.
|
|
|
|
### Preprocessing Scripts
|
|
|
|
**Run BEFORE the HTTP request is sent.** Use preprocessing to:
|
|
- Modify request headers, URL, body, or method
|
|
- Add dynamic values (timestamps, request IDs, signatures)
|
|
- Read environment variables
|
|
- Set/update environment variables
|
|
|
|
**Available API:**
|
|
```javascript
|
|
// Request object (modifiable)
|
|
request.method // "GET", "POST", "PUT", "DELETE"
|
|
request.url // Full URL string
|
|
request.headers // Object with header key-value pairs
|
|
request.body // Request body string
|
|
|
|
// Roster API
|
|
roster.getVariable(name) // Get variable from selected environment
|
|
roster.setVariable(name, value) // Set/update variable
|
|
roster.setVariables({key: value}) // Batch set variables
|
|
roster.project.name // Current project name
|
|
roster.project.environments // Array of environment names
|
|
|
|
// Console output
|
|
console.log(message) // Output shown in preprocessing results
|
|
```
|
|
|
|
**Example 1: Add Dynamic Authentication Header**
|
|
```javascript
|
|
const token = roster.getVariable('auth_token');
|
|
request.headers['Authorization'] = 'Bearer ' + token;
|
|
request.headers['X-Request-Time'] = new Date().toISOString();
|
|
console.log('Added auth header for token:', token);
|
|
```
|
|
|
|
**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');
|
|
}
|
|
```
|
|
|
|
**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);
|
|
```
|
|
|
|
### Postprocessing Scripts
|
|
|
|
**Run AFTER receiving the HTTP response.** Use postprocessing to:
|
|
- Extract data from response body
|
|
- Parse JSON/XML responses
|
|
- Store values in environment variables for use in subsequent requests
|
|
- Validate response data
|
|
|
|
**Available API:**
|
|
```javascript
|
|
// Response object (read-only)
|
|
response.body // Response body as string
|
|
response.headers // Object with header key-value pairs
|
|
response.statusCode // HTTP status code (e.g., 200, 404)
|
|
response.statusText // Status text (e.g., "OK", "Not Found")
|
|
response.responseTime // Response time in milliseconds
|
|
|
|
// Roster API
|
|
roster.setVariable(name, value) // Set/update variable
|
|
roster.setVariables({key: value}) // Batch set variables
|
|
|
|
// Console output
|
|
console.log(message) // Output shown in script results
|
|
```
|
|
|
|
**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');
|
|
}
|
|
```
|
|
|
|
**Example 2: Extract Multiple Values**
|
|
```javascript
|
|
const data = JSON.parse(response.body);
|
|
roster.setVariables({
|
|
user_id: data.user.id,
|
|
user_name: data.user.name,
|
|
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);
|
|
}
|
|
console.log('Found', data.items.length, 'items');
|
|
} else {
|
|
console.log('Error: Invalid response');
|
|
}
|
|
```
|
|
|
|
### Workflow Example: OAuth Token Flow
|
|
|
|
**Request 1 (Login) - Postprocessing:**
|
|
```javascript
|
|
// Extract and store tokens from login response
|
|
const data = JSON.parse(response.body);
|
|
roster.setVariables({
|
|
access_token: data.access_token,
|
|
refresh_token: data.refresh_token,
|
|
user_id: data.user_id
|
|
});
|
|
console.log('Logged in as user:', data.user_id);
|
|
```
|
|
|
|
**Request 2 (API Call) - Preprocessing:**
|
|
```javascript
|
|
// Use stored token in subsequent request
|
|
const token = roster.getVariable('access_token');
|
|
const userId = roster.getVariable('user_id');
|
|
|
|
request.headers['Authorization'] = 'Bearer ' + token;
|
|
request.url = request.url.replace('{userId}', userId);
|
|
console.log('Making authenticated request for user:', userId);
|
|
```
|
|
|
|
### Environment Variables
|
|
|
|
Variables can be:
|
|
- Manually defined in "Manage Environments"
|
|
- Automatically created by scripts using `roster.setVariable()`
|
|
- Used in requests with `{{variable_name}}` syntax
|
|
- Read in preprocessing with `roster.getVariable()`
|
|
|
|
Variables are scoped to environments within projects, allowing different values for development, staging, and production.
|