CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-superagent

Elegant & feature rich browser / node HTTP with a fluent API

Pending
Overview
Eval results
Files

response-handling.mddocs/

Response Handling

Response object properties and methods for accessing response data, headers, and metadata with comprehensive parsing and error handling capabilities.

Capabilities

Response Properties

Core properties available on response objects returned from requests.

/**
 * Response object properties
 */
interface Response {
  /** HTTP status code (e.g., 200, 404, 500) */
  status: number;
  
  /** HTTP status code (alias for status) */
  statusCode: number;
  
  /** Raw response body as string */
  text: string;
  
  /** Parsed response body (JSON, form data, etc.) */
  body: any;
  
  /** Response headers object (lowercase keys) */
  header: object;
  
  /** Content type without parameters */
  type: string;
  
  /** Character encoding (e.g., 'utf8') */
  charset: string;
  
  /** Array of redirect URLs if redirects occurred */
  redirects: string[];
  
  /** Files object for multipart responses */
  files?: object;
  
  /** Links header parsed into object */
  links: object;
  
  /** Response status type (1-5, representing 1xx, 2xx, etc.) */
  statusType: number;
  
  /** Boolean status flags */
  info: boolean;        // 1xx status codes
  ok: boolean;          // 2xx status codes  
  redirect: boolean;    // 3xx status codes
  clientError: boolean; // 4xx status codes
  serverError: boolean; // 5xx status codes
  error: boolean | Error; // 4xx or 5xx status codes
  
  /** Specific status code flags */
  created: boolean;           // 201
  accepted: boolean;          // 202
  noContent: boolean;         // 204
  badRequest: boolean;        // 400
  unauthorized: boolean;      // 401
  forbidden: boolean;         // 403
  notFound: boolean;          // 404
  notAcceptable: boolean;     // 406
  unprocessableEntity: boolean; // 422
}

Usage Examples:

const superagent = require('superagent');

const response = await superagent.get('https://api.example.com/users');

// Status information
console.log('Status:', response.status);        // 200
console.log('Status:', response.statusCode);    // 200 (alias)

// Response body
console.log('Raw text:', response.text);        // Raw response string
console.log('Parsed body:', response.body);     // Parsed JSON/XML/etc

// Headers
console.log('All headers:', response.header);
console.log('Content-Type:', response.header['content-type']);

// Content information
console.log('Content type:', response.type);    // 'application/json'
console.log('Charset:', response.charset);      // 'utf8'

// Redirect information
if (response.redirects.length > 0) {
  console.log('Redirected through:', response.redirects);
}

// Status flags and classifications
console.log('Status type:', response.statusType);  // 2 (for 2xx)
console.log('Is success:', response.ok);           // true for 2xx
console.log('Is redirect:', response.redirect);    // true for 3xx
console.log('Is client error:', response.clientError); // true for 4xx
console.log('Is server error:', response.serverError); // true for 5xx
console.log('Has error:', !!response.error);       // true for 4xx/5xx

// Specific status code flags
if (response.created) {
  console.log('Resource was created (201)');
}
if (response.noContent) {
  console.log('No content returned (204)');
}
if (response.notFound) {
  console.log('Resource not found (404)');
}
if (response.unauthorized) {
  console.log('Authentication required (401)');
}

Response Methods

Methods available on response objects for accessing specific data.

/**
 * Get response header field value (case-insensitive)
 * @param {string} field - Header field name
 * @returns {string} Header field value
 */
Response.prototype.get(field): string;

/**
 * Create an Error object from the response for error handling
 * @returns {Error} Error object with response details
 */
Response.prototype.toError(): Error;

Usage Examples:

const response = await superagent.get('https://api.example.com/data');

// Get specific headers (case-insensitive)
console.log('Content-Type:', response.get('Content-Type'));
console.log('content-type:', response.get('content-type')); // Same result
console.log('Authorization:', response.get('authorization'));

// Common headers
console.log('Cache-Control:', response.get('Cache-Control'));
console.log('ETag:', response.get('ETag'));
console.log('Last-Modified:', response.get('Last-Modified'));

