🎨 Body Parser error
This commit is contained in:
parent
7998b39757
commit
8505d9279b
BIN
package-lock.json
generated
BIN
package-lock.json
generated
Binary file not shown.
@ -21,18 +21,20 @@
|
||||
"@types/express": "^4.17.9",
|
||||
"@types/node-fetch": "^2.5.7",
|
||||
"bcrypt": "^5.0.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"express": "^4.17.1",
|
||||
"express-cache-middleware": "^1.0.1",
|
||||
"express-validator": "^6.9.2",
|
||||
"faker": "^5.1.0",
|
||||
"i18next": "^19.8.5",
|
||||
"i18next-http-middleware": "^3.1.0",
|
||||
"i18next-node-fs-backend": "^2.1.3",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"jwa": "^2.0.0",
|
||||
"jws": "^4.0.0",
|
||||
"lambert-db": "^1.1.3",
|
||||
"lambert-server": "^1.0.9",
|
||||
"missing-native-js-functions": "^1.1.9",
|
||||
"lambert-server": "^1.0.10",
|
||||
"missing-native-js-functions": "^1.2.0",
|
||||
"mongoose": "^5.11.14",
|
||||
"node-fetch": "^2.6.1",
|
||||
"rethinkdb-ts": "^2.4.5"
|
||||
@ -40,6 +42,7 @@
|
||||
"devDependencies": {
|
||||
"@types/bcrypt": "^3.0.0",
|
||||
"@types/faker": "^5.1.5",
|
||||
"@types/i18next-node-fs-backend": "^2.1.0",
|
||||
"@types/jsonwebtoken": "^8.5.0",
|
||||
"@types/jws": "^3.2.3",
|
||||
"@types/node": "^14.14.22",
|
||||
|
||||
@ -4,14 +4,17 @@ import { Authentication, GlobalRateLimit } from "./middlewares/";
|
||||
import Config from "./util/Config";
|
||||
import db from "./util/Database";
|
||||
import i18next from "i18next";
|
||||
import i18nextMiddleware from "i18next-http-middleware";
|
||||
import { Request } from "express";
|
||||
import i18nextMiddleware, { I18next } from "i18next-http-middleware";
|
||||
import i18nextBackend from "i18next-node-fs-backend";
|
||||
import { ErrorHandler } from "./middlewares/ErrorHandler";
|
||||
import { BodyParser } from "./middlewares/BodyParser";
|
||||
|
||||
export interface DiscordServerOptions extends ServerOptions {}
|
||||
|
||||
declare global {
|
||||
namespace Express {
|
||||
interface Request {
|
||||
// @ts-ignore
|
||||
server: DiscordServer;
|
||||
}
|
||||
}
|
||||
@ -21,7 +24,8 @@ export class DiscordServer extends Server {
|
||||
public options: DiscordServerOptions;
|
||||
|
||||
constructor(opts?: Partial<DiscordServerOptions>) {
|
||||
super({ ...opts, errorHandler: false });
|
||||
// @ts-ignore
|
||||
super({ ...opts, errorHandler: false, jsonBody: false });
|
||||
}
|
||||
|
||||
async start() {
|
||||
@ -31,20 +35,28 @@ export class DiscordServer extends Server {
|
||||
|
||||
this.app.use(GlobalRateLimit);
|
||||
this.app.use(Authentication);
|
||||
const namespaces = await fs.readdir(__dirname + "/locales/de/");
|
||||
this.app.use(BodyParser({ inflate: true }));
|
||||
const languages = await fs.readdir(__dirname + "/../locales/");
|
||||
const namespaces = await fs.readdir(__dirname + "/../locales/en/");
|
||||
const ns = namespaces.filter((x) => x.endsWith(".json")).map((x) => x.slice(0, x.length - 5));
|
||||
|
||||
i18next.use(i18nextMiddleware.LanguageDetector).init({
|
||||
preload: ["en", "de"],
|
||||
fallbackLng: "en",
|
||||
ns,
|
||||
backend: {
|
||||
loadPath: "locales/{{lng}}/{{ns}}.json",
|
||||
},
|
||||
});
|
||||
await i18next
|
||||
.use(i18nextBackend)
|
||||
.use(i18nextMiddleware.LanguageDetector)
|
||||
.init({
|
||||
preload: languages,
|
||||
// debug: true,
|
||||
fallbackLng: "en",
|
||||
ns,
|
||||
backend: {
|
||||
loadPath: __dirname + "/../locales/{{lng}}/{{ns}}.json",
|
||||
},
|
||||
load: "all",
|
||||
});
|
||||
this.app.use(i18nextMiddleware.handle(i18next, {}));
|
||||
|
||||
this.routes = await this.registerRoutes(__dirname + "/routes/");
|
||||
this.app.use(ErrorHandler);
|
||||
const indexHTML = await fs.readFile(__dirname + "/../client_test/index.html");
|
||||
|
||||
this.app.get("*", (req, res) => {
|
||||
|
||||
@ -6,3 +6,6 @@ import { DiscordServer } from "./Server";
|
||||
|
||||
const server = new DiscordServer({ port: 3000 });
|
||||
server.start().catch(console.error);
|
||||
|
||||
// @ts-ignore
|
||||
global.server = server;
|
||||
|
||||
@ -19,7 +19,7 @@ export function Authentication(req: Request, res: Response, next: NextFunction)
|
||||
if (NO_AUTHORIZATION_ROUTES.includes(req.url)) return next();
|
||||
if (!req.headers.authorization) return next(new HTTPError("Missing Authorization Header", 401));
|
||||
|
||||
return jwt.verify(req.headers.authorization, Config.get().server.jwtSecret, JWTOptions, (err, decoded: any) => {
|
||||
return jwt.verify(req.headers.authorization, Config.get().security.jwtSecret, JWTOptions, (err, decoded: any) => {
|
||||
if (err || !decoded) return next(new HTTPError("Invalid Token", 401));
|
||||
|
||||
req.token = decoded;
|
||||
|
||||
17
src/middlewares/BodyParser.ts
Normal file
17
src/middlewares/BodyParser.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import bodyParser, { OptionsJson } from "body-parser";
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { HTTPError } from "lambert-server";
|
||||
|
||||
export function BodyParser(opts?: OptionsJson) {
|
||||
const jsonParser = bodyParser.json(opts);
|
||||
|
||||
return (req: Request, res: Response, next: NextFunction) => {
|
||||
jsonParser(req, res, (err) => {
|
||||
if (err) {
|
||||
// TODO: different errors for body parser (request size limit, wrong body type, invalid body, ...)
|
||||
return next(new HTTPError("Invalid Body", 400));
|
||||
}
|
||||
next();
|
||||
});
|
||||
};
|
||||
}
|
||||
@ -3,16 +3,16 @@ import Config from "../util/Config";
|
||||
import db from "../util/Database";
|
||||
|
||||
export async function GlobalRateLimit(req: Request, res: Response, next: NextFunction) {
|
||||
if (!Config.get().server.ipRateLimit.enabled) return next();
|
||||
if (!Config.get().limits.rate.ip.enabled) return next();
|
||||
|
||||
const ip = getIpAdress(req);
|
||||
let limit = (await db.data.ratelimit.global[ip].get()) || { start: Date.now(), count: 0 };
|
||||
if (limit.start < Date.now() - Config.get().server.ipRateLimit.timespan) {
|
||||
if (limit.start < Date.now() - Config.get().limits.rate.ip.timespan) {
|
||||
limit.start = Date.now();
|
||||
limit.count = 0;
|
||||
}
|
||||
|
||||
if (limit.count > Config.get().server.ipRateLimit.count) {
|
||||
if (limit.count > Config.get().limits.rate.ip.count) {
|
||||
const timespan = Date.now() - limit.start;
|
||||
|
||||
return res
|
||||
@ -37,7 +37,7 @@ export async function GlobalRateLimit(req: Request, res: Response, next: NextFun
|
||||
}
|
||||
|
||||
export function getIpAdress(req: Request): string {
|
||||
const { forwadedFor } = Config.get().server;
|
||||
const { forwadedFor } = Config.get().security;
|
||||
const ip = forwadedFor ? <string>req.headers[forwadedFor] : req.ip;
|
||||
return ip.replaceAll(".", "_").replaceAll(":", "_");
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import mongoose from "mongoose";
|
||||
import { Long } from "mongodb";
|
||||
import { Snowflake } from "../util/Snowflake";
|
||||
|
||||
async function main() {
|
||||
const conn = await mongoose.createConnection(
|
||||
@ -9,10 +11,7 @@ async function main() {
|
||||
}
|
||||
);
|
||||
console.log("connected");
|
||||
const result = await conn
|
||||
.collection("users")
|
||||
.find({ $or: [{ email: "samuel.scheit@gmail.com" }, { phone: "samuel.scheit@gmail.com" }] })
|
||||
.toArray();
|
||||
const result = await conn.collection("users").insertOne({ test: Long.fromString(Snowflake.generate().toString()) });
|
||||
// .project(undefined)
|
||||
|
||||
console.log(result);
|
||||
|
||||
@ -1,6 +1,20 @@
|
||||
export const WHITE_SPACE = /\s\s+/g;
|
||||
import { Request } from "express";
|
||||
import { FieldError, FieldErrors } from "./instanceOf";
|
||||
|
||||
export const DOUBLE_WHITE_SPACE = /\s\s+/g;
|
||||
export const SPECIAL_CHAR = /[@#`:\r\n\t\f\v\p{C}]/gu;
|
||||
|
||||
export function trim(str: string) {
|
||||
return str.replace(SPECIAL_CHAR, "").replace(WHITE_SPACE, " ").trim();
|
||||
export function trimSpecial(str: string) {
|
||||
return str.replace(SPECIAL_CHAR, "").replace(DOUBLE_WHITE_SPACE, " ").trim();
|
||||
}
|
||||
|
||||
export function checkLength(str: string, min: number, max: number, key: string, req: Request) {
|
||||
if (str.length < min || str.length > max) {
|
||||
throw FieldErrors({
|
||||
[key]: {
|
||||
code: "BASE_TYPE_BAD_LENGTH",
|
||||
message: req.t("common:field.BASE_TYPE_BAD_LENGTH", { length: `${min} - ${max}` }),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,7 +95,7 @@ export function instanceOf(
|
||||
return true;
|
||||
throw new FieldError("BASE_TYPE_CHOICES", t("common:field.BASE_TYPE_CHOICES", { types: type.types }));
|
||||
case Email:
|
||||
if ((<Email>type).check()) return true;
|
||||
if (new Email(value).check()) return true;
|
||||
throw new FieldError("EMAIL_TYPE_INVALID_EMAIL", t("common:field.EMAIL_TYPE_INVALID_EMAIL"));
|
||||
case Date:
|
||||
value = new Date(value);
|
||||
@ -143,13 +143,13 @@ export function instanceOf(
|
||||
let newKey = key;
|
||||
const OPTIONAL = key.startsWith(OPTIONAL_PREFIX);
|
||||
if (OPTIONAL) newKey = newKey.slice(OPTIONAL_PREFIX.length);
|
||||
errors[key] = {};
|
||||
errors[newKey] = {};
|
||||
|
||||
return (
|
||||
instanceOf(type[key], value[newKey], {
|
||||
path: `${path}.${newKey}`,
|
||||
optional: OPTIONAL,
|
||||
errors: errors[key],
|
||||
errors: errors[newKey],
|
||||
t,
|
||||
ref: { key: newKey, obj: value },
|
||||
}) === true
|
||||
|
||||
Reference in New Issue
Block a user