Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions config/config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ ui:
port: 4000
# NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript
nameSpace: /
# The rateLimiter settings limit each IP to a 'max' of 500 requests per 'windowMs' (1 minute).
# The rateLimiter settings limit each IP to a 'limit' of 500 requests per 'windowMs' (1 minute).
rateLimiter:
windowMs: 60000 # 1 minute
max: 500 # limit each IP to 500 requests per windowMs
limit: 500 # limit each IP to 500 requests per windowMs
# IPv6 subnet mask applied to IPv6 addresses.
# See: https://express-rate-limit.mintlify.app/reference/configuration#ipv6subnet
ipv6Subnet: 56
# Trust X-FORWARDED-* headers from proxies (default = true)
useProxies: true

Expand Down
30 changes: 26 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
"deepmerge": "^4.3.1",
"ejs": "^3.1.10",
"express": "^4.21.2",
"express-rate-limit": "^5.1.3",
"express-rate-limit": "^8.0.1",
"fast-json-patch": "^3.1.1",
"filesize": "^10.1.6",
"http-proxy-middleware": "^2.0.9",
Expand Down
10 changes: 7 additions & 3 deletions server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,14 @@ export function app() {
* When it is present, the rateLimiter will be enabled. When it is undefined, the rateLimiter will be disabled.
*/
if (hasValue((environment.ui as UIServerConfig).rateLimiter)) {
const RateLimit = require('express-rate-limit');
const limiter = new RateLimit({
const { rateLimit } = require('express-rate-limit')
const limiter = rateLimit({
windowMs: (environment.ui as UIServerConfig).rateLimiter.windowMs,
max: (environment.ui as UIServerConfig).rateLimiter.max,
limit: (environment.ui as UIServerConfig).rateLimiter.limit,
standardHeaders: true,
legacyHeaders: false,
// don't log ERR_ERL_PERMISSIVE_TRUST_PROXY if we are trusting proxies
validate: {trustProxy: !environment.ui.useProxies},
});
server.use(limiter);
}
Expand Down
9 changes: 6 additions & 3 deletions src/config/config.util.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ describe('Config Util', () => {
const appConfig = new DefaultAppConfig();
expect(appConfig.cache.msToLive.default).toEqual(15 * 60 * 1000); // 15 minute
expect(appConfig.ui.rateLimiter.windowMs).toEqual(1 * 60 * 1000); // 1 minute
expect(appConfig.ui.rateLimiter.max).toEqual(500);
expect(appConfig.ui.rateLimiter.limit).toEqual(500);
expect(appConfig.ui.rateLimiter.ipv6Subnet).toEqual(56);
expect(appConfig.ui.useProxies).toEqual(true);

expect(appConfig.submission.autosave.metadata).toEqual([]);
Expand All @@ -23,7 +24,8 @@ describe('Config Util', () => {

const rateLimiter = {
windowMs: 5 * 50 * 1000, // 5 minutes
max: 1000,
limit: 1000,
ipv6Subnet: 56,
};
appConfig.ui.rateLimiter = rateLimiter;

Expand All @@ -47,7 +49,8 @@ describe('Config Util', () => {

expect(environment.cache.msToLive.default).toEqual(msToLive);
expect(environment.ui.rateLimiter.windowMs).toEqual(rateLimiter.windowMs);
expect(environment.ui.rateLimiter.max).toEqual(rateLimiter.max);
expect(environment.ui.rateLimiter.limit).toEqual(rateLimiter.limit);
expect(environment.ui.rateLimiter.ipv6Subnet).toEqual(rateLimiter.ipv6Subnet);
expect(environment.ui.useProxies).toEqual(false);
expect(environment.submission.autosave.metadata[0]).toEqual(autoSaveMetadata[0]);
expect(environment.submission.autosave.metadata[1]).toEqual(autoSaveMetadata[1]);
Expand Down
5 changes: 3 additions & 2 deletions src/config/default-app-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ export class DefaultAppConfig implements AppConfig {
// NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript
nameSpace: '/',

// The rateLimiter settings limit each IP to a 'max' of 500 requests per 'windowMs' (1 minute).
// The rateLimiter settings limit each IP to a 'limit' of 500 requests per 'windowMs' (1 minute).
rateLimiter: {
windowMs: 1 * 60 * 1000, // 1 minute
max: 500, // limit each IP to 500 requests per windowMs
limit: 500, // limit each IP to 500 requests per windowMs
ipv6Subnet: 56, // IPv6 subnet mask applied to IPv6 addresses
},

// Trust X-FORWARDED-* headers from proxies
Expand Down
3 changes: 2 additions & 1 deletion src/config/ui-server-config.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ export class UIServerConfig extends ServerConfig {
// rateLimiter is used to limit the amount of requests a user is allowed make in an amount of time, in order to prevent overloading the server
rateLimiter?: {
windowMs: number;
max: number;
limit: number;
ipv6Subnet: number;
};

// Trust X-FORWARDED-* headers from proxies
Expand Down
5 changes: 3 additions & 2 deletions src/environments/environment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ export const environment: BuildConfig = {
// NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript
nameSpace: '/angular-dspace',
baseUrl: 'http://dspace.com/angular-dspace',
// The rateLimiter settings limit each IP to a 'max' of 500 requests per 'windowMs' (1 minute).
// The rateLimiter settings limit each IP to a 'limit' of 500 requests per 'windowMs' (1 minute).
rateLimiter: {
windowMs: 1 * 60 * 1000, // 1 minute
max: 500, // limit each IP to 500 requests per windowMs
limit: 500, // limit each IP to 500 requests per windowMs
ipv6Subnet: 56,
},
useProxies: true,
},
Expand Down