TypeScript SDK Middlewares

Overview

Middleware is used to add functionality to the request object in the TypeScript SDK.

You can add middleware when creating the TypeScript SDK client. Multiple middlewares can be added using a chain of middleware builder methods.

const client = new ClientBuilder()
.withClientCredentialsFlow(authMiddlewareOptions)
.withHttpMiddleware(httpMiddlewareOptions)
.withLoggerMiddleware()
// Chain additional middleware here
.build();
Clipboard icon

Available middleware

HttpMiddleware

Handles sending the HTTP request to the Composable Commerce API.

type HttpMiddlewareOptions = {
host: string;
credentialsMode?: 'omit' | 'same-origin' | 'include';
includeHeaders?: boolean;
includeResponseHeaders?: boolean;
includeOriginalRequest?: boolean;
includeRequestInErrorResponse?: boolean;
maskSensitiveHeaderData?: boolean;
timeout?: number;
enableRetry?: boolean;
retryConfig?: {
maxRetries?: number;
retryDelay?: number;
backoff?: boolean;
maxDelay?: number;
retryOnAbort?: boolean;
retryCodes?: Array<number | string>;
};
fetch?: any;
abortController?: AbortController; // deprecated
getAbortController?: () => AbortController;
};
const options: HttpMiddlewareOptions = {
host: 'https://api.europe-west1.gcp.commercetools.com',
includeResponseHeaders: true,
maskSensitiveHeaderData: true,
includeOriginalRequest: false,
includeRequestInErrorResponse: false,
enableRetry: true,
retryConfig: {
maxRetries: 3,
retryDelay: 200,
backoff: false,
retryCodes: [403],
},
fetch: fetchFn,
};
const client = new ClientBuilder()
.withHttpMiddleware(options)
// ...
.build();
Clipboard icon

AuthMiddleware

Handles generating, authenticating, and refreshing auth tokens used when making authenticated requests to the Composable Commerce API.

The auth token lifecycle is managed by the SDK and there is usually no need to directly interact or access the authentication token. Expired tokens are automatically discarded and new tokens are generated (or refreshed if using withRefreshTokenFlow) for new requests.

The following authentication flows can be used. The main difference in the authentication flows is the options that can be passed to each of the middlewares.

withClientCredentialsFlow

Handles authentication for the client credentials flow of the Composable Commerce API.

type AuthMiddlewareOptions = {
host: string
projectKey: string
credentials: Credentials
scopes?: Array<string>
oauthUri?: string
fetch?: any
tokenCache?: TokenCache
}
const options: AuthMiddlewareOptions {
host: 'https://auth.europe-west1.gcp.commercetools.com',
projectKey: 'test-project-key',
credentials: {
clientId: process.env.CTP_CLIENT_ID,
clientSecret: process.env.CTP_CLIENT_SECRET
},
scopes: [`manage_project:${projectKey}`],
fetch: fetchFn
}
const client = new ClientBuilder()
.withClientCredentialsFlow(options)
// ...
.build()
Clipboard icon

withPasswordFlow

Handles authentication for the password flow of the Composable Commerce API.

type PasswordAuthMiddlewareOptions = {
host: string;
projectKey: string;
credentials: {
clientId: string;
clientSecret: string;
user: {
username: string;
password: string;
};
};
scopes?: Array<string>;
tokenCache?: TokenCache;
oauthUri?: string;
fetch?: any;
};
const options: PasswordAuthMiddlewareOptions = {
host: 'https://auth.europe-west1.gcp.commercetools.com',
projectKey: 'test-project-key',
credentials: {
clientId: process.env.CTP_CLIENT_ID,
clientSecret: process.env.CTP_CLIENT_SECRET,
user: {
username: process.env.USERNAME,
password: process.env.PASSWORD,
},
},
scopes: [`manage_project:${projectKey}`],
fetch: fetchFn,
};
const client = new ClientBuilder()
.withPasswordFlow(options)
// ...
.build();
Clipboard icon

withAnonymousSessionFlow

Handles authentication for the anonymous session flow of the Composable Commerce API.

