Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/juanjh1/asimilation/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Asimilation extends Node.js’s native IncomingMessage and ServerResponse with additional features to make handling HTTP requests and responses more convenient. These enhanced objects are available in all route handlers and middlewares.

Request Object

The request object extends Node.js’s IncomingMessage with additional properties for working with dynamic route parameters.

Type Definition

class ArgumentedIncomingMessageAbc extends IncomingMessage {
  params: Record<string, string>;
}
Defined in abstract/abstract_req.ts:7-11 and interface in interfaces/custom-request.ts:3-5.

Standard Properties

All standard Node.js IncomingMessage properties are available:
url.addPath("/example", (req, res) => {
  console.log(req.method);     // "GET", "POST", etc.
  console.log(req.url);        // "/example?foo=bar"
  console.log(req.headers);    // Headers object
  console.log(req.httpVersion); // "1.1"
});

Route Parameters

The params property contains captured URL parameters from dynamic routes:
url.addPath("/users/<int:id>", (req, res) => {
  const userId = req.params.id;
  res.sendJson({ userId }, 200);
});

// Request to /users/123
// req.params = { id: "123" }
Parameters are always strings, even when using typed routes like <int:id>. You’ll need to parse them if you need numeric values.

Multiple Parameters

url.addPath("/api/<string:resource>/<int:id>", (req, res) => {
  const { resource, id } = req.params;
  // Request to /api/users/42
  // resource = "users", id = "42"
  
  res.sendJson({ resource, id }, 200);
});

Request Headers

Access headers through the standard headers property:
url.addPath("/api/data", (req, res) => {
  const contentType = req.headers["content-type"];
  const auth = req.headers.authorization;
  const userAgent = req.headers["user-agent"];
  
  res.sendJson({ contentType, auth }, 200);
});

Query Parameters

Query parameters are parsed automatically and available via the URL:
url.addPath("/search", (req, res) => {
  // Request to /search?q=test&page=2
  const url = new URL(req.url!, `http://${req.headers.host}`);
  const query = url.searchParams.get("q");      // "test"
  const page = url.searchParams.get("page");    // "2"
  
  res.sendJson({ query, page }, 200);
});
The URL is split at the ? character during routing (see router-manager.ts:113-114) to separate the path from query parameters.

Request Body

For POST/PUT requests, you’ll need to read the body from the stream:
url.addPath("/api/users", async (req, res) => {
  let body = "";
  
  req.on("data", (chunk) => {
    body += chunk.toString();
  });
  
  req.on("end", () => {
    try {
      const data = JSON.parse(body);
      res.sendJson({ received: data }, 201);
    } catch (error) {
      res.sendJson({ error: "Invalid JSON" }, 400);
    }
  });
}, { methods: ["POST"] });
Consider creating a middleware to parse request bodies automatically. See the Middlewares guide for an example.

Response Object

The response object extends Node.js’s ServerResponse with convenient helper methods for common response types.

Type Definition

class ArgumentedServerResponseAbc extends ServerResponse {
  sendJson(json: Object, code: number): void;
  sendText(text: string, code: number): void;
  redirect(url: string, code?: number): void;
}
Defined in abstract/abstract_res.ts:5-21 and interface in interfaces/custom-server-response.ts:3-11.

sendJson()

Send a JSON response with proper headers:
url.addPath("/api/users", (req, res) => {
  const users = [
    { id: 1, name: "John" },
    { id: 2, name: "Jane" }
  ];
  
  res.sendJson({ users }, 200);
});
Implementation (see abstract/abstract_res.ts:7-9 and helpers/http-responses.ts:14-22):
  • Sets Content-Type to application/json
  • Stringifies the object with pretty printing
  • Sets the status code
  • Ends the response

Common Status Codes

// Success responses
res.sendJson({ data }, 200);        // OK
res.sendJson({ created: true }, 201); // Created
res.sendJson({}, 204);              // No Content

// Client errors
res.sendJson({ error: "Bad Request" }, 400);
res.sendJson({ error: "Unauthorized" }, 401);
res.sendJson({ error: "Forbidden" }, 403);
res.sendJson({ error: "Not Found" }, 404);

// Server errors
res.sendJson({ error: "Internal Error" }, 500);

sendText()

Send a plain text response:
url.addPath("/health", (req, res) => {
  res.sendText("OK", 200);
});

url.addPath("/about", (req, res) => {
  res.sendText("About our application", 200);
});
Implementation (see abstract/abstract_res.ts:12-14 and helpers/http-responses.ts:25-32):
  • Sets Content-Type to text/plain
  • Sets the status code
  • Ends the response with the text

redirect()

Redirect to another URL:
url.addPath("/old-page", (req, res) => {
  res.redirect("/new-page", 302); // Temporary redirect
});

url.addPath("/moved", (req, res) => {
  res.redirect("/permanent-location", 301); // Permanent redirect
});

url.addPath("/login", (req, res) => {
  res.redirect("/dashboard"); // Defaults to 302
});
Implementation (see abstract/abstract_res.ts:17-19 and helpers/http-responses.ts:35-43):
  • Sets the Location header
  • Sets the status code (default 302)
  • Ends the response

