W
Wasp3w ago
YuehLin

CORS issue

I set up an api endpoint and has an middleware wrap around it to get the cors middleware. I deployed the to the fly.io. in main.wasp
apiNamespace appsNamespace {
middlewareConfigFn: import { appsNamespaceMiddlewareFn } from "@src/test/apis",
path: "/apps"
}
apiNamespace appsNamespace {
middlewareConfigFn: import { appsNamespaceMiddlewareFn } from "@src/test/apis",
path: "/apps"
}
export const appsNamespaceMiddlewareFn: MiddlewareConfigFn = (middlewareConfig) => {
const customMiddleware: express.RequestHandler = (_req, _res, next) => {
console.log(middlewareConfig); // debug purpose
next()
}

middlewareConfig.set('custom.middleware', customMiddleware)

return middlewareConfig;
};
export const appsNamespaceMiddlewareFn: MiddlewareConfigFn = (middlewareConfig) => {
const customMiddleware: express.RequestHandler = (_req, _res, next) => {
console.log(middlewareConfig); // debug purpose
next()
}

middlewareConfig.set('custom.middleware', customMiddleware)

return middlewareConfig;
};
When I tried to hit the endpoint from lovable or https://cors-test.codehappy.dev/, both saying that the endpoint has cors issue. The current workaround I have is manually set up the response header in the fly-server.toml.
[http_service.http_options.response.headers]
Access-Control-Allow-Origin = "*"
[http_service.http_options.response.headers]
Access-Control-Allow-Origin = "*"
I'm curious about if I did anything wrong to enable cors? or adding that in the response (which seems not that safe) is the only way to go?
9 Replies
kapa.ai
kapa.ai3w ago
Hi @YuehLin. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Short answer: you’re on the right track with apiNamespace, but there are a couple of common gotchas with CORS on Wasp APIs. Key points to check: 1) Ensure the default CORS middleware is actually applied to your APIs
- APIs don’t use the same default middleware stack as operations. To enable CORS for client calls, you need an apiNamespace with a middlewareConfigFn that returns the default config (or explicitly sets cors). Returning the config (even unchanged) attaches the default stack, which includes cors with allowed origins set from config. [Making sure CORS works; Default middleware] Example:
// main.wasp
apiNamespace appsNamespace {
middlewareConfigFn: import { appsNamespaceMiddlewareFn } from "@src/test/apis",
path: "/apps"
}
// main.wasp
apiNamespace appsNamespace {
middlewareConfigFn: import { appsNamespaceMiddlewareFn } from "@src/test/apis",
path: "/apps"
}
// @src/test/apis.ts
import { type MiddlewareConfigFn } from 'wasp/server'
export const appsNamespaceMiddlewareFn: MiddlewareConfigFn = (config) => {
// Important: return the config so default CORS gets installed on this path
return config
}
// @src/test/apis.ts
import { type MiddlewareConfigFn } from 'wasp/server'
export const appsNamespaceMiddlewareFn: MiddlewareConfigFn = (config) => {
// Important: return the config so default CORS gets installed on this path
return config
}
2) If you need to customize allowed origins, set them via global middleware (or on the namespace)
- By default, CORS uses config.allowedCORSOrigins (which includes your frontend URL). If you’re calling your API from other origins like lovable or codehappy’s tester, you need to add those origins. Do this in global middleware or replace the cors entry in your namespace. [Customize global; Default middleware] Global example:
// main.wasp
app myApp {
server: {
middlewareConfigFn: import { serverMiddlewareFn } from "@src/serverSetup"
}
}
// main.wasp
app myApp {
server: {
middlewareConfigFn: import { serverMiddlewareFn } from "@src/serverSetup"
}
}
// @src/serverSetup.ts
import cors from 'cors'
import { config, type MiddlewareConfigFn } from 'wasp/server'

export const serverMiddlewareFn: MiddlewareConfigFn = (mc) => {
// Add extra allowed origins
mc.set('cors', cors({ origin: [config.frontendUrl, '<https://lovable.app',> '<https://cors-test.codehappy.dev']> }))
return mc
}
// @src/serverSetup.ts
import cors from 'cors'
import { config, type MiddlewareConfigFn } from 'wasp/server'

