I've been playing around trying to avoid a CORS error with my next app which is deployed on vercel. The only way I managed to do this was by manually setting the headers on each api request... eg:
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
res.setHeader('Access-Control-Allow-Credentials', 'true')
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Methods', 'GET')
res.setHeader(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept, Authorization'
)
// Handle pre-flight requests
if (req.method === 'OPTIONS') {
res.status(200).end()
return
}
let houses: House[] = []
try {
await client.connect()
console.log('Connected to MongoDB')
const db = client.db('vroom')
const housesCollection = db.collection('houses')
houses = (await housesCollection.find().toArray()).map((house) => ({
house: house.house,
price: house.price,
timestamp: house.timestamp,
developer: house.developer,
}))
console.log('Retrieved houses:', houses)
} catch (error) {
console.error(`Error connecting to MongoDB: ${error}`)
} finally {
await client.close()
}
res.json({ houses })
}
Is it possible to achieve the same result either via the middleware.ts file, or through some sort of wrapper code?
I hope this makes sense but please ask for any clarification if not!
Thanks
I tried the above but have to enter some text here :)
I managed to do the next best thing and create a wrapper for my apis facing that cors error:
here's a utils/middlware.ts file:
import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next'
import Cors from 'cors'
const corsMiddleware = Cors({
methods: ['GET', 'OPTIONS', 'HEAD'],
})
const runMiddleware = (
req: NextApiRequest,
res: NextApiResponse,
fn: Function
) => {
return new Promise((resolve, reject) => {
fn(req, res, (result: any) => {
if (result instanceof Error) {
return reject(result)
}
return resolve(result)
})
})
}
export const withCors =
(handler: NextApiHandler) =>
async (req: NextApiRequest, res: NextApiResponse) => {
await runMiddleware(req, res, corsMiddleware)
if (req.method === 'OPTIONS') {
res.status(200).end()
return
}
return handler(req, res)
}
Which can then be used like so:
import { NextApiRequest, NextApiResponse } from 'next'
import { connectToDB, paginateCollection, withCors } from '@/utils'
export type House = {
house: string
price: string
timestamp: string
developer: string
}
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const page = parseInt(req.query.page as string) || 1
const perPage = 10
let houses: House[] = []
let totalPages = 1
try {
const db = await connectToDB()
const housesCollection = db.collection('foo')
const { items, totalPages: pages } = await paginateCollection(
housesCollection,
page,
perPage
)
totalPages = pages
houses = items.map((house) => ({
house: house.house,
price: house.price,
timestamp: house.timestamp,
developer: house.developer,
}))
} catch (error) {
console.error(`Error connecting to MongoDB: ${error}`)
}
res.json({ houses, totalPages })
}
export default withCors(handler)
Hope that helps someone else!