// Convert response to error (useful for error status codes)
if (response.error) {
  const errorObj = response.toError();
  console.log('Error message:', errorObj.message);
  console.log('Error status:', errorObj.status);
}

Response Body Parsing

Automatic parsing based on content type with support for various formats.

// JSON responses
const jsonResponse = await superagent.get('https://api.example.com/users.json');
console.log('Users:', jsonResponse.body.users); // Automatically parsed JSON

// XML responses (if parser is configured)
const xmlResponse = await superagent.get('https://api.example.com/data.xml');
console.log('XML body:', xmlResponse.body);

// Form-encoded responses
const formResponse = await superagent.get('https://api.example.com/form-data');
console.log('Form data:', formResponse.body);

// Binary responses
const binaryResponse = await superagent
  .get('https://api.example.com/file.pdf')
  .responseType('blob'); // Browser
console.log('Binary data:', binaryResponse.body);

// Text responses
const textResponse = await superagent.get('https://api.example.com/plain.txt');
console.log('Text content:', textResponse.text);
console.log('Also available as body:', textResponse.body);

Error Response Handling

Handle error responses with detailed information.

try {
  const response = await superagent.get('https://api.example.com/data');
  console.log('Success:', response.body);
} catch (err) {
  // Error responses still have response object
  if (err.response) {
    console.log('Error status:', err.response.status);
    console.log('Error body:', err.response.body);
    console.log('Error text:', err.response.text);
    console.log('Error headers:', err.response.header);
    
    // Handle specific error codes
    switch (err.response.status) {
      case 400:
        console.log('Bad request:', err.response.body.message);
        break;
      case 401:
        console.log('Unauthorized - check credentials');
        break;
      case 404:
        console.log('Resource not found');
        break;
      case 500:
        console.log('Server error:', err.response.body.error);
        break;
      default:
        console.log('Unexpected error:', err.response.status);
    }
  } else {
    // Network or other errors without response
    console.error('Network error:', err.message);
  }
}

Response Status Checking

Check response status and handle different scenarios.

const response = await superagent
  .get('https://api.example.com/data')
  .ok(res => res.status < 500); // Don't throw on 4xx errors

// Check status ranges
if (response.status >= 200 && response.status < 300) {
  console.log('Success response');
} else if (response.status >= 300 && response.status < 400) {
  console.log('Redirect response');
} else if (response.status >= 400 && response.status < 500) {
  console.log('Client error');
} else if (response.status >= 500) {
  console.log('Server error');
}

// Check specific status codes
switch (response.status) {
  case 200:
    console.log('OK');
    break;
  case 201:
    console.log('Created');
    break;
  case 204:
    console.log('No Content');
    break;
  case 304:
    console.log('Not Modified');
    break;
}

Headers Analysis

Analyze and use response headers for various purposes.

const response = await superagent.get('https://api.example.com/data');

// Content information
const contentType = response.get('Content-Type');
const contentLength = response.get('Content-Length');
const encoding = response.get('Content-Encoding');

console.log(`Received ${contentLength} bytes of ${contentType}`);
if (encoding) {
  console.log(`Content encoded with: ${encoding}`);
}

// Caching headers
const cacheControl = response.get('Cache-Control');
const etag = response.get('ETag');
const lastModified = response.get('Last-Modified');

if (cacheControl) {
  console.log('Cache policy:', cacheControl);
}

// Security headers
const securityHeaders = [
  'X-Content-Type-Options',
  'X-Frame-Options',
  'X-XSS-Protection',
  'Strict-Transport-Security'
];

securityHeaders.forEach(header => {
  const value = response.get(header);
  if (value) {
    console.log(`${header}: ${value}`);
  }
});

// Custom application headers
const requestId = response.get('X-Request-ID');
const rateLimit = response.get('X-RateLimit-Remaining');

if (requestId) {
  console.log('Request ID:', requestId);
}
if (rateLimit) {
  console.log('Rate limit remaining:', rateLimit);
}

Multipart Response Handling

Handle multipart responses with files and form data.

const response = await superagent
  .post('https://api.example.com/upload')
  .attach('file', '/path/to/file.txt')
  .field('title', 'My File');

