Create and extend Got instances with custom defaults and configurations for reusable HTTP clients with shared settings and behavior.
Factory function for creating new Got instances with custom default configurations.
/**
* Create a new Got instance with custom defaults
* @param defaults - Default configuration for the instance
* @returns New Got instance
*/
function create(defaults: InstanceDefaults): Got;
/**
* Instance defaults configuration
*/
interface InstanceDefaults {
/**
* Default options for all requests
*/
options: Options;
/**
* Array of handler functions executed for each request
* @default []
*/
handlers: HandlerFunction[];
/**
* Whether defaults can be modified after creation
* @default false
*/
mutableDefaults: boolean;
}
/**
* Handler function for customizing request processing
*/
type HandlerFunction = <T extends GotReturn>(
options: Options,
next: (options: Options) => T
) => T | Promise<T>;Usage Examples:
import { create, Options } from "got";
// Create instance with API base URL and auth
const api = create({
options: new Options({
prefixUrl: "https://api.example.com",
headers: {
"Authorization": "Bearer your-token-here",
"User-Agent": "MyApp/1.0"
},
timeout: { request: 10000 },
retry: { limit: 3 }
}),
handlers: [],
mutableDefaults: false
});
// Use the instance
const users = await api.get("users").json();
const user = await api.post("users", {
json: { name: "Alice", email: "alice@example.com" }
}).json();Create new instances by extending existing ones with additional or modified configuration.
/**
* Instance extension interface
*/
interface Got {
/**
* Create extended instance with merged configuration
* @param instancesOrOptions - Instances or options to merge
* @returns New extended Got instance
*/
extend<T extends Array<Got | ExtendOptions>>(...instancesOrOptions: T): Got<MergeExtendsConfig<T>>;
/**
* Access to instance defaults
*/
defaults: InstanceDefaults;
}
/**
* Options for extending instances
*/
interface ExtendOptions extends OptionsInit {
/**
* Handler functions for request processing
*/
handlers?: HandlerFunction[];
/**
* Whether defaults are mutable
*/
mutableDefaults?: boolean;
}Usage Examples:
import got from "got";
// Create base API client
const api = got.extend({
prefixUrl: "https://api.example.com",
headers: {
"User-Agent": "MyApp/1.0"
},
timeout: { request: 10000 }
});
// Extend for authenticated requests
const authenticatedApi = api.extend({
headers: {
"Authorization": "Bearer token123"
}
});
// Extend for specific service
const userService = authenticatedApi.extend({
prefixUrl: "https://api.example.com/users",
responseType: "json",
resolveBodyOnly: true
});
// Use extended instances
const users = await userService.get(""); // GET /users
const user = await userService.get("123"); // GET /users/123Access and inspect instance configuration and defaults.
/**
* Instance defaults object
*/
interface InstanceDefaults {
/**
* Default options used by the instance
*/
readonly options: Options;
/**
* Handler functions executed for each request
*/
readonly handlers: readonly HandlerFunction[];
/**
* Whether the defaults can be modified
*/
readonly mutableDefaults: boolean;
}Usage Examples:
import got from "got";
const api = got.extend({
prefixUrl: "https://api.example.com",
headers: { "Authorization": "Bearer token" }
});
// Inspect instance defaults
console.log("Base URL:", api.defaults.options.prefixUrl);
console.log("Headers:", api.defaults.options.headers);
console.log("Handlers count:", api.defaults.handlers.length);
console.log("Mutable:", api.defaults.mutableDefaults);
// Create new instance with modified defaults
const newApi = api.extend({
timeout: { request: 5000 }
});Custom handler functions for request processing and middleware-like functionality.
/**
* Handler function signature
* @param options - Request options
* @param next - Function to call next handler or make request
* @returns Request result or promise
*/
type HandlerFunction = <T extends GotReturn>(
options: Options,
next: (options: Options) => T
) => T | Promise<T>;
/**
* Got return type (Request or CancelableRequest)
*/
type GotReturn = Request | CancelableRequest;Usage Examples:
import got, { create, Options } from "got";
// Logging handler
const loggingHandler: HandlerFunction = (options, next) => {
console.log(`Making request to: ${options.url}`);
const start = Date.now();
const result = next(options);
if (result instanceof Promise) {
return result.then(response => {
console.log(`Request completed in ${Date.now() - start}ms`);
return response;
});
}
return result;
};
// Retry handler
const retryHandler: HandlerFunction = async (options, next) => {
const maxRetries = 3;
let lastError: Error;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await next(options);
} catch (error) {
lastError = error;
if (attempt === maxRetries) break;
// Wait before retry
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
}
}
throw lastError;
};
// Create instance with handlers
const api = create({
options: new Options({ prefixUrl: "https://api.example.com" }),
handlers: [loggingHandler, retryHandler],
mutableDefaults: false
});Combine multiple instances to create complex configurations.
import got from "got";
// Base configuration
const baseApi = got.extend({
timeout: { request: 10000 },
retry: { limit: 2 }
});
// Authentication configuration
const authConfig = got.extend({
headers: {
"Authorization": "Bearer token123"
}
});
// JSON configuration
const jsonConfig = got.extend({
responseType: "json",
resolveBodyOnly: true,
headers: {
"Content-Type": "application/json"
}
});
// Compose all configurations
const apiClient = got.extend(baseApi, authConfig, jsonConfig, {
prefixUrl: "https://api.example.com"
});
// Use composed client
const users = await apiClient.get("users");
const newUser = await apiClient.post("users", {
json: { name: "Alice" }
});Create instances with mutable defaults that can be updated at runtime.
import { create, Options } from "got";
// Create instance with mutable defaults
const api = create({
options: new Options({
prefixUrl: "https://api.example.com",
headers: { "Authorization": "Bearer initial-token" }
}),
handlers: [],
mutableDefaults: true
});
// Update token at runtime
api.defaults.options.headers["Authorization"] = "Bearer new-token";
// Or update entire header object
Object.assign(api.defaults.options.headers, {
"Authorization": "Bearer updated-token",
"X-Client-Version": "1.2.0"
});
// Use updated instance
const response = await api.get("protected-resource");Warning: Mutable defaults should be used carefully as they can lead to unexpected behavior in concurrent scenarios.
Service-specific clients:
import got from "got";
// Base API configuration
const baseApi = got.extend({
prefixUrl: "https://api.example.com",
headers: {
"Authorization": "Bearer token",
"User-Agent": "MyApp/1.0"
},
timeout: { request: 10000 },
retry: { limit: 3 }
});
// User service
export const userService = baseApi.extend({
prefixUrl: "https://api.example.com/users",
responseType: "json",
resolveBodyOnly: true
});
// Order service
export const orderService = baseApi.extend({
prefixUrl: "https://api.example.com/orders",
responseType: "json",
resolveBodyOnly: true
});
// Usage
const users = await userService.get(""); // GET /users
const user = await userService.get("123"); // GET /users/123
const orders = await orderService.get(""); // GET /ordersEnvironment-specific clients:
import got from "got";
const createApiClient = (environment: string) => {
const baseUrls = {
development: "https://dev-api.example.com",
staging: "https://staging-api.example.com",
production: "https://api.example.com"
};
return got.extend({
prefixUrl: baseUrls[environment],
headers: {
"User-Agent": `MyApp/1.0 (${environment})`
},
timeout: {
request: environment === "development" ? 30000 : 10000
},
retry: {
limit: environment === "production" ? 3 : 1
}
});
};
// Create environment-specific clients
export const devApi = createApiClient("development");
export const prodApi = createApiClient("production");Plugin pattern:
import got from "got";
// Plugin for adding API key authentication
const withApiKey = (apiKey: string) => got.extend({
headers: {
"X-API-Key": apiKey
}
});
// Plugin for adding request logging
const withLogging = () => got.extend({
hooks: {
beforeRequest: [
(options) => {
console.log(`→ ${options.method} ${options.url}`);
}
],
afterResponse: [
(response) => {
console.log(`← ${response.statusCode} ${response.requestUrl}`);
return response;
}
]
}
});
// Plugin for adding retry logic
const withRetry = (maxRetries: number = 3) => got.extend({
retry: {
limit: maxRetries,
methods: ["GET", "PUT", "HEAD", "DELETE", "OPTIONS", "TRACE"],
statusCodes: [408, 413, 429, 500, 502, 503, 504]
}
});
// Compose plugins
const api = got
.extend(withApiKey("your-api-key"))
.extend(withLogging())
.extend(withRetry(5))
.extend({
prefixUrl: "https://api.example.com"
});Maintain type safety when extending instances with custom configurations.
/**
* Type for merging extend configurations
*/
type MergeExtendsConfig<T extends Array<Got | ExtendOptions>> = /* complex type merging logic */;
/**
* Extract extend options from Got instance or options
*/
type ExtractExtendOptions<T> = T extends Got<infer GotOptions> ? GotOptions : T;Usage:
import got from "got";
// Typed API client
interface ApiResponse<T> {
data: T;
status: "success" | "error";
message?: string;
}
const typedApi = got.extend({
prefixUrl: "https://api.example.com",
responseType: "json",
resolveBodyOnly: true
});
// Type-safe usage
const response = await typedApi.get("users") as ApiResponse<User[]>;
const user = await typedApi.post("users", {
json: { name: "Alice" }
}) as ApiResponse<User>;