# Node-Style vs Web Standard Middleware Signatures in SXO

> Understand Node-style and Web Standard middleware signatures in SXO. Learn how SXO supports both Nodejs and serverless environments for flexible application development.

- Repository: [Víctor García/sxo](https://github.com/gc-victor/sxo)
- Tags: deep-dive
- Published: 2026-03-02

---

**SXO supports two distinct middleware APIs—Node-style `(req, res, next)` for local CLI servers and Web Standard `(request, env) => Response` for portable edge runtimes—allowing the same framework to run in both Node.js and serverless environments.**

The SXO framework (gc-victor/sxo) bridges traditional Node.js HTTP servers and modern Web Standard runtimes by providing dual middleware interfaces. Understanding the difference between **Node-style and Web Standard middleware signatures** ensures your middleware runs correctly whether you're using `sxo dev` locally or deploying to Cloudflare Workers.

## Node-Style Middleware Signature

### Function Signature and Return Values

**Node-style** middleware uses the signature `(req, res, next) => void` or `(req, res) => boolean`. According to the README (lines 29-33), this API accepts the raw Node.js `http.IncomingMessage` and `http.ServerResponse` objects. The function may call `next()` to continue the chain, return `true` or `false` to indicate request handling status, or terminate the response directly via `res.end()`.

### When to Use Node-Style Middleware

This signature is exclusive to the **CLI server** context used by `sxo dev` and `sxo start` commands. It executes within the local Node.js process that handles raw HTTP primitives, making it ideal for quick local development, custom logging, or features requiring direct socket access such as TCP upgrades.

### Implementation Example

The loader in [`src/js/server/middleware.js`](https://github.com/gc-victor/sxo/blob/main/src/js/server/middleware.js) discovers user-defined middleware and invokes each function with the Node request-response pair:

```javascript
// src/middleware.js – Node-style example
export default function (req, res, next) {
  // Simple health-check endpoint
  if (req.url === "/ping") {
    res.end("pong");        // handle the request
    return;                 // stop further processing
  }
  next();                   // continue to the next middleware / route
}

```

## Web Standard Middleware Signature

### Function Signature and Return Values

**Web Standard** middleware implements the Fetch API signature `(request: Request, env?: object) => Response | void | Promise<Response | void>`. As documented in the README (lines 46-50), this function receives a standard `Request` object and an optional `env` object containing platform bindings or secrets. Returning a `Response` short-circuits the middleware chain immediately, while returning `void` allows the request to continue.

### When to Use Web Standard Middleware

This signature is required for **platform adapters** such as Cloudflare Workers, Bun, Deno, and SXO's internal production adapters. The runtime in [`src/js/runtime/middleware.js`](https://github.com/gc-victor/sxo/blob/main/src/js/runtime/middleware.js) re-exports the `executeMiddleware` executor from [`src/js/runtime/handler.js`](https://github.com/gc-victor/sxo/blob/main/src/js/runtime/handler.js), which iterates over the middleware array expecting Web Standard objects. This approach ensures your code remains portable across all serverless runtimes that implement the Fetch API standard.

### Implementation Example

The runtime executor awaits each middleware call, handling promises and response short-circuiting automatically:

```javascript
// src/middleware.js – Web Standard example
export default async function (request, env) {
  const url = new URL(request.url);

  // Short-circuit the request with a Response
  if (url.pathname === "/ping") {
    return new Response("pong", { status: 200 });
  }

  // Returning nothing lets the request continue to the next middleware / route
}

```

## Core Implementation Files in SXO

The framework maintains separate loaders and executors to handle both signatures:

- **[`src/js/server/middleware.js`](https://github.com/gc-victor/sxo/blob/main/src/js/server/middleware.js)** — Contains the loader that discovers user-defined middleware. The comment block at lines 5-7 explicitly defines the expected "Web Standard middleware functions" signature, while the implementation handles the discovery and loading logic for both development and production contexts.

- **[`src/js/runtime/middleware.js`](https://github.com/gc-victor/sxo/blob/main/src/js/runtime/middleware.js)** — Re-exports the `executeMiddleware` executor (lines 11-12) used by platform adapters. This module processes the Web Standard middleware chain for Cloudflare Workers and other edge runtimes.

- **[`src/js/server/prod/node.js`](https://github.com/gc-victor/sxo/blob/main/src/js/server/prod/node.js)** — Implements the production Node.js adapter. Lines 69-76 demonstrate how the framework calls `loadUserDefinedMiddlewares()` to load user middleware, then converts the Node `req` object to a Web Standard `Request` via `toWebRequest(req, PORT)` before execution. This conversion allows the same middleware array to function across both Node and Web Standard environments.

## Summary

- **Node-style middleware** uses `(req, res, next)` and runs only in the local CLI server (`sxo dev`, `sxo start`) with direct access to Node.js HTTP primitives.
- **Web Standard middleware** uses `(request, env) => Response` and runs in all platform adapters including Cloudflare Workers, Bun, and Deno, utilizing portable Fetch API objects.
- The production Node adapter in [`src/js/server/prod/node.js`](https://github.com/gc-victor/sxo/blob/main/src/js/server/prod/node.js) converts incoming requests to Web Standard format before executing middleware, ensuring cross-platform compatibility.
- Both middleware types are registered in [`src/js/server/middleware.js`](https://github.com/gc-victor/sxo/blob/main/src/js/server/middleware.js), but executed by different runtimes depending on the deployment target.

## Frequently Asked Questions

### Can I use Node-style middleware in Cloudflare Workers?

No. Cloudflare Workers and other edge runtimes do not expose Node.js `http` modules. These environments exclusively use the Web Standard signature processed by [`src/js/runtime/middleware.js`](https://github.com/gc-victor/sxo/blob/main/src/js/runtime/middleware.js), which expects `Request` and `Response` objects rather than `http.IncomingMessage` and `http.ServerResponse`.

### Does SXO automatically convert between Node and Web Standard formats?

Yes. According to [`src/js/server/prod/node.js`](https://github.com/gc-victor/sxo/blob/main/src/js/server/prod/node.js), the production Node adapter automatically converts incoming Node requests to Web Standard `Request` objects using the internal `toWebRequest(req, PORT)` utility. This conversion happens before the middleware chain executes, allowing Web Standard middleware to run unchanged in Node.js production environments.

### Which signature should I use for new projects?

Use the **Web Standard** signature `(request, env)` for maximum portability. This ensures your middleware runs on Cloudflare Workers, Bun, Deno, and SXO's production adapters without modification. Only use Node-style middleware when you specifically require direct access to raw Node.js HTTP primitives for local development tasks.

### What happens if middleware returns a Response in Web Standard mode?

Returning a `Response` object immediately short-circuits the middleware chain and sends that response to the client. If middleware returns `void` or `undefined`, the runtime executor continues to the next middleware function or route handler. This behavior is implemented in the `executeMiddleware` function exported from [`src/js/runtime/handler.js`](https://github.com/gc-victor/sxo/blob/main/src/js/runtime/handler.js) and re-exported via [`src/js/runtime/middleware.js`](https://github.com/gc-victor/sxo/blob/main/src/js/runtime/middleware.js).