CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-connect

High performance middleware framework for Node.js HTTP servers

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

index.mddocs/

Connect

Connect is an extensible HTTP server framework for Node.js using middleware to handle requests. It provides a minimalist foundation for building web applications, APIs, and HTTP services through a composable middleware stack architecture.

Package Information

  • Package Name: connect
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install connect

Core Imports

const connect = require("connect");

For ES modules:

import connect from "connect";

Basic Usage

const connect = require("connect");
const http = require("http");

// Create app
const app = connect();

// Add middleware
app.use(function(req, res, next) {
  res.writeHead(200, { "Content-Type": "text/plain" });
  res.end("Hello from Connect!");
});

// Start server
app.listen(3000);
// or: http.createServer(app).listen(3000);

Architecture

Connect implements a middleware stack pattern where:

  • App Instance: Function that handles HTTP requests and maintains middleware stack
  • Middleware Stack: Array of middleware functions executed in sequence
  • Request Flow: Each request flows through middleware until one responds or all complete
  • Error Handling: Special 4-parameter middleware functions handle errors
  • Route Mounting: Middleware can be mounted on specific URL paths
  • Asynchronous Execution: Uses setImmediate (or process.nextTick fallback) for non-blocking flow
  • Final Handler: Integrates with finalhandler module for unhandled requests/errors

Capabilities

App Creation

Creates a new Connect application instance that can handle HTTP requests.

/**
 * Create a new Connect server application
 * @returns {Function} Connect app function with middleware capabilities
 */
function connect();

The returned app is both a function (req, res, next) => void and an object with methods.

Middleware Registration

Adds middleware functions to the application stack for processing requests.

/**
 * Add middleware function to the app stack
 * @param {string} [route] - Optional path to mount middleware on (defaults to '/')
 * @param {Function|Server} fn - Middleware function, HTTP server, or Connect app
 * @returns {Function} The app instance for chaining
 */
app.use([route], fn);

/**
 * Add middleware function to the app stack (no route)
 * @param {Function|Server} fn - Middleware function, HTTP server, or Connect app  
 * @returns {Function} The app instance for chaining
 */
app.use(fn);

Usage Examples:

// Basic middleware
app.use(function(req, res, next) {
  console.log("Request:", req.method, req.url);
  next();
});

// Path-mounted middleware  
app.use("/api", function(req, res, next) {
  // Only handles requests starting with /api
  // req.url is modified: "/api/users" becomes "/users"
  // req.originalUrl preserves original: "/api/users"
  next();
});

// Mounting other Connect apps
const adminApp = connect();
adminApp.use(function(req, res, next) {
  res.end("Admin section");
});
app.use("/admin", adminApp);

// Mounting HTTP servers
const http = require("http");
const staticServer = http.createServer(/* static handler */);
app.use("/static", staticServer);

// Error-handling middleware (4 parameters)
app.use(function(err, req, res, next) {
  console.error(err.stack);
  res.statusCode = 500;
  res.end("Internal Server Error");
});

// Chaining
app.use(middleware1).use("/admin", middleware2);

Request Handling

Processes HTTP requests through the middleware stack. Connect automatically sets req.originalUrl to preserve the original URL and manipulates req.url for mounted middleware.

/**
 * Handle HTTP requests through middleware stack
 * @param {IncomingMessage} req - Node.js HTTP request object  
 * @param {ServerResponse} res - Node.js HTTP response object
 * @param {Function} [out] - Optional callback for unhandled requests or errors
 */
app.handle(req, res, [out]);

/**
 * Alias for app.handle - app itself is callable
 * @param {IncomingMessage} req - Node.js HTTP request object
 * @param {ServerResponse} res - Node.js HTTP response object  
 * @param {Function} [next] - Optional callback for unhandled requests
 */
app(req, res, [next]);

URL Manipulation Behavior:

When middleware is mounted on a route, Connect modifies the request URL:

  • req.originalUrl is set to the full original URL (only set once)
  • req.url is modified to remove the mounted path
  • Route matching is case-insensitive
  • Routes must end at path separator (/) or dot (.) boundaries
