PerishableClient API¶
The PerishableClient class is the core client for interacting with the Perishable proxy server.
Import¶
Constructor¶
PerishableClientOptions¶
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
proxyUrl |
string |
Yes | - | URL of the Perishable proxy server |
apiKey |
string |
No | - | Direct OpenAI API key (for development) |
abusePreventionOptions |
object |
No | See below | Retry and timeout settings |
sessionOptions |
object |
No | See below | Session handling settings |
securityOptions |
object |
No | See below | Security settings |
abusePreventionOptions¶
| Property | Type | Default | Description |
|---|---|---|---|
maxRetries |
number |
3 |
Maximum retry attempts for failed requests |
retryDelay |
number |
1000 |
Base delay between retries (ms) |
requestTimeout |
number |
30000 |
Request timeout (ms) |
requireUserInteraction |
boolean |
true |
Require entropy collection |
sessionOptions¶
| Property | Type | Default | Description |
|---|---|---|---|
expiryBuffer |
number |
300000 |
Refresh session this many ms before expiry |
enableRequestSigning |
boolean |
true |
Enable request signatures |
securityOptions¶
| Property | Type | Default | Description |
|---|---|---|---|
jwtSecret |
string |
- | Secret for JWT signing (should match server) |
Example¶
const client = new PerishableClient({
proxyUrl: 'http://localhost:3000',
abusePreventionOptions: {
maxRetries: 3,
retryDelay: 1000,
requestTimeout: 30000,
requireUserInteraction: true
},
sessionOptions: {
expiryBuffer: 5 * 60 * 1000,
enableRequestSigning: true
}
});
Methods¶
createSession()¶
Create a new session with the proxy server.
Returns: The session token string.
Throws:
- Error if session creation fails
Example:
Behavior:
- Checks if a valid session already exists
- If valid session exists, returns the existing token
- Otherwise, generates a client fingerprint
- Sends fingerprint to proxy server's
/sessionendpoint - Stores the returned token and session data
- Returns the token
makeRequest()¶
Make a request to the OpenAI API through the proxy.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
endpoint |
string |
Yes | OpenAI API endpoint (e.g., /openai/chat/completions) |
options |
RequestInit |
No | Fetch request options |
Returns: A Response object from the fetch API.
Throws:
- Error if using direct API access mode
- Error if all retry attempts fail
Example:
const response = await client.makeRequest('/openai/chat/completions', {
method: 'POST',
body: JSON.stringify({
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: 'Hello!' }]
})
});
const data = await response.json();
Behavior:
- Gets or creates a session token
- Generates the client fingerprint
- Prepares headers with authorization and optional signature
- Adds fingerprint to request body
- Makes request with retry logic (exponential backoff)
Internal Methods¶
These methods are private but understanding them helps with debugging.
isSessionExpired() (private)¶
Checks if the current session has expired or will expire within the buffer period.
getSessionToken() (private)¶
Gets the current session token, creating a new session if needed.
generateRequestSignature() (private)¶
Generates a signature for request integrity verification.
fetchWithTimeout() (private)¶
Makes a fetch request with timeout using AbortController.
fetchWithRetry() (private)¶
Makes a fetch request with exponential backoff retry logic.
SessionData Interface¶
Internal structure for session data:
interface SessionData {
token: string; // JWT token
sessionId: string; // Session identifier
expiresAt: number; // Expiration timestamp (ms)
fingerprint: string; // Client fingerprint
}
Error Handling¶
try {
const response = await client.makeRequest('/openai/chat/completions', {
method: 'POST',
body: JSON.stringify({
model: 'gpt-3.5-turbo',
messages: [{ role: 'user', content: 'Hello!' }]
})
});
if (!response.ok) {
const error = await response.json();
switch (response.status) {
case 401:
console.error('Session expired or invalid');
break;
case 429:
console.error('Rate limit exceeded');
break;
default:
console.error('API error:', error);
}
}
} catch (error) {
if (error.name === 'AbortError') {
console.error('Request timed out');
} else {
console.error('Network error:', error);
}
}
Type Definitions¶
interface PerishableClientOptions {
proxyUrl: string;
apiKey?: string;
abusePreventionOptions?: {
maxRetries?: number;
retryDelay?: number;
requestTimeout?: number;
requireUserInteraction?: boolean;
};
sessionOptions?: {
expiryBuffer?: number;
enableRequestSigning?: boolean;
};
securityOptions?: {
jwtSecret?: string;
};
}
interface SessionData {
token: string;
sessionId: string;
expiresAt: number;
fingerprint: string;
}