export const serverMiddlewareFn: MiddlewareConfigFn = (mc) => {
// Add extra allowed origins
mc.set('cors', cors({ origin: [config.frontendUrl, '<https://lovable.app',> '<https://cors-test.codehappy.dev']> }))
return mc
}
Per-path example (if you only want this under /apps):
import cors from 'cors'
import { config, type MiddlewareConfigFn } from 'wasp/server'

export const appsNamespaceMiddlewareFn: MiddlewareConfigFn = (mc) => {
mc.set('cors', cors({ origin: [config.frontendUrl, '<https://lovable.app',> '<https://cors-test.codehappy.dev']> }))
return mc
}
import cors from 'cors'
import { config, type MiddlewareConfigFn } from 'wasp/server'

export const appsNamespaceMiddlewareFn: MiddlewareConfigFn = (mc) => {
mc.set('cors', cors({ origin: [config.frontendUrl, '<https://lovable.app',> '<https://cors-test.codehappy.dev']> }))
return mc
}
3) Make sure preflight (OPTIONS) is covered
- Using apiNamespace ensures middleware is attached at the router for the path, so CORS applies to both OPTIONS and your actual method (GET/POST). Setting middleware only on a single api can miss OPTIONS, which is a common source of CORS failures. [Per-path middleware; Improve CORS + API] 4) Avoid overriding CORS via fly.toml unless necessary
- Manually forcing Access-Control-Allow-Origin="" at the edge can mask real configuration and security issues. Prefer configuring CORS in Wasp middleware so it’s limited to the exact origins you need. The docs explicitly show how to tune cors via middleware. [Customize global] If you still see CORS errors after the above: - Confirm the exact Origin header of the caller and that it matches one of your allowed origins (including scheme and host). - Check that your namespace path matches the API routes (e.g., path: "/apps" and APIs under /apps/). - Ensure your middleware function returns the config and doesn’t inadvertently remove or replace cors with a stricter version. - If you’re adding auth headers or sending multipart/form-data, that triggers preflight—so OPTIONS must succeed under the namespace. [Api.post CORS issue; Making sure CORS works] References: [Making sure CORS works; Default middleware; Customize global; Per-path middleware; Improve CORS + API] ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @YuehLin, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
miho
miho2w ago
@YuehLin did the bot's answer help you out? Did you put the multiple origins you need in the CORS config as suggested?
YuehLin
YuehLinOP2w ago
If I follow the suggestion doing this
mc.set('cors', cors({ origin: [config.frontendUrl, 'https://lovable.app', 'https://cors-test.codehappy.dev'] }))
return mc
mc.set('cors', cors({ origin: [config.frontendUrl, 'https://lovable.app', 'https://cors-test.codehappy.dev'] }))
return mc
do I need to put my FE url that replace config.frontendUrl?
miho
miho2w ago
config.frontendUrl is your FE url that you put in the env variables 🙂
YuehLin
YuehLinOP2w ago
going to say that I should probably replace it using env.WASP_WEB_CLIENT_URL
miho
miho2w ago
it's the same value, feel free to use any of them, but config is how we use it internally 😄
YuehLin
YuehLinOP2w ago
I modified my middleware function to
export const appsNamespaceMiddlewareFn: MiddlewareConfigFn = (middlewareConfig) => {
middlewareConfig.set('cors', cors({
origin: [
config.frontendUrl,
'https://lovable.app',
'https://cors-test.codehappy.dev'
]
}))

return middlewareConfig;
};
export const appsNamespaceMiddlewareFn: MiddlewareConfigFn = (middlewareConfig) => {
middlewareConfig.set('cors', cors({
origin: [
config.frontendUrl,
'https://lovable.app',
'https://cors-test.codehappy.dev'
]
}))

return middlewareConfig;
};
and remove
[http_service.http_options.response.headers]
Access-Control-Allow-Origin = "*"
[http_service.http_options.response.headers]
Access-Control-Allow-Origin = "*"
from fly-server.toml Now I run into the CORS issue again 😂
miho
miho2w ago
Could you maybe zip your project and share it with me in the DM so I can run some tests?
YuehLin
YuehLinOP2w ago
sure

Did you find this page helpful?