nitro icon indicating copy to clipboard operation
nitro copied to clipboard

How to add cors settings (origin)?

Open MickL opened this issue 1 year ago • 5 comments

Describe the feature

At the moment I have the following rule in my nitro.config.ts:

routeRules: {
    '/**': {
      cors: true,
    },
  },

I want to only accept cors for my website-domain (prod and dev). How can I make options like cors origin in Nitro? Unfortunately the whole cors topic is not covered in the docs.

E.g. my domain is www.example.com and my api is at api.example.com -> Without cors: true this results in errors.

Reference

  • Express CORS options: https://github.com/expressjs/cors#configuration-options
  • Fastify CORS options: https://github.com/fastify/fastify-cors?tab=readme-ov-file#options

Additional information

  • [ ] Would you be willing to help implement this feature?

MickL avatar Nov 25 '24 15:11 MickL

This should help, https://github.com/nitrojs/nitro/issues/539

Official docs for routeRules shows how to handle special routes in dev or prod individually: https://nitro.build/config#routerules

You could use devProxy, if I understand correctly what you want to achieve on localhost:

{
  devProxy: {
    '/proxy/test': 'http://localhost:3001',
    '/proxy/example': { target: 'https://example.com', changeOrigin: true }
  }

Shooteger avatar Nov 25 '24 17:11 Shooteger

I have no problem making a differntiation between dev and prod. I want to set cors origin to a specific URL instead of accepting all origins.

For example in Express cors has an options attribute where you can set origin and other things. You could even use an async function for this:

var corsOptions = {
  origin: function (origin, callback) {
     db.loadOrigins(function (error, origins) {
      callback(error, origins)
    })
  }
}

app.use(cors(corsOptions));

What I am looking for is something like this:

routeRules: {
    '/**': {
      cors: {
           origin: 'www.example.com'
      },
    },
  },

MickL avatar Nov 25 '24 19:11 MickL

I think we can have a Fastify-like configuration for CORS. Currently, I am setting up the CORS configuration through a middleware, which, in my opinion, isn't the best approach. I propose to have something like this:

interface NitroCorsOptions {
  origin?: string | string[];
  credentials?: boolean;
  exposedHeaders?: string | string[];
  allowedHeaders?: string | string[];
  methods?: string | string[];
  maxAge?: number;
  preflightContinue?: boolean;
  optionsSuccessStatus?: number;
  preflight?: boolean;
  strictPreflight?: boolean;
}

If @pi0 agrees on this. I can help implement.

ssahillppatell avatar Jun 17 '25 18:06 ssahillppatell

I was just wondering if this actually needs to be done within H3?

MickL avatar Jun 23 '25 11:06 MickL

Just to note a workaround for now: Cors cant be configured by nitro.config.ts (what this issue is about), but it can be configured by use of a middleware, e.g. here is what I came up with that works with dev and prod:

1.cors.ts

import {
  defineEventHandler,
  getHeader,
  isMethod,
  setHeader,
  setResponseStatus,
} from 'h3';
import { useRuntimeConfig } from 'nitropack/runtime';

export default defineEventHandler((event) => {
  const { frontendUrl } = useRuntimeConfig();

  const origin = getHeader(event, 'origin');

  if (origin === frontendUrl) {
    setHeader(event, 'Access-Control-Allow-Origin', origin);
    setHeader(event, 'Vary', 'Origin');
    setHeader(
      event,
      'Access-Control-Allow-Methods',
      'GET, POST, PUT, PATCH, DELETE, OPTIONS',
    );
    setHeader(event, 'Access-Control-Allow-Credentials', 'true');
    setHeader(event, 'Access-Control-Allow-Headers', 'Content-Type, Authorization');
  }

  // Short-circuit preflight requests
  if (isMethod(event, 'OPTIONS')) {
    setResponseStatus(event, 204);
    return {};
  }
});

MickL avatar Jul 19 '25 10:07 MickL