Human-friendly and powerful HTTP request library for Node.js
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Response objects with parsed bodies, metadata, timing information, and utilities for processing HTTP responses.
The main response interface containing parsed body data and comprehensive metadata.
/**
* Complete response object with parsed body and metadata
*/
interface Response<T = unknown> extends PlainResponse {
/**
* Parsed response body based on responseType
*/
body: T;
/**
* HTTP status code
*/
statusCode: number;
/**
* HTTP status message
*/
statusMessage?: string;
/**
* Response headers
*/
headers: IncomingHttpHeaders;
/**
* Original request URL
*/
requestUrl: URL;
/**
* Array of redirect URLs if redirects occurred
*/
redirectUrls: URL[];
/**
* Final URL after redirects
*/
url: string;
/**
* Request object that generated this response
*/
request: Request;
/**
* Detailed timing information
*/
timings: Timings;
/**
* Number of retry attempts made
*/
retryCount: number;
/**
* Whether response indicates success (2xx status)
*/
ok: boolean;
/**
* Whether response was retrieved from cache
*/
isFromCache: boolean;
/**
* Remote IP address (if available)
*/
ip?: string;
/**
* Raw response body buffer
*/
rawBody?: Buffer;
}The base response interface without parsed body, used internally and for error handling.
/**
* Response object without parsed body
*/
interface PlainResponse {
/**
* Original request URL
*/
requestUrl: URL;
/**
* Array of redirect URLs
*/
redirectUrls: URL[];
/**
* Request object that generated this response
*/
request: Request;
/**
* Remote IP address (if available)
*/
ip?: string;
/**
* Whether response was retrieved from cache
*/
isFromCache: boolean;
/**
* HTTP status code
*/
statusCode: number;
/**
* Final URL after redirects
*/
url: string;
/**
* Detailed timing information
*/
timings: Timings;
/**
* Number of retry attempts made
*/
retryCount: number;
/**
* Raw response body buffer (if available)
*/
rawBody?: Buffer;
/**
* Parsed response body (if available)
*/
body?: unknown;
/**
* Whether response indicates success
*/
ok: boolean;
}Response body parsing based on the responseType option and content type detection.
/**
* Parse response body based on response type
* @param response - Raw response object
* @param responseType - Desired response type
* @param parseJson - Custom JSON parsing function
* @param encoding - Text encoding for string responses
* @returns Parsed response body
*/
function parseBody<T>(
response: IncomingMessageWithTimings,
responseType: ResponseType,
parseJson?: ParseJsonFunction,
encoding?: BufferEncoding
): T;
/**
* Response body parsing types
*/
type ResponseType = "text" | "json" | "buffer";
/**
* Custom JSON parsing function
*/
type ParseJsonFunction = (text: string) => unknown;Usage Examples:
import got from "got";
// Text response
const textResponse = await got("https://example.com", {
responseType: "text"
});
console.log(typeof textResponse.body); // "string"
// JSON response
const jsonResponse = await got("https://api.example.com/users", {
responseType: "json"
});
console.log(typeof jsonResponse.body); // "object"
// Buffer response
const bufferResponse = await got("https://example.com/image.png", {
responseType: "buffer"
});
console.log(Buffer.isBuffer(bufferResponse.body)); // true
// Custom JSON parsing
const customResponse = await got("https://api.example.com/data", {
responseType: "json",
parseJson: (text) => {
return JSON.parse(text, (key, value) => {
// Convert ISO date strings to Date objects
if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(value)) {
return new Date(value);
}
return value;
});
}
});Detailed timing information for performance monitoring and debugging.
/**
* Detailed timing information for HTTP requests
*/
interface Timings {
/**
* Time when the request started
*/
start: number;
/**
* Time when a socket was assigned
*/
socket?: number;
/**
* Time when DNS lookup finished
*/
lookup?: number;
/**
* Time when socket connected
*/
connect?: number;
/**
* Time when TLS handshake completed
*/
secureConnect?: number;
/**
* Time when request was sent
*/
upload?: number;
/**
* Time when response started
*/
response?: number;
/**
* Time when response finished
*/
end?: number;
/**
* Time when error occurred
*/
error?: number;
/**
* Time when request was aborted
*/
abort?: number;
/**
* Calculated phase timings
*/
phases: {
/**
* Time waiting for socket assignment
*/
wait?: number;
/**
* DNS lookup time
*/
dns?: number;
/**
* TCP connection time
*/
tcp?: number;
/**
* TLS handshake time
*/
tls?: number;
/**
* Request upload time
*/
request?: number;
/**
* Time to first byte
*/
firstByte?: number;
/**
* Response download time
*/
download?: number;
/**
* Total request time
*/
total?: number;
};
}Usage Examples:
import got from "got";
const response = await got("https://api.example.com/data");
console.log("Timing breakdown:");
console.log(`DNS lookup: ${response.timings.phases.dns}ms`);
console.log(`TCP connect: ${response.timings.phases.tcp}ms`);
console.log(`TLS handshake: ${response.timings.phases.tls}ms`);
console.log(`Request: ${response.timings.phases.request}ms`);
console.log(`First byte: ${response.timings.phases.firstByte}ms`);
console.log(`Download: ${response.timings.phases.download}ms`);
console.log(`Total: ${response.timings.phases.total}ms`);
// Performance monitoring
if (response.timings.phases.total > 5000) {
console.warn("Slow request detected:", response.requestUrl.href);
}Utilities for checking response status and success conditions.
/**
* Check if response status indicates success
* @param response - Response object
* @returns Whether response is successful
*/
function isResponseOk(response: PlainResponse): boolean;Usage Examples:
import got from "got";
// Disable automatic error throwing
const response = await got("https://api.example.com/might-fail", {
throwHttpErrors: false
});
// Manual status checking
if (response.ok) {
console.log("Request successful:", response.body);
} else {
console.error(`Request failed: ${response.statusCode} ${response.statusMessage}`);
// Handle specific status codes
switch (response.statusCode) {
case 404:
console.log("Resource not found");
break;
case 429:
console.log("Rate limited");
break;
case 500:
console.log("Server error");
break;
default:
console.log("Other error:", response.statusCode);
}
}
// Check response properties
console.log("Status:", response.statusCode);
console.log("Headers:", response.headers);
console.log("From cache:", response.isFromCache);
console.log("Redirects:", response.redirectUrls.length);
console.log("Retries:", response.retryCount);Working with HTTP response headers and metadata.
/**
* HTTP response headers
*/
type IncomingHttpHeaders = Record<string, string | string[] | undefined>;Usage Examples:
import got from "got";
const response = await got("https://api.example.com/data");
// Access common headers
console.log("Content-Type:", response.headers["content-type"]);
console.log("Content-Length:", response.headers["content-length"]);
console.log("Cache-Control:", response.headers["cache-control"]);
console.log("ETag:", response.headers.etag);
// Check for specific headers
if (response.headers["x-ratelimit-remaining"]) {
const remaining = parseInt(response.headers["x-ratelimit-remaining"] as string);
if (remaining < 10) {
console.warn("Rate limit nearly exceeded:", remaining);
}
}
// Link header parsing for pagination
if (response.headers.link) {
const linkHeader = response.headers.link as string;
console.log("Link header:", linkHeader);
// Parse link header (requires parseLinkHeader utility)
const links = parseLinkHeader(linkHeader);
console.log("Next page:", links.next);
}
// Last-Modified header for caching
if (response.headers["last-modified"]) {
const lastModified = new Date(response.headers["last-modified"] as string);
console.log("Last modified:", lastModified);
}Convenient methods for accessing different response types without specifying responseType.
interface CancelableRequest<T> extends Promise<T> {
/**
* Get response body as parsed JSON
* @returns Promise resolving to parsed JSON
*/
json<ReturnType>(): CancelableRequest<ReturnType>;
/**
* Get response body as Buffer
* @returns Promise resolving to Buffer
*/
buffer(): CancelableRequest<Buffer>;
/**
* Get response body as text string
* @returns Promise resolving to string
*/
text(): CancelableRequest<string>;
}Usage Examples:
import got from "got";
// JSON shortcut
const users = await got("https://api.example.com/users").json();
console.log(users); // Parsed JSON object
// Text shortcut
const html = await got("https://example.com").text();
console.log(typeof html); // "string"
// Buffer shortcut
const imageBuffer = await got("https://example.com/image.png").buffer();
console.log(Buffer.isBuffer(imageBuffer)); // true
// Type-safe JSON shortcut
interface User {
id: number;
name: string;
email: string;
}
const typedUsers = await got("https://api.example.com/users").json<User[]>();
console.log(typedUsers[0].name); // TypeScript knows this is a stringInformation about cached responses and cache behavior.
import got from "got";
const response = await got("https://api.example.com/data", {
cache: true
});
// Check if response came from cache
if (response.isFromCache) {
console.log("Response served from cache");
} else {
console.log("Fresh response from server");
}
// Cache-related headers
console.log("Cache-Control:", response.headers["cache-control"]);
console.log("ETag:", response.headers.etag);
console.log("Expires:", response.headers.expires);
// Conditional requests
const etag = response.headers.etag;
if (etag) {
const conditionalResponse = await got("https://api.example.com/data", {
headers: {
"If-None-Match": etag
},
throwHttpErrors: false
});
if (conditionalResponse.statusCode === 304) {
console.log("Content not modified, use cached version");
}
}Working with streaming responses for large data or real-time processing.
import got from "got";
import { pipeline } from "node:stream";
import { createWriteStream } from "node:fs";
// Stream large responses
const downloadStream = got.stream("https://example.com/large-file.zip");
downloadStream.on("response", (response) => {
console.log("Response started:");
console.log("Status:", response.statusCode);
console.log("Content-Length:", response.headers["content-length"]);
console.log("Content-Type:", response.headers["content-type"]);
});
downloadStream.on("downloadProgress", (progress) => {
if (progress.total) {
const percent = Math.round((progress.transferred / progress.total) * 100);
console.log(`Download progress: ${percent}%`);
}
});
// Save to file
await pipeline(downloadStream, createWriteStream("download.zip"));Handling different response scenarios and error conditions.
import got, { HTTPError } from "got";
async function handleResponse() {
try {
const response = await got("https://api.example.com/data");
// Successful response
console.log("Success:", response.statusCode);
return response.body;
} catch (error) {
if (error instanceof HTTPError) {
// HTTP error response
const { response } = error;
console.log("HTTP Error:", response.statusCode);
console.log("Response body:", response.body);
console.log("Headers:", response.headers);
// Handle specific errors
if (response.statusCode === 429) {
const retryAfter = response.headers["retry-after"];
console.log("Rate limited, retry after:", retryAfter);
}
return null;
} else {
// Network or other error
throw error;
}
}
}
// Graceful handling without throwing
async function safeRequest() {
const response = await got("https://api.example.com/data", {
throwHttpErrors: false
});
return {
success: response.ok,
status: response.statusCode,
data: response.ok ? response.body : null,
error: response.ok ? null : response.statusMessage
};
}