type AnonymousAuthMiddlewareOptions = {
host: string;
projectKey: string;
credentials: {
clientId: string;
clientSecret: string;
anonymousId?: string;
};
scopes?: Array<string>;
oauthUri?: string;
fetch?: any;
tokenCache?: TokenCache;
};
const options: AnonymousAuthMiddlewareOptions = {
host: 'https://auth.europe-west1.gcp.commercetools.com',
projectKey: 'test-project-key',
credentials: {
clientId: process.env.CTP_CLIENT_ID,
clientSecret: process.env.CTP_CLIENT_SECRET,
anonymousId: process.env.CTP_ANONYMOUS_ID, // a unique id
},
scopes: [`manage_project:${projectKey}`],
fetch: fetchFn,
};
const client = new ClientBuilder()
.withAnonymousSessionFlow(options)
// ...
.build();
Clipboard icon

withRefreshTokenFlow

Handles authentication for the refresh token flow of the Composable Commerce API.

type RefreshAuthMiddlewareOptions = {
host: string;
projectKey: string;
credentials: {
clientId: string;
clientSecret: string;
};
refreshToken: string;
tokenCache?: TokenCache;
oauthUri?: string;
fetch?: any;
};
const options: RefreshAuthMiddlewareOptions = {
host: 'https://auth.europe-west1.gcp.commercetools.com',
projectKey: 'test-project-key',
credentials: {
clientId: process.env.CTP_CLIENT_ID,
clientSecret: process.env.CTP_CLIENT_SECRET,
},
refreshToken: 'bXvTyxc5yuebdvwTwyXn==',
tokenCache: TokenCache,
scopes: [`manage_project:${projectKey}`],
fetch: fetchFn,
};
const client = new ClientBuilder()
.withRefreshTokenFlow(options)
// ...
.build();
Clipboard icon

withExistingTokenFlow

Attaches an access token Authorization header.

type ExistingTokenMiddlewareOptions = {
force?: boolean;
};
const authorization: string = 'bXvTyxc5yuebdvwTwyXn==';
const options: ExistingTokenMiddlewareOptions = {
force: true,
};
const client = new ClientBuilder()
.withExistingTokenFlow(authorization, options)
// ...
.build();
Clipboard icon

CorrelationIdMiddleware

CorrelationIdMiddlewareExternal link icon adds the X-Correlation-ID entry to the request headers.

type CorrelationIdMiddlewareOptions = {
generate: () => string;
};
const options: CorrelationIdMiddlewareOptions = {
generate: () => 'cd260fc9-c575-4ba3-8789-cc4c9980ee4e', // Replace with your own UUID or a generator function
};
const client = new ClientBuilder()
.withCorrelationIdMiddleware(options)
// ...
.build();
Clipboard icon

UserAgentMiddleware

UserAgentMiddlewareExternal link icon adds a customizable User-Agent header to every request. By default it adds the SDK (and its version) and the running process (and its version) to the request. For example:

'User-Agent': 'commercetools-sdk-javascript-v2/2.1.4 node.js/18.13.0'

type HttpUserAgentOptions = {
name?: string;
version?: string;
libraryName?: string;
libraryVersion?: string;
contactUrl?: string;
contactEmail?: string;
customAgent?: string;
};
const options: HttpUserAgentOptions = {
name: 'test-client-agent',
version: '2.9.0',
};
const client = new ClientBuilder()
.withUserAgentMiddleware(options)
// ...
.build();
Clipboard icon

QueueMiddleware

Throttles concurrent requests, which is useful for reducing concurrent HTTP requests.

type QueueMiddlewareOptions = {
concurrency: number;
};
const options: QueueMiddlewareOptions = {
concurrency: 20,
};
const client = new ClientBuilder()
.withQueueMiddleware(options)
// ...
.build();
Clipboard icon

LoggerMiddleware

Logs incoming requests and response objects.

const client = new ClientBuilder()
.withLoggerMiddleware()
// ...
.build();
Clipboard icon

Custom middleware

Certain use cases, such as adding headers to API requests, may require you to create custom middleware.

The following code example demonstrates how to create custom middleware that includes a value for the header X-External-User-ID.

function customHeaderMiddleware() {
return (next) => (request, response) => {
const newRequest = {
...request,
headers: {
...request.headers,
'X-External-User-ID': 'custom-header-value',
},
};
next(newRequest, response);
};
}
Clipboard icon

This custom middleware can then be added using the .withMiddleware() method.

const client = new ClientBuilder()
.withMiddleware(customHeaderMiddleware())
// ...
.build();
Clipboard icon