// Access form fields
console.log('Response body:', response.body);

// Access uploaded files (if server returns file info)
if (response.files) {
  console.log('Files processed:', response.files);
}

// Parse multipart response
const multipartResponse = await superagent
  .get('https://api.example.com/multipart-data')
  .buffer(true);

if (multipartResponse.files) {
  Object.keys(multipartResponse.files).forEach(fieldName => {
    const file = multipartResponse.files[fieldName];
    console.log(`File ${fieldName}:`, {
      name: file.name,
      size: file.size,
      type: file.type
    });
  });
}

Response Streaming

Handle streamed responses for large data.

const fs = require('fs');

// Stream response to file
const request = superagent.get('https://api.example.com/large-file.zip');
const writeStream = fs.createWriteStream('/path/to/output.zip');

request.pipe(writeStream);

// Handle streaming events
request.on('response', (res) => {
  console.log('Response started:', res.status);
  console.log('Content-Length:', res.get('Content-Length'));
});

request.on('progress', (event) => {
  console.log(`Downloaded: ${event.loaded}/${event.total} bytes`);
});

writeStream.on('finish', () => {
  console.log('Download completed');
});

writeStream.on('error', (err) => {
  console.error('Download failed:', err);
});

Response Processing Patterns

Common patterns for processing responses.

// Paginated response handling
async function fetchAllPages(baseUrl) {
  const allData = [];
  let nextUrl = baseUrl;
  
  while (nextUrl) {
    const response = await superagent.get(nextUrl);
    
    allData.push(...response.body.data);
    
    // Check for pagination info in headers or body
    const linkHeader = response.get('Link');
    nextUrl = parseLinkHeader(linkHeader)?.next;
    
    // Or check response body for next page
    // nextUrl = response.body.pagination?.next_url;
  }
  
  return allData;
}

// Response validation
function validateResponse(response) {
  // Check content type
  const contentType = response.get('Content-Type');
  if (!contentType || !contentType.includes('application/json')) {
    throw new Error('Expected JSON response');
  }
  
  // Check required fields
  if (!response.body.data) {
    throw new Error('Missing required data field');
  }
  
  // Validate response structure
  if (typeof response.body.data !== 'object') {
    throw new Error('Invalid data format');
  }
  
  return response.body;
}

// Usage
try {
  const response = await superagent.get('https://api.example.com/data');
  const validatedData = validateResponse(response);
  console.log('Valid data:', validatedData);
} catch (err) {
  console.error('Validation failed:', err.message);
}

Response Caching

Implement response caching based on headers.

const responseCache = new Map();

async function cachedRequest(url) {
  // Check cache first
  const cached = responseCache.get(url);
  if (cached && !isCacheExpired(cached)) {
    console.log('Using cached response');
    return cached.response;
  }
  
  // Make request with cache headers
  const request = superagent.get(url);
  
  if (cached) {
    // Add conditional request headers
    if (cached.etag) {
      request.set('If-None-Match', cached.etag);
    }
    if (cached.lastModified) {
      request.set('If-Modified-Since', cached.lastModified);
    }
  }
  
  try {
    const response = await request;
    
    // Cache the response
    responseCache.set(url, {
      response: response,
      etag: response.get('ETag'),
      lastModified: response.get('Last-Modified'),
      cacheControl: response.get('Cache-Control'),
      timestamp: Date.now()
    });
    
    return response;
    
  } catch (err) {
    if (err.status === 304) {
      // Not modified, return cached version
      console.log('Resource not modified, using cache');
      return cached.response;
    }
    throw err;
  }
}

function isCacheExpired(cached) {
  if (cached.cacheControl) {
    const maxAge = extractMaxAge(cached.cacheControl);
    if (maxAge && Date.now() - cached.timestamp > maxAge * 1000) {
      return true;
    }
  }
  return false;
}

Install with Tessl CLI

npx tessl i tessl/npm-superagent

docs

agent-sessions.md

auth-security.md

file-uploads.md

http-methods.md

index.md

parsers-serializers.md

request-building.md

request-execution.md

response-handling.md

tile.json