同步精简
This commit is contained in:
parent
dae1b2704f
commit
c29ee4d0c3
|
|
@ -7,6 +7,15 @@ import {
|
||||||
getMedusaProductsPaginated,
|
getMedusaProductsPaginated,
|
||||||
getProductCollection,
|
getProductCollection,
|
||||||
} from '@/lib/medusa'
|
} from '@/lib/medusa'
|
||||||
|
import { addCorsHeaders, handleCorsOptions } from '@/lib/cors'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 CORS 预检请求
|
||||||
|
*/
|
||||||
|
export async function OPTIONS(request: Request) {
|
||||||
|
const origin = request.headers.get('origin')
|
||||||
|
return handleCorsOptions(origin)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过 seedId 或 medusaId 查找产品(优先使用 seedId)
|
* 通过 seedId 或 medusaId 查找产品(优先使用 seedId)
|
||||||
|
|
@ -99,11 +108,14 @@ function mergeProductData(existingProduct: any, newData: any, forceUpdate: boole
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 同步 Medusa 商品到 Payload CMS
|
* 同步 Medusa 商品到 Payload CMS
|
||||||
* GET /api/sync-medusa
|
* GET /api/sync-medusa - 同步所有商品
|
||||||
* GET /api/sync-medusa?medusaId=prod_xxx (通过 Medusa ID 同步单个商品)
|
* GET /api/sync-medusa?medusaId=prod_xxx - 同步单个商品
|
||||||
* GET /api/sync-medusa?payloadId=123 (通过 Payload ID 同步单个商品)
|
* GET /api/sync-medusa?medusaId=prod_xxx&collection=preorder-products - 指定目标 collection
|
||||||
|
* GET /api/sync-medusa?forceUpdate=true - 强制更新所有字段
|
||||||
*/
|
*/
|
||||||
export async function GET(request: Request) {
|
export async function GET(request: Request) {
|
||||||
|
const origin = request.headers.get('origin')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 可选的 API Key 验证
|
// 可选的 API Key 验证
|
||||||
const authHeader = request.headers.get('authorization')
|
const authHeader = request.headers.get('authorization')
|
||||||
|
|
@ -113,53 +125,45 @@ export async function GET(request: Request) {
|
||||||
if (payloadApiKey && authHeader) {
|
if (payloadApiKey && authHeader) {
|
||||||
const token = authHeader.replace('Bearer ', '')
|
const token = authHeader.replace('Bearer ', '')
|
||||||
if (token !== payloadApiKey) {
|
if (token !== payloadApiKey) {
|
||||||
return NextResponse.json(
|
const response = NextResponse.json(
|
||||||
{
|
{
|
||||||
success: false,
|
success: false,
|
||||||
error: 'Invalid API key',
|
error: 'Invalid API key',
|
||||||
},
|
},
|
||||||
{ status: 401 },
|
{ status: 401 },
|
||||||
)
|
)
|
||||||
|
return addCorsHeaders(response, origin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { searchParams } = new URL(request.url)
|
const { searchParams } = new URL(request.url)
|
||||||
const medusaId = searchParams.get('medusaId')
|
const medusaId = searchParams.get('medusaId')
|
||||||
const payloadId = searchParams.get('payloadId')
|
|
||||||
const collection = searchParams.get('collection') as 'products' | 'preorder-products' | null
|
const collection = searchParams.get('collection') as 'products' | 'preorder-products' | null
|
||||||
const forceUpdate = searchParams.get('forceUpdate') === 'true'
|
const forceUpdate = searchParams.get('forceUpdate') === 'true'
|
||||||
|
|
||||||
const payload = await getPayload({ config })
|
const payload = await getPayload({ config })
|
||||||
|
|
||||||
// 同步单个商品(通过 Medusa ID)
|
// 同步单个商品
|
||||||
if (medusaId) {
|
if (medusaId) {
|
||||||
const result = await syncSingleProductByMedusaId(payload, medusaId, forceUpdate, collection || undefined)
|
const result = await syncSingleProductByMedusaId(payload, medusaId, forceUpdate, collection || undefined)
|
||||||
return NextResponse.json(result)
|
const response = NextResponse.json(result)
|
||||||
}
|
return addCorsHeaders(response, origin)
|
||||||
|
|
||||||
// 同步单个商品(通过 Payload ID)
|
|
||||||
if (payloadId) {
|
|
||||||
const result = await syncSingleProductByPayloadId(
|
|
||||||
payload,
|
|
||||||
payloadId,
|
|
||||||
collection || '',
|
|
||||||
forceUpdate,
|
|
||||||
)
|
|
||||||
return NextResponse.json(result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 同步所有商品
|
// 同步所有商品
|
||||||
const result = await syncAllProducts(payload, forceUpdate)
|
const result = await syncAllProducts(payload, forceUpdate)
|
||||||
return NextResponse.json(result)
|
const response = NextResponse.json(result)
|
||||||
|
return addCorsHeaders(response, origin)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Sync error:', error)
|
console.error('[Sync API] ❌ 请求处理失败:', error)
|
||||||
return NextResponse.json(
|
const response = NextResponse.json(
|
||||||
{
|
{
|
||||||
success: false,
|
success: false,
|
||||||
error: error instanceof Error ? error.message : 'Unknown error',
|
error: error instanceof Error ? error.message : 'Unknown error',
|
||||||
},
|
},
|
||||||
{ status: 500 },
|
{ status: 500 },
|
||||||
)
|
)
|
||||||
|
return addCorsHeaders(response, origin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -316,73 +320,6 @@ async function syncSingleProductByMedusaId(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过 Payload ID 同步单个商品
|
|
||||||
*/
|
|
||||||
async function syncSingleProductByPayloadId(
|
|
||||||
payload: any,
|
|
||||||
payloadId: string,
|
|
||||||
collection: string,
|
|
||||||
forceUpdate: boolean,
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
// 如果未指定 collection,尝试在两个 collections 中查找
|
|
||||||
let product: any = null
|
|
||||||
let foundCollection: string = collection
|
|
||||||
|
|
||||||
if (collection) {
|
|
||||||
product = await payload.findByID({
|
|
||||||
collection,
|
|
||||||
id: payloadId,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// 尝试 preorder-products
|
|
||||||
try {
|
|
||||||
product = await payload.findByID({
|
|
||||||
collection: 'preorder-products',
|
|
||||||
id: payloadId,
|
|
||||||
})
|
|
||||||
foundCollection = 'preorder-products'
|
|
||||||
} catch {
|
|
||||||
// 最后尝试旧的 products
|
|
||||||
product = await payload.findByID({
|
|
||||||
collection: 'products',
|
|
||||||
id: payloadId,
|
|
||||||
})
|
|
||||||
foundCollection = 'products'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!product) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
action: 'not_found',
|
|
||||||
message: `未找到商品 ID: ${payloadId}`,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果没有 medusaId,无法同步
|
|
||||||
if (!product.medusaId) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
action: 'no_medusa_id',
|
|
||||||
message: `商品 ${product.title} 没有关联的 Medusa ID,无法同步`,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用 medusaId 同步(保持在当前 collection)
|
|
||||||
return await syncSingleProductByMedusaId(payload, product.medusaId, forceUpdate, foundCollection as 'products' | 'preorder-products')
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error syncing product by Payload ID ${payloadId}:`, error)
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
action: 'error',
|
|
||||||
message: `同步商品 ID ${payloadId} 失败`,
|
|
||||||
error: error instanceof Error ? error.message : 'Unknown error',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 同步所有商品
|
* 同步所有商品
|
||||||
*/
|
*/
|
||||||
|
|
@ -555,41 +492,45 @@ async function syncAllProducts(payload: any, forceUpdate: boolean) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST /api/sync-medusa
|
* POST /api/sync-medusa
|
||||||
* 触发手动同步(需要认证)
|
* 手动触发同步(与 GET 参数相同)
|
||||||
|
* Body: { medusaId?, collection?, forceUpdate? }
|
||||||
*/
|
*/
|
||||||
export async function POST(request: Request) {
|
export async function POST(request: Request) {
|
||||||
|
const origin = request.headers.get('origin')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const payload = await getPayload({ config })
|
const payload = await getPayload({ config })
|
||||||
|
|
||||||
// 可以在这里添加认证检查
|
// 可以在这里添加认证检查
|
||||||
// const { user } = await payload.auth({ headers: request.headers })
|
// const { user } = await payload.auth({ headers: request.headers })
|
||||||
// if (!user) {
|
// if (!user) {
|
||||||
// return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
// const response = NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
||||||
|
// return addCorsHeaders(response, origin)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const body = await request.json()
|
const body = await request.json()
|
||||||
const { medusaId, payloadId, collection = '', forceUpdate = true } = body
|
const { medusaId, collection, forceUpdate = true } = body
|
||||||
|
|
||||||
|
// 同步单个商品
|
||||||
if (medusaId) {
|
if (medusaId) {
|
||||||
const result = await syncSingleProductByMedusaId(payload, medusaId, forceUpdate, collection || undefined)
|
const result = await syncSingleProductByMedusaId(payload, medusaId, forceUpdate, collection)
|
||||||
return NextResponse.json(result)
|
const response = NextResponse.json(result)
|
||||||
}
|
return addCorsHeaders(response, origin)
|
||||||
|
|
||||||
if (payloadId) {
|
|
||||||
const result = await syncSingleProductByPayloadId(payload, payloadId, collection, forceUpdate)
|
|
||||||
return NextResponse.json(result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 同步所有商品
|
||||||
const result = await syncAllProducts(payload, forceUpdate)
|
const result = await syncAllProducts(payload, forceUpdate)
|
||||||
return NextResponse.json(result)
|
const response = NextResponse.json(result)
|
||||||
|
return addCorsHeaders(response, origin)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Sync error:', error)
|
console.error('[Sync API] ❌ POST 请求处理失败:', error)
|
||||||
return NextResponse.json(
|
const response = NextResponse.json(
|
||||||
{
|
{
|
||||||
success: false,
|
success: false,
|
||||||
error: error instanceof Error ? error.message : 'Unknown error',
|
error: error instanceof Error ? error.message : 'Unknown error',
|
||||||
},
|
},
|
||||||
{ status: 500 },
|
{ status: 500 },
|
||||||
)
|
)
|
||||||
|
return addCorsHeaders(response, origin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,225 @@
|
||||||
|
import { getPayload } from 'payload'
|
||||||
|
import config from '@payload-config'
|
||||||
|
import { NextResponse } from 'next/server'
|
||||||
|
import {
|
||||||
|
getAllMedusaProducts,
|
||||||
|
transformMedusaProductToPayload,
|
||||||
|
getProductCollection,
|
||||||
|
} from '@/lib/medusa'
|
||||||
|
import { addCorsHeaders, handleCorsOptions } from '@/lib/cors'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 CORS 预检请求
|
||||||
|
*/
|
||||||
|
export async function OPTIONS(request: Request) {
|
||||||
|
const origin = request.headers.get('origin')
|
||||||
|
return handleCorsOptions(origin)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步单个产品并返回完整的产品数据
|
||||||
|
* POST /api/sync-product
|
||||||
|
* Body: { medusaId: string, collection?: 'products' | 'preorder-products', forceUpdate?: boolean }
|
||||||
|
*
|
||||||
|
* 返回: { success: true, product: {...完整的产品数据}, action: 'created' | 'updated' | 'skipped' }
|
||||||
|
*/
|
||||||
|
export async function POST(request: Request) {
|
||||||
|
console.log('[Sync Product API] 📥 收到同步请求')
|
||||||
|
|
||||||
|
const origin = request.headers.get('origin')
|
||||||
|
|
||||||
|
try {
|
||||||
|
const body = await request.json()
|
||||||
|
const { medusaId, collection: preferredCollection, forceUpdate = false } = body
|
||||||
|
|
||||||
|
if (!medusaId) {
|
||||||
|
const response = NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
error: 'medusaId is required',
|
||||||
|
},
|
||||||
|
{ status: 400 },
|
||||||
|
)
|
||||||
|
return addCorsHeaders(response, origin)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[Sync Product API] 🎯 参数:', { medusaId, preferredCollection, forceUpdate })
|
||||||
|
|
||||||
|
const payload = await getPayload({ config })
|
||||||
|
|
||||||
|
// 从 Medusa 获取商品数据
|
||||||
|
const medusaProducts = await getAllMedusaProducts()
|
||||||
|
const medusaProduct = medusaProducts.find((p) => p.id === medusaId)
|
||||||
|
|
||||||
|
if (!medusaProduct) {
|
||||||
|
console.error(`[Sync Product API] ❌ Medusa 中未找到商品: ${medusaId}`)
|
||||||
|
const response = NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
error: `Medusa 中未找到商品 ${medusaId}`,
|
||||||
|
},
|
||||||
|
{ status: 404 },
|
||||||
|
)
|
||||||
|
return addCorsHeaders(response, origin)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[Sync Product API] ✅ 找到 Medusa 产品: ${medusaProduct.title}`)
|
||||||
|
|
||||||
|
// 确定目标 collection
|
||||||
|
const targetCollection = preferredCollection || getProductCollection(medusaProduct)
|
||||||
|
console.log(`[Sync Product API] 🎯 目标 collection: ${targetCollection}`)
|
||||||
|
|
||||||
|
// 转换数据
|
||||||
|
const productData = transformMedusaProductToPayload(medusaProduct)
|
||||||
|
const seedId = productData.seedId
|
||||||
|
|
||||||
|
// 查找现有产品(优先通过 seedId)
|
||||||
|
let existingProduct: any = null
|
||||||
|
let existingCollection: 'products' | 'preorder-products' | null = null
|
||||||
|
|
||||||
|
// 先通过 seedId 查找
|
||||||
|
if (seedId) {
|
||||||
|
for (const coll of ['products', 'preorder-products'] as const) {
|
||||||
|
const result = await payload.find({
|
||||||
|
collection: coll,
|
||||||
|
where: { seedId: { equals: seedId } },
|
||||||
|
limit: 1,
|
||||||
|
})
|
||||||
|
if (result.docs[0]) {
|
||||||
|
existingProduct = result.docs[0]
|
||||||
|
existingCollection = coll
|
||||||
|
console.log(`[Sync Product API] 🔍 通过 seedId 找到产品 (${coll}): ${existingProduct.id}`)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没找到,通过 medusaId 查找
|
||||||
|
if (!existingProduct) {
|
||||||
|
for (const coll of ['products', 'preorder-products'] as const) {
|
||||||
|
const result = await payload.find({
|
||||||
|
collection: coll,
|
||||||
|
where: { medusaId: { equals: medusaId } },
|
||||||
|
limit: 1,
|
||||||
|
})
|
||||||
|
if (result.docs[0]) {
|
||||||
|
existingProduct = result.docs[0]
|
||||||
|
existingCollection = coll
|
||||||
|
console.log(`[Sync Product API] 🔍 通过 medusaId 找到产品 (${coll}): ${existingProduct.id}`)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let action: 'created' | 'updated' | 'updated_partial' | 'moved' | 'skipped' = 'created'
|
||||||
|
let finalProduct: any
|
||||||
|
|
||||||
|
// 如果在错误的 collection 中,需要移动
|
||||||
|
if (existingProduct && existingCollection && existingCollection !== targetCollection) {
|
||||||
|
console.log(`[Sync Product API] 🚚 移动产品: ${existingCollection} -> ${targetCollection}`)
|
||||||
|
|
||||||
|
await payload.delete({
|
||||||
|
collection: existingCollection,
|
||||||
|
id: existingProduct.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
finalProduct = await payload.create({
|
||||||
|
collection: targetCollection,
|
||||||
|
data: productData,
|
||||||
|
})
|
||||||
|
|
||||||
|
action = 'moved'
|
||||||
|
console.log(`[Sync Product API] ✅ 移动成功, 新 ID: ${finalProduct.id}`)
|
||||||
|
}
|
||||||
|
// 如果找到了并且在正确的 collection 中
|
||||||
|
else if (existingProduct) {
|
||||||
|
if (!forceUpdate) {
|
||||||
|
// 只更新空字段
|
||||||
|
const mergedData: any = {
|
||||||
|
lastSyncedAt: productData.lastSyncedAt,
|
||||||
|
medusaId: productData.medusaId,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existingProduct.seedId && productData.seedId) {
|
||||||
|
mergedData.seedId = productData.seedId
|
||||||
|
}
|
||||||
|
if (!existingProduct.title) mergedData.title = productData.title
|
||||||
|
if (!existingProduct.handle) mergedData.handle = productData.handle
|
||||||
|
if (!existingProduct.thumbnail) mergedData.thumbnail = productData.thumbnail
|
||||||
|
if (!existingProduct.status) mergedData.status = productData.status
|
||||||
|
|
||||||
|
// 如果没有需要更新的字段,跳过
|
||||||
|
if (Object.keys(mergedData).length <= 2) {
|
||||||
|
console.log(`[Sync Product API] ⏭️ 跳过: 所有字段都有值`)
|
||||||
|
action = 'skipped'
|
||||||
|
finalProduct = existingProduct
|
||||||
|
} else {
|
||||||
|
console.log(`[Sync Product API] 📝 更新字段: ${Object.keys(mergedData).join(', ')}`)
|
||||||
|
finalProduct = await payload.update({
|
||||||
|
collection: targetCollection,
|
||||||
|
id: existingProduct.id,
|
||||||
|
data: mergedData,
|
||||||
|
})
|
||||||
|
action = 'updated_partial'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 强制更新所有字段
|
||||||
|
console.log(`[Sync Product API] ⚡ 强制更新所有字段`)
|
||||||
|
finalProduct = await payload.update({
|
||||||
|
collection: targetCollection,
|
||||||
|
id: existingProduct.id,
|
||||||
|
data: productData,
|
||||||
|
})
|
||||||
|
action = 'updated'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 不存在,创建新产品
|
||||||
|
else {
|
||||||
|
console.log(`[Sync Product API] ✨ 创建新产品`)
|
||||||
|
finalProduct = await payload.create({
|
||||||
|
collection: targetCollection,
|
||||||
|
data: productData,
|
||||||
|
})
|
||||||
|
action = 'created'
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[Sync Product API] ✅ 同步完成: ${action}`)
|
||||||
|
|
||||||
|
// 返回完整的产品数据
|
||||||
|
const response = NextResponse.json({
|
||||||
|
success: true,
|
||||||
|
action,
|
||||||
|
collection: targetCollection,
|
||||||
|
product: {
|
||||||
|
id: finalProduct.id,
|
||||||
|
title: finalProduct.title,
|
||||||
|
medusaId: finalProduct.medusaId,
|
||||||
|
seedId: finalProduct.seedId,
|
||||||
|
thumbnail: finalProduct.thumbnail,
|
||||||
|
status: finalProduct.status,
|
||||||
|
lastSyncedAt: finalProduct.lastSyncedAt,
|
||||||
|
// 如果是预购产品,包含预购信息
|
||||||
|
...(targetCollection === 'preorder-products' && {
|
||||||
|
preorderType: finalProduct.preorderType,
|
||||||
|
preorderEndDate: finalProduct.preorderEndDate,
|
||||||
|
fundingGoal: finalProduct.fundingGoal,
|
||||||
|
orderCount: finalProduct.orderCount,
|
||||||
|
fakeOrderCount: finalProduct.fakeOrderCount,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
message: `产品已${action === 'created' ? '创建' : action === 'moved' ? '移动' : action === 'skipped' ? '跳过' : '更新'}于 ${targetCollection}`,
|
||||||
|
})
|
||||||
|
|
||||||
|
return addCorsHeaders(response, origin)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[Sync Product API] ❌ 同步失败:', error)
|
||||||
|
const errorResponse = NextResponse.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
error: error instanceof Error ? error.message : 'Unknown error',
|
||||||
|
},
|
||||||
|
{ status: 500 },
|
||||||
|
)
|
||||||
|
return addCorsHeaders(errorResponse, origin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { NextResponse } from 'next/server'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CORS 配置
|
||||||
|
* 允许 Medusa 开发服务器访问 Payload API
|
||||||
|
*/
|
||||||
|
const ALLOWED_ORIGINS = [
|
||||||
|
'http://localhost:9000', // Medusa 开发服务器
|
||||||
|
'http://localhost:7001', // Medusa Admin 默认端口
|
||||||
|
'http://localhost:7000', // Storefront 默认 端口
|
||||||
|
process.env.MEDUSA_URL,
|
||||||
|
process.env.ADMIN_URL,
|
||||||
|
].filter(Boolean) as string[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 CORS 头部到响应
|
||||||
|
*/
|
||||||
|
export function addCorsHeaders(response: NextResponse, origin?: string | null): NextResponse {
|
||||||
|
// 检查 origin 是否在允许列表中
|
||||||
|
const allowedOrigin = origin && ALLOWED_ORIGINS.includes(origin) ? origin : ALLOWED_ORIGINS[0]
|
||||||
|
|
||||||
|
response.headers.set('Access-Control-Allow-Origin', allowedOrigin)
|
||||||
|
response.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
|
||||||
|
response.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization')
|
||||||
|
response.headers.set('Access-Control-Allow-Credentials', 'true')
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 OPTIONS 预检请求
|
||||||
|
*/
|
||||||
|
export function handleCorsOptions(origin?: string | null): NextResponse {
|
||||||
|
const response = NextResponse.json({}, { status: 200 })
|
||||||
|
return addCorsHeaders(response, origin)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue