Request Middleware
Request Middleware allows you to intercept and modify requests and responses made by the SDK. This can be useful for logging, retries, authentication, metrics collection, custom headers, and other cross-cutting concerns.
Simply put, the middleware is just a function that receives the outgoing request and a next function. The middleware can inspect or modify the request before passing it to the next middleware in the chain.
import { type RequestMiddleware } from '@community-fabs/playfab-sdk/core';
const middleware: RequestMiddleware = async (req, next) => { // Run logic before the request const response = await next(req);
// Run logic after the request return response;};Registering Middleware
Section titled “Registering Middleware”Middleware is attached to a PlayFab SDK instance using the .with() method.
import { initializePlayFab } from '@community-fabs/playfab-sdk/core';
const playfab = initializePlayFab({ titleId: 'YOUR_TITLE_ID', developerSecretKey: 'YOUR_DEV_SECRET_KEY',}).with(myMiddleware());Multiple middleware can be chained together.
const playfab = initializePlayFab({ titleId: 'YOUR_TITLE_ID',}).with(loggerMiddleware()).with(retryMiddleware(3)).with(metricsMiddleware());Middleware executes in the order it is registered.
Logging Requests and Responses
Section titled “Logging Requests and Responses”A simple logging middleware can help with debugging and development.
import { initializePlayFab, type RequestMiddleware,} from '@community-fabs/playfab-sdk/core';
function loggerMiddleware(): RequestMiddleware { return async (req, next) => { console.log('Request:', req);
const res = await next(req);
console.log('Response:', res);
return res; };}
const playfab = initializePlayFab({ titleId: 'YOUR_TITLE_ID',}).with(loggerMiddleware());Retrying Failed Requests
Section titled “Retrying Failed Requests”Middleware can be used to automatically retry failed requests.
import { initializePlayFab, type RequestMiddleware,} from '@community-fabs/playfab-sdk/core';
function retryMiddleware(retries = 2): RequestMiddleware { return async (req, next) => { let lastError: unknown;
for (let i = 0; i <= retries; i++) { try { return await next(req); } catch (err) { lastError = err; } }
throw lastError; };}
const playfab = initializePlayFab({ titleId: 'YOUR_TITLE_ID',}).with(retryMiddleware(3));Adding Custom Headers
Section titled “Adding Custom Headers”Middleware can modify outgoing requests before they are sent.
import { type RequestMiddleware } from '@community-fabs/playfab-sdk/core';
function customHeaderMiddleware(): RequestMiddleware { return async (req, next) => { req.headers = { ...req.headers, 'X-Application-Version': '1.0.0', 'X-Environment': 'development', };
return next(req); };}Measuring Request Duration
Section titled “Measuring Request Duration”You can use middleware to collect performance metrics.
import { type RequestMiddleware } from '@community-fabs/playfab-sdk/core';
function metricsMiddleware(): RequestMiddleware { return async (req, next) => { const start = performance.now();
try { return await next(req); } finally { const duration = performance.now() - start;
console.log( `${req.url} completed in ${duration.toFixed(2)}ms` ); } };}Middleware Execution Order
Section titled “Middleware Execution Order”Middleware wraps around subsequent middleware in the chain.
Given:
initializePlayFab({ titleId: 'YOUR_TITLE_ID',}).with(middlewareA()).with(middlewareB()).with(middlewareC());Execution order:
middlewareA (before) middlewareB (before) middlewareC (before) API Request middlewareC (after) middlewareB (after)middlewareA (after)This pattern allows middleware to perform work both before and after a request is executed.
Common Use Cases
Section titled “Common Use Cases”Middleware can be used for things like:
- Request and response logging
- Automatic retries
- Custom authentication
- Adding request headers
- Metrics and telemetry collection
- Error tracking
- Request timing and profiling
- Distributed tracing
Best Practices
Section titled “Best Practices”- Keep middleware focused on a single responsibility.
- Avoid mutating request objects unless necessary.
- Prefer reusable middleware factories that accept configuration.
- Be cautious when retrying non-idempotent operations.
- Always rethrow errors unless you intentionally want to handle them.
- Keep logging and telemetry lightweight in production environments.