app.use("/api/v1", function(req, res, next) {
  // Request to "/api/v1/users/123"
  console.log(req.originalUrl); // "/api/v1/users/123"
  console.log(req.url);         // "/users/123"
  next();
});

// Route boundary examples:
app.use("/foo", handler); // Matches: /foo, /foo/, /foo/bar, /foo.bar
                         // Does NOT match: /foobar

Server Creation

Creates and starts an HTTP server using the Connect app as the request handler.

/**
 * Start HTTP server listening for requests
 * @param {...*} args - Same arguments as Node.js http.Server.listen()
 * @returns {Server} Node.js HTTP server instance
 */
app.listen(...args);

Usage Examples:

// Listen on port 3000
const server = app.listen(3000);

// Listen with hostname and callback
app.listen(3000, "localhost", function() {
  console.log("Server running on http://localhost:3000");
});

// Using http.createServer directly
const http = require("http");
const server = http.createServer(app);
server.listen(3000);

Event Handling

Connect apps inherit from EventEmitter and can emit/listen for events.

/**
 * Add event listener (inherited from EventEmitter)
 * @param {string} event - Event name
 * @param {Function} listener - Event listener function
 * @returns {Function} The app instance
 */
app.on(event, listener);

/**
 * Emit event (inherited from EventEmitter)  
 * @param {string} event - Event name
 * @param {...*} args - Arguments to pass to listeners
 * @returns {boolean} Whether event had listeners
 */
app.emit(event, ...args);

Usage Examples:

// Listen for custom events
app.on("user:login", function(user) {
  console.log("User logged in:", user.name);
});

// Emit events from middleware
app.use(function(req, res, next) {
  if (req.url === "/login") {
    app.emit("user:login", { name: "John" });
  }
  next();
});

Types

Middleware Function Signatures

/**
 * Standard middleware function
 * @param {IncomingMessage} req - HTTP request object
 * @param {ServerResponse} res - HTTP response object  
 * @param {Function} next - Call to continue to next middleware or pass error
 */
function middleware(req, res, next);

/**
 * Error-handling middleware function (4 parameters)
 * @param {Error} err - Error object from previous middleware
 * @param {IncomingMessage} req - HTTP request object
 * @param {ServerResponse} res - HTTP response object
 * @param {Function} next - Call to continue to next error handler or pass error
 */
function errorMiddleware(err, req, res, next);

App Properties and Request Objects

/**
 * Connect app properties
 */
interface ConnectApp {
  /** Middleware stack array (internal, but publicly accessible) */
  stack: Array<{route: string, handle: Function}>;
  /** Mount route path (defaults to '/') */
  route: string;
  /** Alias for app.handle */
  (req: IncomingMessage, res: ServerResponse, next?: Function): void;
  /** Add middleware to the stack */
  use(fn: Function): ConnectApp;
  use(route: string, fn: Function): ConnectApp;
  /** Handle requests through middleware stack */
  handle(req: IncomingMessage, res: ServerResponse, out?: Function): void;
  /** Start HTTP server */
  listen(...args: any[]): http.Server;
  /** Event emitter methods (inherited) */
  on(event: string, listener: Function): ConnectApp;
  emit(event: string, ...args: any[]): boolean;
}

/**
 * Enhanced request object (Node.js IncomingMessage with Connect additions)
 */
interface ConnectRequest extends IncomingMessage {
  /** Original URL before any modifications (set by Connect) */
  originalUrl?: string;
}

Error Handling

Connect uses a special error-handling pattern:

  • Error Propagation: Call next(error) to pass errors to error handlers
  • Error Middleware: Functions with 4 parameters (err, req, res, next) handle errors
  • Error Flow: Errors skip regular middleware and go to next error handler
  • Default Handler: Uses finalhandler module if no error middleware handles the error
// Middleware that might error
app.use(function(req, res, next) {
  if (req.url === "/error") {
    return next(new Error("Something went wrong"));
  }
  next();
});

// Error handler
app.use(function(err, req, res, next) {
  res.statusCode = 500;
  res.end("Error: " + err.message);
});

Complex Error Handling Examples:

// Multiple error handlers for different error types
app.use(function(req, res, next) {
  if (req.url === "/auth-error") {
    const err = new Error("Unauthorized");
    err.status = 401;
    return next(err);
  }
  next();
});

