CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-micro

Asynchronous HTTP microservices framework with built-in body parsing and error handling

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

response-handling.mddocs/

Response Handling

Response sending utilities with automatic content-type detection and error response management for HTTP microservices.

Capabilities

Send Function

Sends HTTP responses with automatic content-type detection and proper headers for different data types.

/**
 * Sends HTTP response with automatic content-type detection
 * @param res - Node.js ServerResponse object
 * @param code - HTTP status code (required)
 * @param obj - Data to send (optional, defaults to null for empty response)
 */
function send(res: ServerResponse, code: number, obj?: unknown): void;

Automatic Content-Type Handling:

  • null/undefined: Empty response with no content
  • Buffer: application/octet-stream with Content-Length
  • Stream: application/octet-stream, pipes stream to response
  • Object/Array: application/json; charset=utf-8 with JSON serialization
  • String: Text response with Content-Length
  • Number: Converted to string with Content-Length

Usage Examples:

import { send } from "micro";

const handler = async (req, res) => {
  // JSON response
  send(res, 200, { message: "Success", data: [1, 2, 3] });
  
  // Text response
  send(res, 200, "Hello World");
  
  // Buffer response
  send(res, 200, Buffer.from("Binary data"));
  
  // Empty response
  send(res, 204); // or send(res, 204, null);
  
  // Error response
  send(res, 400, { error: "Bad Request", code: "INVALID_INPUT" });
};

// Stream response
import fs from "fs";

const fileHandler = async (req, res) => {
  const stream = fs.createReadStream("./large-file.pdf");
  send(res, 200, stream);
  
  // Handle stream errors
  stream.on('error', (err) => {
    send(res, 500, { error: "File read error" });
  });
};

Send Error Function

Specialized function for sending error responses with automatic status code handling and development/production error visibility.

/**
 * Sends error responses with status code and message handling
 * @param req - Incoming HTTP request (for logging context)
 * @param res - HTTP response object
 * @param errorObj - Error object to send (Error or HttpError)
 */
function sendError(req: IncomingMessage, res: ServerResponse, errorObj: Error | HttpError): void;

Error Handling Behavior:

  • Uses errorObj.statusCode if available, otherwise defaults to 500
  • Sends error message as response body
  • Logs error stack to console with console.error
  • In development mode (NODE_ENV=development), includes stack traces in response

Usage Examples:

import { sendError, createError, HttpError, json } from "micro";

const handler = async (req, res) => {
  try {
    // Some operation that might fail
    throw new Error("Database connection failed");
  } catch (error) {
    // Send generic error
    sendError(req, res, error as Error);
    return;
  }
};

// With HTTP status codes
const validationHandler = async (req, res) => {
  try {
    const data = await json(req);
    if (!data.email) {
      const error = createError(400, "Email is required", new Error("Missing email"));
      sendError(req, res, error);
      return;
    }
    return { success: true };
  } catch (error) {
    sendError(req, res, error as Error);
  }
};

// Custom error handling
const customHandler = async (req, res) => {
  try {
    // Your code here
  } catch (error) {
    if (error instanceof HttpError && error.statusCode === 429) {
      // Custom handling for rate limit errors
      send(res, 429, { 
        error: "Rate limited", 
        retryAfter: 60 
      });
    } else {
      sendError(req, res, error as Error);
    }
  }
};

Response Examples

JSON API Response

const apiHandler = async (req, res) => {
  const users = await getUsers();
  
  send(res, 200, {
    data: users,
    pagination: {
      page: 1,
      limit: 10,
      total: users.length
    },
    meta: {
      timestamp: new Date().toISOString(),
      version: "1.0"
    }
  });
};

File Download Response

import fs from "fs";
import path from "path";

const downloadHandler = async (req, res) => {
  const filePath = path.join(__dirname, "files", "document.pdf");
  
  if (!fs.existsSync(filePath)) {
    send(res, 404, { error: "File not found" });
    return;
  }
  
  // Set additional headers before sending
  res.setHeader("Content-Disposition", "attachment; filename=document.pdf");
  res.setHeader("Content-Type", "application/pdf");
  
  const stream = fs.createReadStream(filePath);
  send(res, 200, stream);
};

Conditional Response

const conditionalHandler = async (req, res) => {
  const { format } = req.url?.includes("?") 
    ? new URLSearchParams(req.url.split("?")[1])
    : new URLSearchParams();
  
  const data = { message: "Hello", timestamp: Date.now() };
  
  switch (format) {
    case "xml":
      res.setHeader("Content-Type", "application/xml");
      send(res, 200, `<response><message>${data.message}</message></response>`);
      break;
    case "text":
      send(res, 200, `${data.message} at ${data.timestamp}`);
      break;
    default:
      send(res, 200, data); // JSON
  }
};

docs

body-parsing.md

cli.md

error-management.md

index.md

response-handling.md

server.md

tile.json