HTTP(S)
HTTP client generator creates type-safe functions for making HTTP requests based on your API specification. It supports various authentication methods, pagination, retry logic, and extensibility hooks.
It is currently available through the generators (channels):
All of this is available through AsyncAPI. Requires HTTP method binding for operation and statusCode for messages.
TypeScript
| Feature | Is supported? |
|---|---|
| Download | ❌ |
| Upload | ❌ |
| Offset based Pagination | ✅ |
| Cursor based Pagination | ✅ |
| Page based Pagination | ✅ |
| Range based Pagination | ✅ |
| Retry with backoff | ✅ |
| OAuth2 Authorization code | ❌ (browser-only) |
| OAuth2 Implicit | ❌ (browser-only) |
| OAuth2 Password | ✅ |
| OAuth2 Client Credentials | ✅ |
| OAuth2 Token Refresh | ✅ |
| Username/password Authentication | ✅ |
| Bearer Authentication | ✅ |
| Basic Authentication | ✅ |
| API Key Authentication | ✅ |
| Request/Response Hooks | ✅ |
| XML Based API | ❌ |
| JSON Based API | ✅ |
| POST | ✅ |
| GET | ✅ |
| PATCH | ✅ |
| DELETE | ✅ |
| PUT | ✅ |
| HEAD | ✅ |
| OPTIONS | ✅ |
Channels
Read more about the channels generator here.
| Input (AsyncAPI) | Using the code |
|---|---|
| |
Authentication
The HTTP client uses a discriminated union for authentication, providing excellent TypeScript autocomplete support.
Bearer Token
const response = await postPingPostRequest({
payload: message,
server: 'https://api.example.com',
auth: {
type: 'bearer',
token: 'your-jwt-token'
}
});
Basic Authentication
const response = await postPingPostRequest({
payload: message,
server: 'https://api.example.com',
auth: {
type: 'basic',
username: 'user',
password: 'pass'
}
});
API Key
// API Key in header (default)
const response = await postPingPostRequest({
payload: message,
server: 'https://api.example.com',
auth: {
type: 'apiKey',
key: 'your-api-key',
name: 'X-API-Key', // Header name (default: 'X-API-Key')
in: 'header' // 'header' or 'query'
}
});
// API Key in query parameter
const response = await postPingPostRequest({
payload: message,
server: 'https://api.example.com',
auth: {
type: 'apiKey',
key: 'your-api-key',
name: 'api_key',
in: 'query'
}
});
OAuth2 Client Credentials
For server-to-server authentication:
const response = await postPingPostRequest({
payload: message,
server: 'https://api.example.com',
auth: {
type: 'oauth2',
flow: 'client_credentials',
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
tokenUrl: 'https://auth.example.com/oauth/token',
scopes: ['read', 'write'],
onTokenRefresh: (tokens) => {
// Called when tokens are obtained/refreshed
console.log('New access token:', tokens.accessToken);
}
}
});
OAuth2 Password Flow
For legacy applications requiring username/password:
const response = await postPingPostRequest({
payload: message,
server: 'https://api.example.com',
auth: {
type: 'oauth2',
flow: 'password',
clientId: 'your-client-id',
username: 'user@example.com',
password: 'user-password',
tokenUrl: 'https://auth.example.com/oauth/token',
onTokenRefresh: (tokens) => {
// Store tokens for future use
saveTokens(tokens);
}
}
});
OAuth2 with Pre-obtained Token
For tokens obtained via browser-based flows (implicit, authorization code):
// Token obtained from browser OAuth flow
const accessToken = getTokenFromBrowserFlow();
const response = await postPingPostRequest({
payload: message,
server: 'https://api.example.com',
auth: {
type: 'oauth2',
accessToken: accessToken,
refreshToken: refreshToken, // Optional: for auto-refresh on 401
tokenUrl: 'https://auth.example.com/oauth/token',
clientId: 'your-client-id',
onTokenRefresh: (tokens) => {
// Update stored tokens
updateStoredTokens(tokens);
}
}
});
Pagination
The HTTP client supports multiple pagination strategies. Pagination parameters can be placed in query parameters or headers.
Offset-based Pagination
const response = await getItemsRequest({
server: 'https://api.example.com',
pagination: {
type: 'offset',
offset: 0,
limit: 25,
in: 'query', // 'query' or 'header'
offsetParam: 'offset', // Query param name (default: 'offset')
limitParam: 'limit' // Query param name (default: 'limit')
}
});
// Navigate pages
if (response.hasNextPage?.()) {
const nextPage = await response.getNextPage?.();
}
Cursor-based Pagination
const response = await getItemsRequest({
server: 'https://api.example.com',
pagination: {
type: 'cursor',
cursor: undefined, // First page
limit: 25,
cursorParam: 'cursor'
}
});
// Get next page using cursor from response
if (response.pagination?.nextCursor) {
const nextPage = await response.getNextPage?.();
}
Page-based Pagination
const response = await getItemsRequest({
server: 'https://api.example.com',
pagination: {
type: 'page',
page: 1,
pageSize: 25,
pageParam: 'page',
pageSizeParam: 'per_page'
}
});
Range-based Pagination (RFC 7233)
const response = await getItemsRequest({
server: 'https://api.example.com',
pagination: {
type: 'range',
start: 0,
end: 24,
unit: 'items', // Range unit (default: 'items')
rangeHeader: 'Range' // Header name (default: 'Range')
}
});
// Sends: Range: items=0-24
Retry with Exponential Backoff
Configure automatic retry for failed requests:
const response = await postPingPostRequest({
payload: message,
server: 'https://api.example.com',
retry: {
maxRetries: 3, // Maximum retry attempts (default: 3)
initialDelayMs: 1000, // Initial delay before first retry (default: 1000)
maxDelayMs: 30000, // Maximum delay between retries (default: 30000)
backoffMultiplier: 2, // Exponential backoff multiplier (default: 2)
retryableStatusCodes: [408, 429, 500, 502, 503, 504], // Status codes to retry
retryOnNetworkError: true, // Retry on network failures
onRetry: (attempt, delay, error) => {
console.log(`Retry attempt ${attempt} after ${delay}ms: ${error.message}`);
}
}
});
Request/Response Hooks
Customize request behavior with hooks:
const response = await postPingPostRequest({
payload: message,
server: 'https://api.example.com',
hooks: {
// Modify request before sending
beforeRequest: async (params) => {
console.log('Making request to:', params.url);
// Add custom header
return {
...params,
headers: {
...params.headers,
'X-Request-ID': generateRequestId()
}
};
},
// Replace the default fetch implementation
makeRequest: async (params) => {
// Use axios, got, or any HTTP client
const axiosResponse = await axios({
url: params.url,
method: params.method,
headers: params.headers,
data: params.body
});
return {
ok: axiosResponse.status >= 200 && axiosResponse.status < 300,
status: axiosResponse.status,
statusText: axiosResponse.statusText,
headers: axiosResponse.headers,
json: () => axiosResponse.data
};
},
// Process response after receiving
afterResponse: async (response, params) => {
console.log(`Response ${response.status} from ${params.url}`);
return response;
},
// Handle errors
onError: async (error, params) => {
console.error(`Request failed: ${error.message}`);
// Optionally transform the error
return error;
}
}
});
Path Parameters
For operations with path parameters, the generator creates typed parameter classes:
import { UserItemsParameters } from './__gen__/parameters/UserItemsParameters';
// Create parameters with type safety
const params = new UserItemsParameters({
userId: 'user-123',
itemId: 456
});
const response = await getGetUserItem({
server: 'https://api.example.com',
parameters: params // Replaces {userId} and {itemId} in path
});
Typed Headers
For operations with defined headers, the generator creates typed header classes:
import { ItemRequestHeaders } from './__gen__/headers/ItemRequestHeaders';
const headers = new ItemRequestHeaders({
xCorrelationId: 'corr-123',
xRequestId: 'req-456'
});
const response = await putUpdateUserItem({
server: 'https://api.example.com',
parameters: params,
payload: itemData,
requestHeaders: headers // Type-safe headers
});
Additional Headers and Query Parameters
Add custom headers or query parameters to any request:
const response = await postPingPostRequest({
payload: message,
server: 'https://api.example.com',
additionalHeaders: {
'X-Custom-Header': 'value',
'Accept-Language': 'en-US'
},
queryParams: {
include: 'metadata',
format: 'detailed'
}
});
Multi-Status Responses
For operations that return different payloads based on status code, the generator creates union types:
# AsyncAPI spec with multiple response types
operations:
getItem:
reply:
messages:
- $ref: '#/components/messages/ItemResponse' # 200
- $ref: '#/components/messages/NotFoundError' # 404
const response = await getItemRequest({
server: 'https://api.example.com',
parameters: params
});
// Response type is union: ItemResponse | NotFoundError
// Use response.status to discriminate
if (response.status === 200) {
console.log('Item:', response.data); // ItemResponse
} else if (response.status === 404) {
console.log('Not found:', response.data); // NotFoundError
}