143 lines
4.7 KiB
JavaScript
143 lines
4.7 KiB
JavaScript
const Koa = require('koa')
|
|
const Router = require('koa-router')
|
|
const https = require('https')
|
|
const fs = require('fs')
|
|
const cors = require('@koa/cors')
|
|
const bodyParser = require('koa-bodyparser')
|
|
const path = require('path')
|
|
require('dotenv').config()
|
|
|
|
const app = new Koa()
|
|
const router = new Router()
|
|
|
|
const ALLOWED_ORIGINS = (process.env.CORS_ORIGIN || '')
|
|
.split(',')
|
|
.map(s => s.trim())
|
|
.filter(Boolean)
|
|
const IS_PROD = process.env.NODE_ENV === 'production'
|
|
|
|
if (IS_PROD && ALLOWED_ORIGINS.length === 0) {
|
|
console.error('CORS_ORIGIN is required in production. Set comma-separated allowlist in .env')
|
|
}
|
|
|
|
function corsOriginCheck(ctx) {
|
|
const reqOrigin = ctx.request.header.origin || ''
|
|
if (ALLOWED_ORIGINS.length === 0) {
|
|
return IS_PROD ? '' : reqOrigin || '*'
|
|
}
|
|
if (ALLOWED_ORIGINS.includes('*')) return reqOrigin
|
|
return ALLOWED_ORIGINS.includes(reqOrigin) ? reqOrigin : ''
|
|
}
|
|
|
|
app.use(cors({
|
|
origin: corsOriginCheck,
|
|
credentials: true,
|
|
allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
|
allowHeaders: ['Content-Type', 'Authorization']
|
|
}))
|
|
|
|
app.use(bodyParser({
|
|
jsonLimit: '5mb',
|
|
formLimit: '5mb'
|
|
}))
|
|
|
|
app.use(require('koa-static')(path.join(__dirname, 'public')))
|
|
|
|
const errorHandler = async (ctx, next) => {
|
|
try {
|
|
await next()
|
|
if (ctx.status === 404) {
|
|
ctx.body = {
|
|
code: 404,
|
|
message: '接口不存在'
|
|
}
|
|
ctx.status = 404
|
|
}
|
|
} catch (error) {
|
|
console.error('Server error:', error)
|
|
ctx.status = error.status || 500
|
|
ctx.body = {
|
|
code: ctx.status,
|
|
message: IS_PROD ? '服务器内部错误' : error.message
|
|
}
|
|
}
|
|
}
|
|
|
|
app.use(errorHandler)
|
|
|
|
const orderRoutes = require('./routes/orders')
|
|
const categoryRoutes = require('./routes/categories')
|
|
const goodsRoutes = require('./routes/goods')
|
|
const userRoutes = require('./routes/users')
|
|
const uploadRoutes = require('./routes/upload')
|
|
const stockRoutes = require('./routes/stock')
|
|
const aiRoutes = require('./routes/ai')
|
|
const supplierRoutes = require('./routes/suppliers')
|
|
const purchaseRoutes = require('./routes/purchases')
|
|
const pointsGoodsRoutes = require('./routes/points-goods')
|
|
const statsRoutes = require('./routes/stats')
|
|
const priceListRoutes = require('./routes/price-list')
|
|
const pointsLogsRoutes = require('./routes/points-logs')
|
|
const recognizeRoutes = require('./routes/recognize')
|
|
const reportRoutes = require('./routes/reports')
|
|
const exportRoutes = require('./routes/export')
|
|
const subscribeRoutes = require('./routes/subscribe')
|
|
const addressRoutes = require('./routes/addresses')
|
|
const goodsSpecRoutes = require('./routes/goods-specs')
|
|
const cartRoutes = require('./routes/carts')
|
|
const refundRoutes = require('./routes/refunds')
|
|
const homeCategoryRoutes = require('./routes/homeCategories')
|
|
const paymentRoutes = require('./routes/payment')
|
|
|
|
router.use('/api/orders', orderRoutes)
|
|
router.use('/api/categories', categoryRoutes)
|
|
router.use('/api/goods', goodsRoutes)
|
|
router.use('/api/users', userRoutes)
|
|
router.use('/api/upload', uploadRoutes)
|
|
router.use('/api/stock', stockRoutes)
|
|
router.use('/api/ai', aiRoutes)
|
|
router.use('/api/suppliers', supplierRoutes)
|
|
router.use('/api/purchases', purchaseRoutes)
|
|
router.use('/api/points-goods', pointsGoodsRoutes)
|
|
router.use('/api/stats', statsRoutes)
|
|
router.use('/api/price-list', priceListRoutes)
|
|
router.use('/api/points/logs', pointsLogsRoutes)
|
|
router.use('/api/recognize', recognizeRoutes)
|
|
router.use('/api/reports', reportRoutes)
|
|
router.use('/api/export', exportRoutes)
|
|
router.use('/api/subscribe', subscribeRoutes)
|
|
router.use('/api/addresses', addressRoutes)
|
|
router.use('/api/goods-specs', goodsSpecRoutes)
|
|
router.use('/api/cart', cartRoutes)
|
|
router.use('/api/refunds', refundRoutes)
|
|
router.use('/api/home', homeCategoryRoutes)
|
|
router.use('/api/payment', paymentRoutes)
|
|
|
|
app.use(router.routes())
|
|
app.use(router.allowedMethods())
|
|
|
|
const { startHealthCheck } = require('./config/database')
|
|
const PORT = parseInt(process.env.PORT) || 3006
|
|
const HTTPS_ENABLED = process.env.HTTPS_ENABLED === '1'
|
|
const SSL_KEY = process.env.SSL_KEY_PATH
|
|
const SSL_CERT = process.env.SSL_CERT_PATH
|
|
|
|
if (HTTPS_ENABLED) {
|
|
if (!SSL_KEY || !SSL_CERT || !fs.existsSync(SSL_KEY) || !fs.existsSync(SSL_CERT)) {
|
|
console.error('HTTPS_ENABLED=1 but SSL_KEY_PATH / SSL_CERT_PATH missing or files not found')
|
|
process.exit(1)
|
|
}
|
|
const options = { key: fs.readFileSync(SSL_KEY), cert: fs.readFileSync(SSL_CERT) }
|
|
https.createServer(options, app.callback()).listen(PORT, () => {
|
|
console.log(`HTTPS server running on port ${PORT}`)
|
|
startHealthCheck(30000)
|
|
})
|
|
} else {
|
|
if (IS_PROD) {
|
|
console.warn('Running HTTP in production. Set HTTPS_ENABLED=1 + SSL_KEY_PATH/SSL_CERT_PATH')
|
|
}
|
|
app.listen(PORT, () => {
|
|
console.log(`Server running on port ${PORT}`)
|
|
startHealthCheck(30000)
|
|
})
|
|
} |