refactor: Add cors middleware

This commit is contained in:
journey-ad 2024-10-25 13:36:32 +08:00
parent 1dce9e93aa
commit bdc1cb0794
3 changed files with 85 additions and 51 deletions

View File

@ -7,13 +7,14 @@ const { z } = require("zod");
const db = require("./db");
const { themeList, getCountImage } = require("./utils/themify");
const { ZodValid } = require("./utils/zod");
const { cors, ZodValid } = require("./utils/middleware");
const { randomArray } = require("./utils");
const app = express();
app.use(express.static("assets"));
app.use(compression());
app.use(cors());
app.set("view engine", "pug");
app.get('/', (req, res) => {

83
utils/middleware.js Normal file
View File

@ -0,0 +1,83 @@
function parseError(error) {
const err = JSON.parse(error)[0];
return {
code: 400,
message: `The field \`${err.path[0]}\` is invalid. ${err.message}`,
}
}
function validateInput(parseFn, input) {
const result = parseFn(input);
if (!result.success) {
return parseError(result.error);
}
return null;
}
module.exports = {
ZodValid: ({ headers, params, query, body }) => {
const handler = (req, res, next) => {
const validations = [
{ input: req.headers, parseFn: headers?.safeParse },
{ input: req.params, parseFn: params?.safeParse },
{ input: req.query, parseFn: query?.safeParse },
{ input: req.body, parseFn: body?.safeParse },
];
for (const { input, parseFn } of validations) {
if (parseFn) {
const error = validateInput(parseFn, input);
if (error) {
return res.status(400).send(error);
}
}
}
next();
}
return handler
},
cors: ({ allowOrigins = '*', allowMethods = 'GET, POST, PUT, DELETE' } = {}) => {
const isOriginAllowed = (origin) => {
if (Array.isArray(allowOrigins)) {
return allowOrigins.includes(origin);
}
if (typeof allowOrigins === 'string') {
return allowOrigins === '*' || allowOrigins === origin;
}
return false;
};
const handler = (req, res, next) => {
const origin = req.headers.origin;
if (origin && isOriginAllowed(origin)) {
res.header("Access-Control-Allow-Origin", origin);
res.header("Access-Control-Allow-Credentials", "true");
} else {
return next();
}
if (req.method === "OPTIONS") {
const requestMethod = req.headers['access-control-request-method'];
if (requestMethod) {
res.header("Access-Control-Allow-Methods", requestMethod);
} else {
res.header("Access-Control-Allow-Methods", allowMethods);
}
const requestHeaders = req.headers['access-control-request-headers'];
if (requestHeaders) {
res.header("Access-Control-Allow-Headers", requestHeaders);
}
return res.sendStatus(204);
}
next();
};
return handler;
}
}

View File

@ -1,50 +0,0 @@
function parseError(error) {
const err = JSON.parse(error)[0];
return {
code: 400,
message: `The field \`${err.path[0]}\` is invalid. ${err.message}`,
}
}
module.exports = {
ZodValid: ({ headers, params, query, body }) => {
const handler = (req, res, next) => {
if (headers) {
const result = headers.safeParse(req.headers);
if (!result.success) {
res.status(400).send(parseError(result.error));
return;
}
}
if (params) {
const result = params.safeParse(req.params);
if (!result.success) {
res.status(400).send(parseError(result.error));
return;
}
}
if (query) {
const result = query.safeParse(req.query);
if (!result.success) {
res.status(400).send(parseError(result.error));
return;
}
}
if (body) {
const result = body.safeParse(req.body);
if (!result.success) {
res.status(400).send(parseError(result.error));
return;
}
}
next();
}
return handler
}
}