Restify CORS Middleware 2

raw JSON →
2.2.1 verified Thu Apr 23 auth: no javascript

restify-cors-middleware2 is a specialized CORS (Cross-Origin Resource Sharing) middleware designed for use with Restify servers, providing full compliance with the W3C CORS specification. The package, currently at version 2.2.1, offers robust features for handling preflight requests and actual requests, with advanced capabilities for defining allowed origins using strings, wildcards, and regular expressions. A key differentiator is its enhanced security posture, where it dynamically sets the `Access-Control-Allow-Origin` header to the matching origin, rather than a broad wildcard, preventing information leakage about other supported domains. It also clearly documents potential security implications of using `origins: ['*']`. This middleware is a successor to an earlier `restify-cors-middleware` package, indicating updates and potential breaking changes from its predecessor. It includes TypeScript declaration files, facilitating its use in TypeScript projects. The release cadence is moderate, with stable versions released as needed for feature enhancements and bug fixes.

error Access to XMLHttpRequest at 'http://api.example.com/data' from origin 'http://client.example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
cause The client's origin is not configured in `origins` option, or the server is not correctly applying the middleware.
fix
Ensure the client's origin (e.g., http://client.example.com) is explicitly listed in the origins array of the corsMiddleware options, or use a wildcard/regex that matches it if appropriate for your security model.
error Failed to load resource: Preflight response for URL 'http://api.example.com/data' is invalid. HTTP status code 405.
cause The OPTIONS request (preflight) is not being handled correctly by the Restify server, often due to a lack of an OPTIONS route or improper middleware application.
fix
Verify that server.pre(cors.preflight) is called before any other routes or middleware that might prematurely handle or block OPTIONS requests. Ensure the preflightMaxAge is set appropriately.
error Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
cause The preflight (OPTIONS) request is not returning a successful HTTP status code (e.g., 200, 204), or is being rejected for other reasons.
fix
Check server logs for errors during the OPTIONS request. Ensure your Restify server is correctly configured to handle OPTIONS requests via cors.preflight middleware and that no other middleware is interfering or returning an error status for preflight requests.
breaking This package, `restify-cors-middleware2`, is a successor or fork of an older `restify-cors-middleware` package. There are likely breaking changes in API and behavior compared to the original, necessitating careful migration if upgrading from the older version.
fix Review the README and unit tests for `restify-cors-middleware2` to understand the current API and adapt your code accordingly. Do not assume direct compatibility with `restify-cors-middleware`.
gotcha Using `origins: ['*']` allows all origins, but this comes with significant security implications. Additionally, enabling `allowCredentialsAllOrigins` with `*` can be a security risk.
fix Always specify explicit origins using strings, wildcards, or regular expressions whenever possible. Only use `['*']` in specific, controlled environments (e.g., public APIs without sensitive data) and understand the security trade-offs. Avoid `allowCredentialsAllOrigins` with `*` unless absolutely necessary and secure.
gotcha CORS headers are not sent for requests that do not include an `Origin` header, as per the W3C spec. This can be a source of confusion for developers expecting CORS headers on all requests.
fix Ensure that client-side requests are properly setting the `Origin` header. Tools like `curl` typically don't set it by default unless specified. Browser-initiated requests (e.g., `fetch`, `XMLHttpRequest`) generally handle this automatically for cross-origin requests.
gotcha Caching layers (reverse proxies, CDNs) must be configured to vary their cache based on the `Origin` header. Failing to do so can lead to incorrect CORS headers being served to clients, potentially exposing data or causing unexpected behavior.
fix Configure your reverse proxy (e.g., Nginx, Varnish) or CDN to include `Vary: Origin` in cached responses. This ensures that different `Origin` headers result in separate cache entries, preventing cross-origin response leakage.
gotcha The TypeScript declaration file is noted as 'basic' and 'not validated' by the package maintainers, who don't use TypeScript locally. This means the types might not be fully accurate or comprehensive.
fix Be aware that TypeScript type definitions may have limitations. Consider contributing to the type definitions if you encounter inaccuracies or missing types. You may need to use `// @ts-ignore` in some cases or declare custom module augmentations.
npm install restify-cors-middleware2
yarn add restify-cors-middleware2
pnpm add restify-cors-middleware2

This quickstart demonstrates how to set up `restify-cors-middleware2` with a basic Restify server, configuring preflight caching, specific allowed origins (including a regex for localhost), and custom headers.

const restify = require('restify');
const corsMiddleware = require('restify-cors-middleware2');

const server = restify.createServer({
  name: 'my-cors-server',
});

const cors = corsMiddleware({
  preflightMaxAge: 5, // Cache preflight response for 5 seconds
  origins: ['http://localhost:3000', /localhost:\d+$/], // Allow specific origins, including regex
  allowHeaders: ['API-Token', 'Authorization', 'Content-Type'], // Custom headers to allow
  exposeHeaders: ['API-Token-Expiry', 'X-Custom-Header'] // Headers to expose to the client
});

server.pre(cors.preflight);
server.use(cors.actual);

// Example route
server.get('/hello', (req, res, next) => {
  res.send({ message: 'Hello from Restify!' });
  return next();
});

server.listen(8080, () => {
  console.log('%s listening at %s', server.name, server.url);
});