axe-api 1.5.0-rc-1 → 1.5.0-rc-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.d.ts +2 -2
- package/build/index.js +2 -2
- package/build/src/Handlers/RequestHandler.js +3 -5
- package/build/src/Interfaces.d.ts +5 -0
- package/build/src/Middlewares/RateLimit/index.d.ts +13 -2
- package/build/src/Middlewares/RateLimit/index.js +49 -29
- package/build/src/Services/AxeResponse.js +1 -1
- package/package.json +1 -1
package/build/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ import ApiError from "./src/Exceptions/ApiError";
|
|
|
4
4
|
import RedisAdaptor from "./src/Middlewares/RateLimit/RedisAdaptor";
|
|
5
5
|
import { DEFAULT_HANDLERS, DEFAULT_VERSION_CONFIG } from "./src/constants";
|
|
6
6
|
import { IoCService, allow, deny, App, AxeRequest, AxeResponse } from "./src/Services";
|
|
7
|
-
import { rateLimit,
|
|
7
|
+
import { rateLimit, createRateLimitter } from "./src/Middlewares/RateLimit";
|
|
8
8
|
export * from "./src/Enums";
|
|
9
9
|
export * from "./src/Interfaces";
|
|
10
10
|
export * from "./src/Types";
|
|
11
|
-
export { App, AxeRequest, AxeResponse, Server, Model, ApiError, RedisAdaptor, DEFAULT_HANDLERS, DEFAULT_VERSION_CONFIG, IoCService, allow, deny, rateLimit,
|
|
11
|
+
export { App, AxeRequest, AxeResponse, Server, Model, ApiError, RedisAdaptor, DEFAULT_HANDLERS, DEFAULT_VERSION_CONFIG, IoCService, allow, deny, rateLimit, createRateLimitter, };
|
package/build/index.js
CHANGED
|
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.
|
|
20
|
+
exports.createRateLimitter = exports.rateLimit = exports.deny = exports.allow = exports.IoCService = exports.DEFAULT_VERSION_CONFIG = exports.DEFAULT_HANDLERS = exports.RedisAdaptor = exports.ApiError = exports.Model = exports.Server = exports.AxeResponse = exports.AxeRequest = exports.App = void 0;
|
|
21
21
|
const Server_1 = __importDefault(require("./src/Server"));
|
|
22
22
|
exports.Server = Server_1.default;
|
|
23
23
|
const Model_1 = __importDefault(require("./src/Model"));
|
|
@@ -38,7 +38,7 @@ Object.defineProperty(exports, "AxeRequest", { enumerable: true, get: function (
|
|
|
38
38
|
Object.defineProperty(exports, "AxeResponse", { enumerable: true, get: function () { return Services_1.AxeResponse; } });
|
|
39
39
|
const RateLimit_1 = require("./src/Middlewares/RateLimit");
|
|
40
40
|
Object.defineProperty(exports, "rateLimit", { enumerable: true, get: function () { return RateLimit_1.rateLimit; } });
|
|
41
|
-
Object.defineProperty(exports, "
|
|
41
|
+
Object.defineProperty(exports, "createRateLimitter", { enumerable: true, get: function () { return RateLimit_1.createRateLimitter; } });
|
|
42
42
|
__exportStar(require("./src/Enums"), exports);
|
|
43
43
|
__exportStar(require("./src/Interfaces"), exports);
|
|
44
44
|
__exportStar(require("./src/Types"), exports);
|
|
@@ -53,11 +53,9 @@ exports.default = (request, response, next) => __awaiter(void 0, void 0, void 0,
|
|
|
53
53
|
}
|
|
54
54
|
const validator = yield Services_1.IoCService.use("Validator");
|
|
55
55
|
const context = Object.assign(Object.assign({}, match.data), { params: match.params, api, req: axeRequest, res: axeResponse, isTransactionOpen: match.hasTransaction, database: match.hasTransaction && trx ? trx : database, validator });
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
response.setHeader("x-powered-by", "Axe API");
|
|
60
|
-
}
|
|
56
|
+
response.setHeader("Content-Type", "application/json");
|
|
57
|
+
if (api.config.disableXPoweredByHeader === false) {
|
|
58
|
+
response.setHeader("x-powered-by", "Axe API");
|
|
61
59
|
}
|
|
62
60
|
for (const phase of match.phases) {
|
|
63
61
|
// If there is an non-async phase, it should be an Event function
|
|
@@ -44,6 +44,11 @@ export interface IQueryConfig {
|
|
|
44
44
|
limits: Array<IQueryLimitConfig[]>;
|
|
45
45
|
defaults?: IQueryDefaultConfig;
|
|
46
46
|
}
|
|
47
|
+
export interface IRateLimitMiddleware {
|
|
48
|
+
name: string;
|
|
49
|
+
clientKey: string;
|
|
50
|
+
setResponseHeaders?: boolean;
|
|
51
|
+
}
|
|
47
52
|
export interface IRateLimitOptions {
|
|
48
53
|
maxRequests: number;
|
|
49
54
|
windowInSeconds: number;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { IncomingMessage, ServerResponse } from "http";
|
|
2
|
-
import { AxeConfig, IRateLimitOptions, IContext } from "../../Interfaces";
|
|
2
|
+
import { AxeConfig, IRateLimitOptions, IContext, IRateLimitMiddleware } from "../../Interfaces";
|
|
3
3
|
export declare const setupRateLimitAdaptors: (config: AxeConfig) => Promise<void>;
|
|
4
|
-
export declare const createRateLimitMiddleware: (req: IncomingMessage, res: ServerResponse, next: () => void, key: string, options: IRateLimitOptions) => Promise<void>;
|
|
5
4
|
/**
|
|
6
5
|
* Add a rate limit with the `IRateLimitOptions`
|
|
7
6
|
*
|
|
@@ -20,5 +19,17 @@ export declare const createRateLimitMiddleware: (req: IncomingMessage, res: Serv
|
|
|
20
19
|
* }
|
|
21
20
|
*/
|
|
22
21
|
export declare const rateLimit: (options?: IRateLimitOptions) => (context: IContext) => Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Create a rate-limitter middleware (a connect middleware) with a middleware
|
|
24
|
+
* configurations
|
|
25
|
+
*
|
|
26
|
+
* @param middleware IRateLimitMiddleware
|
|
27
|
+
* @param options IRateLimitOptions
|
|
28
|
+
* @param req IncomingMessage
|
|
29
|
+
* @param res ServerResponse
|
|
30
|
+
* @param next NextFunction
|
|
31
|
+
* @returns
|
|
32
|
+
*/
|
|
33
|
+
export declare const createRateLimitter: (middleware: IRateLimitMiddleware, options: IRateLimitOptions, req: IncomingMessage, res: ServerResponse, next: any) => Promise<any>;
|
|
23
34
|
declare const _default: (req: IncomingMessage, res: ServerResponse, next: any) => Promise<any>;
|
|
24
35
|
export default _default;
|
|
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.
|
|
15
|
+
exports.createRateLimitter = exports.rateLimit = exports.setupRateLimitAdaptors = void 0;
|
|
16
16
|
const AdaptorFactory_1 = __importDefault(require("./AdaptorFactory"));
|
|
17
17
|
const Services_1 = require("../../Services");
|
|
18
18
|
const nanoid_1 = require("nanoid");
|
|
@@ -70,25 +70,6 @@ const setupRateLimitAdaptors = (config) => __awaiter(void 0, void 0, void 0, fun
|
|
|
70
70
|
adaptor = yield (0, AdaptorFactory_1.default)(((_a = config.rateLimit) === null || _a === void 0 ? void 0 : _a.adaptor) || "memory");
|
|
71
71
|
});
|
|
72
72
|
exports.setupRateLimitAdaptors = setupRateLimitAdaptors;
|
|
73
|
-
const createRateLimitMiddleware = (req, res, next, key, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
74
|
-
// Checking the rate limit
|
|
75
|
-
const isAllowed = yield checkRateLimit(key, options);
|
|
76
|
-
// Setting the headers
|
|
77
|
-
res.setHeader("X-RateLimit-Limit", isAllowed.limit);
|
|
78
|
-
res.setHeader("X-RateLimit-Remaining", isAllowed.remaining);
|
|
79
|
-
// Sending an error message if there is an error
|
|
80
|
-
if (isAllowed.success === false) {
|
|
81
|
-
Services_1.LogService.warn(`Rate limit exceeded: ${req.url}`);
|
|
82
|
-
res.statusCode = Enums_1.StatusCodes.TOO_MANY_REQUESTS;
|
|
83
|
-
res.write(JSON.stringify({
|
|
84
|
-
error: "Rate limit exceeded.",
|
|
85
|
-
}));
|
|
86
|
-
res.isResponded = true;
|
|
87
|
-
res.end();
|
|
88
|
-
}
|
|
89
|
-
next();
|
|
90
|
-
});
|
|
91
|
-
exports.createRateLimitMiddleware = createRateLimitMiddleware;
|
|
92
73
|
/**
|
|
93
74
|
* Add a rate limit with the `IRateLimitOptions`
|
|
94
75
|
*
|
|
@@ -109,21 +90,60 @@ exports.createRateLimitMiddleware = createRateLimitMiddleware;
|
|
|
109
90
|
const rateLimit = (options) => {
|
|
110
91
|
// For each model middleware, we should use a different ID for the cache key
|
|
111
92
|
const id = (0, nanoid_1.nanoid)();
|
|
112
|
-
// API configuration fetching
|
|
113
|
-
const api = Services_1.APIService.getInstance();
|
|
114
|
-
// Developers are able to set different rate limit options
|
|
115
|
-
// in model files. That's why we should create a new option object.
|
|
116
|
-
const selectedOptions = Object.assign(Object.assign({}, api.config.rateLimit), options);
|
|
117
93
|
return (context) => __awaiter(void 0, void 0, void 0, function* () {
|
|
94
|
+
// API configuration fetching
|
|
95
|
+
const api = Services_1.APIService.getInstance();
|
|
118
96
|
// Creating a clientkey by the client key configurations
|
|
119
97
|
const clientKey = getClientKeyByConfigurations(context.req.original, api.config.rateLimit);
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
98
|
+
// Developers are able to set different rate limit options
|
|
99
|
+
// in model files. That's why we should create a new option object.
|
|
100
|
+
const selectedOptions = Object.assign(Object.assign({}, api.config.rateLimit), options);
|
|
101
|
+
// Checking the rate limit
|
|
102
|
+
const isAllowed = yield checkRateLimit(`${clientKey}:${id}`, selectedOptions);
|
|
103
|
+
// Setting the headers
|
|
104
|
+
context.res.original.setHeader("X-RateLimit-Limit", isAllowed.limit);
|
|
105
|
+
context.res.original.setHeader("X-RateLimit-Remaining", isAllowed.remaining);
|
|
106
|
+
// Sending an error message if there is an error
|
|
107
|
+
if (isAllowed.success === false) {
|
|
108
|
+
Services_1.LogService.warn(`Rate limit exceeded: ${context.req.url}`);
|
|
109
|
+
context.res
|
|
110
|
+
.status(Enums_1.StatusCodes.TOO_MANY_REQUESTS)
|
|
111
|
+
.json({ error: "Rate limit exceeded." });
|
|
112
|
+
}
|
|
124
113
|
});
|
|
125
114
|
};
|
|
126
115
|
exports.rateLimit = rateLimit;
|
|
116
|
+
/**
|
|
117
|
+
* Create a rate-limitter middleware (a connect middleware) with a middleware
|
|
118
|
+
* configurations
|
|
119
|
+
*
|
|
120
|
+
* @param middleware IRateLimitMiddleware
|
|
121
|
+
* @param options IRateLimitOptions
|
|
122
|
+
* @param req IncomingMessage
|
|
123
|
+
* @param res ServerResponse
|
|
124
|
+
* @param next NextFunction
|
|
125
|
+
* @returns
|
|
126
|
+
*/
|
|
127
|
+
const createRateLimitter = (middleware, options, req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
|
128
|
+
// Checking the rate limits.
|
|
129
|
+
const isAllowed = yield checkRateLimit(middleware.clientKey, options);
|
|
130
|
+
// Setting the HTTP Response headers.
|
|
131
|
+
if (middleware.setResponseHeaders) {
|
|
132
|
+
res.setHeader(`X-${middleware.name}-Limit`, isAllowed.limit);
|
|
133
|
+
res.setHeader(`X-${middleware.name}-Remaining`, isAllowed.remaining);
|
|
134
|
+
}
|
|
135
|
+
// If it is allowed, the next function would be called.
|
|
136
|
+
if (isAllowed.success) {
|
|
137
|
+
return next();
|
|
138
|
+
}
|
|
139
|
+
// Sending an error message.
|
|
140
|
+
Services_1.LogService.warn(`Rate limit exceeded: ${req.url}`);
|
|
141
|
+
res.writeHead(429, { "Content-Type": "application/json" });
|
|
142
|
+
res.end(JSON.stringify({
|
|
143
|
+
error: "Rate limit exceeded.",
|
|
144
|
+
}));
|
|
145
|
+
});
|
|
146
|
+
exports.createRateLimitter = createRateLimitter;
|
|
127
147
|
exports.default = (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
|
128
148
|
const api = Services_1.APIService.getInstance();
|
|
129
149
|
// Generating the client key
|