// Handle auth errors specifically
app.use(function(err, req, res, next) {
  if (err.status === 401) {
    res.statusCode = 401;
    res.setHeader("Content-Type", "application/json");
    res.end(JSON.stringify({ error: "Unauthorized access" }));
    return;
  }
  next(err); // Pass to next error handler
});

// General error handler (should be last)
app.use(function(err, req, res, next) {
  console.error(err.stack);
  res.statusCode = err.status || 500;
  res.end("Internal Server Error");
});

Advanced Usage

Sub-applications

Connect apps can be mounted as middleware in other Connect apps, creating modular application structures.

const main = connect();
const admin = connect();
const api = connect();

// Build admin sub-app
admin.use(function(req, res, next) {
  // Admin authentication middleware
  if (!req.headers.authorization) {
    res.statusCode = 401;
    res.end("Unauthorized");
    return;
  }
  next();
});

admin.use(function(req, res, next) {
  res.end("Admin Dashboard: " + req.url);
});

// Build API sub-app  
api.use(function(req, res, next) {
  res.setHeader("Content-Type", "application/json");
  next();
});

api.use("/users", function(req, res, next) {
  res.end(JSON.stringify({ users: [] }));
});

// Mount sub-apps in main app
main.use("/admin", admin);  // All /admin/* requests go to admin app
main.use("/api", api);      // All /api/* requests go to api app

// Main app middleware
main.use(function(req, res, next) {
  res.end("Main app: " + req.url);
});

HTTP Server Integration

Connect apps work with any Node.js HTTP server and can be combined with other server technologies.

const https = require("https");
const http2 = require("http2");
const fs = require("fs");

// HTTPS server
const httpsOptions = {
  key: fs.readFileSync("private-key.pem"),
  cert: fs.readFileSync("certificate.pem")
};
https.createServer(httpsOptions, app).listen(443);

// HTTP/2 server  
const http2Server = http2.createSecureServer(httpsOptions, app);
http2Server.listen(8443);

// Multiple servers with same app
const httpServer = http.createServer(app);
const httpsServer = https.createServer(httpsOptions, app);

httpServer.listen(80);
httpsServer.listen(443);

Complex Routing Patterns

// Conditional routing based on request properties
app.use(function(req, res, next) {
  if (req.method === "POST" && req.url.startsWith("/api/")) {
    // Handle API POST requests differently
    res.setHeader("Content-Type", "application/json");
  }
  next();
});

// Route parameter extraction (manual)
app.use("/users", function(req, res, next) {
  // req.url is "/123" for request to "/users/123"
  const userId = req.url.slice(1); // Remove leading slash
  if (userId && /^\d+$/.test(userId)) {
    req.userId = userId;
  }
  next();
});

// Multiple route patterns
app.use("/api/v1", apiV1Handler);
app.use("/api/v2", apiV2Handler);
app.use("/api", function(req, res, next) {
  // Catch-all for other API routes
  res.statusCode = 404;
  res.end("API version not found");
});

Implementation Details

Middleware Execution Flow

Connect processes requests through several internal steps:

  1. URL Preservation: req.originalUrl is set to preserve the original request URL
  2. Stack Iteration: Middleware functions are called sequentially from the stack array
  3. Route Matching: Each middleware's route is compared against the request URL path
  4. URL Modification: For mounted middleware, req.url is temporarily modified
  5. Error Routing: Errors skip regular middleware and flow to error handlers only
  6. Final Handling: Unhandled requests/errors are passed to finalhandler

Route Matching Rules

// Route matching follows specific rules:
app.use("/foo", handler);

// Matches these URLs:
// "/foo"         - exact match
// "/foo/"        - with trailing slash  
// "/foo/bar"     - with additional path
// "/foo.html"    - with dot separator

// Does NOT match:
// "/foobar"      - no separator after route
// "/FOO"         - case-insensitive (actually matches in Connect)

Note: Route matching is case-insensitive in Connect.

Environment Integration

Connect respects the NODE_ENV environment variable:

  • Development: Error stack traces are logged to console
  • Test: Error logging is suppressed
  • Production: Minimal error information is exposed

docs

index.md

tile.json