Redirect Status Codes

  • 301 - Moved Permanently
  • 302 - Found (Temporary Redirect)
  • 303 - See Other
  • 307 - Temporary Redirect (Strict)
  • 308 - Permanent Redirect (Strict)

Standard Methods

All standard Node.js ServerResponse methods are also available:
url.addPath("/custom", (req, res) => {
  // Set headers
  res.setHeader("Content-Type", "application/xml");
  res.setHeader("X-Custom-Header", "value");
  
  // Write status code
  res.statusCode = 200;
  
  // Write response body
  res.write("<xml>");
  res.write("<data>content</data>");
  res.write("</xml>");
  
  // End response
  res.end();
});

Custom Response Formats

For custom response formats, use the standard Node.js API:

XML Response

url.addPath("/api/data.xml", (req, res) => {
  const xml = `<?xml version="1.0"?>
<response>
  <status>success</status>
</response>`;
  
  res.writeHead(200, { "Content-Type": "application/xml" });
  res.end(xml);
});

HTML Response

url.addPath("/page", (req, res) => {
  const html = `
<!DOCTYPE html>
<html>
<head><title>Page</title></head>
<body><h1>Hello World</h1></body>
</html>`;
  
  res.writeHead(200, { "Content-Type": "text/html" });
  res.end(html);
});

Binary Response

import { readFile } from "fs/promises";

url.addPath("/download", async (req, res) => {
  const file = await readFile("./file.pdf");
  
  res.writeHead(200, {
    "Content-Type": "application/pdf",
    "Content-Disposition": "attachment; filename=file.pdf"
  });
  res.end(file);
});

Complete Example

Here’s a complete example using request and response features:
import { url } from "@asimilation/core";

// GET user by ID
url.addPath("/api/users/<int:id>", (req, res) => {
  const userId = req.params.id;
  const accept = req.headers.accept;
  
  const user = {
    id: parseInt(userId),
    name: "John Doe",
    email: "john@example.com"
  };
  
  // Content negotiation
  if (accept?.includes("application/json")) {
    res.sendJson(user, 200);
  } else {
    res.sendText(JSON.stringify(user), 200);
  }
}, { methods: ["GET"] });

// Create user
url.addPath("/api/users", (req, res) => {
  let body = "";
  
  req.on("data", chunk => {
    body += chunk.toString();
  });
  
  req.on("end", () => {
    try {
      const userData = JSON.parse(body);
      
      // Validate
      if (!userData.name || !userData.email) {
        res.sendJson({ error: "Missing required fields" }, 400);
        return;
      }
      
      // Create user (pseudo-code)
      const newUser = {
        id: 123,
        ...userData
      };
      
      res.sendJson(newUser, 201);
    } catch (error) {
      res.sendJson({ error: "Invalid JSON" }, 400);
    }
  });
}, { methods: ["POST"] });

// Update user
url.addPath("/api/users/<int:id>", (req, res) => {
  const userId = req.params.id;
  let body = "";
  
  req.on("data", chunk => {
    body += chunk.toString();
  });
  
  req.on("end", () => {
    try {
      const updates = JSON.parse(body);
      
      // Update user (pseudo-code)
      const updatedUser = {
        id: parseInt(userId),
        ...updates
      };
      
      res.sendJson(updatedUser, 200);
    } catch (error) {
      res.sendJson({ error: "Invalid JSON" }, 400);
    }
  });
}, { methods: ["PUT"] });

// Delete user
url.addPath("/api/users/<int:id>", (req, res) => {
  const userId = req.params.id;
  
  // Delete user (pseudo-code)
  // deleteUser(userId);
  
  res.sendJson({ deleted: true, id: userId }, 200);
}, { methods: ["DELETE"] });

How It Works Internally

When a request is received (see router-manager.ts:103-146):
1

Prototype Enhancement

The native request and response objects have their prototypes set to the enhanced classes (router-manager.ts:110-111).
2

URL Parsing

The URL is split to separate the path from query parameters (router-manager.ts:113-115).
3

Route Matching

The path is matched against static and dynamic routes to find the handler.
4

Parameter Extraction

For dynamic routes, parameters are extracted and set on req.params (router-manager.ts:137).
5

Handler Execution

The route handler receives the enhanced request and response objects (router-manager.ts:139).

Type Safety

For better type safety in TypeScript, you can create custom types:
import { ArgumentedIncomingMessageAbc, ArgumentedServerResponseAbc } from "@asimilation/core";

interface RequestWithUser extends ArgumentedIncomingMessageAbc {
  user?: {
    id: number;
    name: string;
  };
}

url.addPath("/api/profile", (req: RequestWithUser, res) => {
  const user = req.user; // Type-safe access
  res.sendJson(user, 200);
});

Best Practices

Always set status codes

Explicitly set appropriate HTTP status codes for all responses.

Use helper methods

Prefer sendJson() and sendText() over manual response construction.

Validate input

Always validate request parameters and body data before processing.

Handle errors

Catch errors and return appropriate error responses to clients.

Next Steps

Routing

Learn how to define routes and capture parameters

Middlewares

Discover how to process requests with middlewares