diff --git a/build/build-validation.js b/build/build-validation.js
index 65b8053d0b..d3429d36db 100644
--- a/build/build-validation.js
+++ b/build/build-validation.js
@@ -16,6 +16,7 @@ const defaultInitOptions = {
connectionTimeout: 0, // 0 sec
keepAliveTimeout: 5000, // 5 sec
maxRequestsPerSocket: 0, // no limit
+ requestTimeout: 0, // no limit
bodyLimit: 1024 * 1024, // 1 MiB
caseSensitive: true,
disableRequestLogging: false,
@@ -49,6 +50,7 @@ const schema = {
connectionTimeout: { type: 'integer', default: defaultInitOptions.connectionTimeout },
keepAliveTimeout: { type: 'integer', default: defaultInitOptions.keepAliveTimeout },
maxRequestsPerSocket: { type: 'integer', default: defaultInitOptions.maxRequestsPerSocket, nullable: true },
+ requestTimeout: { type: 'integer', default: defaultInitOptions.requestTimeout },
bodyLimit: { type: 'integer', default: defaultInitOptions.bodyLimit },
caseSensitive: { type: 'boolean', default: defaultInitOptions.caseSensitive },
http2: { type: 'boolean' },
diff --git a/docs/Server.md b/docs/Server.md
index b2504e5e3b..a637b0503c 100644
--- a/docs/Server.md
+++ b/docs/Server.md
@@ -13,6 +13,7 @@ document describes the properties available in that options object.
- [connectionTimeout](./Server.md#connectiontimeout)
- [keepAliveTimeout](./Server.md#keepalivetimeout)
- [maxRequestsPerSocket](./Server.md#maxRequestsPerSocket)
+- [requestTimeout](./Server.md#requestTimeout)
- [ignoreTrailingSlash](./Server.md#ignoretrailingslash)
- [maxParamLength](./Server.md#maxparamlength)
- [onProtoPoisoning](./Server.md#onprotopoisoning)
@@ -94,6 +95,17 @@ is in use. Also, when `serverFactory` option is specified, this option is ignore
+ Default: `0` (no limit)
+
+### `requestTimeout`
+
+Defines the maximum number of milliseconds for receiving the entire request from the client.
+[`server.requestTimeout` property](https://nodejs.org/dist/latest/docs/api/http.html#http_server_requesttimeout)
+to understand the effect of this option. Also, when `serverFactory` option is specified, this option is ignored.
+It must be set to a non-zero value (e.g. 120 seconds) to protect against potential Denial-of-Service attacks in case the server is deployed without a reverse proxy in front.
+> At the time of this writing, only node version greater or equal to 14.11.0 support this option. Check the Node.js documentation for availability in the version you are running.
+
++ Default: `0` (no limit)
+
### `ignoreTrailingSlash`
diff --git a/fastify.d.ts b/fastify.d.ts
index ef3ec5e168..0aca4418e6 100644
--- a/fastify.d.ts
+++ b/fastify.d.ts
@@ -97,6 +97,8 @@ export type FastifyServerOptions<
ignoreTrailingSlash?: boolean,
connectionTimeout?: number,
keepAliveTimeout?: number,
+ maxRequestsPerSocket?: number,
+ requestTimeout?: number,
pluginTimeout?: number,
bodyLimit?: number,
maxParamLength?: number,
diff --git a/fastify.js b/fastify.js
index 222298ee03..679bb65516 100644
--- a/fastify.js
+++ b/fastify.js
@@ -133,6 +133,7 @@ function fastify (options) {
options.connectionTimeout = options.connectionTimeout || defaultInitOptions.connectionTimeout
options.keepAliveTimeout = options.keepAliveTimeout || defaultInitOptions.keepAliveTimeout
options.maxRequestsPerSocket = options.maxRequestsPerSocket || defaultInitOptions.maxRequestsPerSocket
+ options.requestTimeout = options.requestTimeout || defaultInitOptions.requestTimeout
options.logger = logger
options.genReqId = genReqId
options.requestIdHeader = requestIdHeader
diff --git a/lib/configValidator.js b/lib/configValidator.js
index 03edb80855..7e6deb5070 100644
--- a/lib/configValidator.js
+++ b/lib/configValidator.js
@@ -15,6 +15,7 @@ var validate = (function() {
if (data.connectionTimeout === undefined) data.connectionTimeout = 0;
if (data.keepAliveTimeout === undefined) data.keepAliveTimeout = 5000;
if (data.maxRequestsPerSocket === undefined) data.maxRequestsPerSocket = 0;
+ if (data.requestTimeout === undefined) data.requestTimeout = 0;
if (data.bodyLimit === undefined) data.bodyLimit = 1048576;
if (data.caseSensitive === undefined) data.caseSensitive = true;
if (data.ignoreTrailingSlash === undefined) data.ignoreTrailingSlash = false;
@@ -114,7 +115,7 @@ var validate = (function() {
}
var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.bodyLimit;
+ var data1 = data.requestTimeout;
var errs_1 = errors;
if ((typeof data1 !== "number" || (data1 % 1) || data1 !== data1)) {
var dataType1 = typeof data1;
@@ -124,8 +125,8 @@ var validate = (function() {
else {
validate.errors = [{
keyword: 'type',
- dataPath: (dataPath || '') + '.bodyLimit',
- schemaPath: '#/properties/bodyLimit/type',
+ dataPath: (dataPath || '') + '.requestTimeout',
+ schemaPath: '#/properties/requestTimeout/type',
params: {
type: 'integer'
},
@@ -135,298 +136,297 @@ var validate = (function() {
}
if (coerced1 !== undefined) {
data1 = coerced1;
- data['bodyLimit'] = coerced1;
+ data['requestTimeout'] = coerced1;
}
}
var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.caseSensitive;
+ var data1 = data.bodyLimit;
var errs_1 = errors;
- if (typeof data1 !== "boolean") {
+ if ((typeof data1 !== "number" || (data1 % 1) || data1 !== data1)) {
var dataType1 = typeof data1;
var coerced1 = undefined;
if (coerced1 !== undefined);
- else if (data1 === 'false' || data1 === 0 || data1 === null) coerced1 = false;
- else if (data1 === 'true' || data1 === 1) coerced1 = true;
+ else if (dataType1 == 'boolean' || data1 === null || (dataType1 == 'string' && data1 && data1 == +data1 && !(data1 % 1))) coerced1 = +data1;
else {
validate.errors = [{
keyword: 'type',
- dataPath: (dataPath || '') + '.caseSensitive',
- schemaPath: '#/properties/caseSensitive/type',
+ dataPath: (dataPath || '') + '.bodyLimit',
+ schemaPath: '#/properties/bodyLimit/type',
params: {
- type: 'boolean'
+ type: 'integer'
},
- message: 'should be boolean'
+ message: 'should be integer'
}];
return false;
}
if (coerced1 !== undefined) {
data1 = coerced1;
- data['caseSensitive'] = coerced1;
+ data['bodyLimit'] = coerced1;
}
}
var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.http2;
- if (data1 === undefined) {
- valid1 = true;
- } else {
- var errs_1 = errors;
- if (typeof data1 !== "boolean") {
- var dataType1 = typeof data1;
- var coerced1 = undefined;
- if (coerced1 !== undefined);
- else if (data1 === 'false' || data1 === 0 || data1 === null) coerced1 = false;
- else if (data1 === 'true' || data1 === 1) coerced1 = true;
- else {
- validate.errors = [{
- keyword: 'type',
- dataPath: (dataPath || '') + '.http2',
- schemaPath: '#/properties/http2/type',
- params: {
- type: 'boolean'
- },
- message: 'should be boolean'
- }];
- return false;
- }
- if (coerced1 !== undefined) {
- data1 = coerced1;
- data['http2'] = coerced1;
- }
+ var data1 = data.caseSensitive;
+ var errs_1 = errors;
+ if (typeof data1 !== "boolean") {
+ var dataType1 = typeof data1;
+ var coerced1 = undefined;
+ if (coerced1 !== undefined);
+ else if (data1 === 'false' || data1 === 0 || data1 === null) coerced1 = false;
+ else if (data1 === 'true' || data1 === 1) coerced1 = true;
+ else {
+ validate.errors = [{
+ keyword: 'type',
+ dataPath: (dataPath || '') + '.caseSensitive',
+ schemaPath: '#/properties/caseSensitive/type',
+ params: {
+ type: 'boolean'
+ },
+ message: 'should be boolean'
+ }];
+ return false;
+ }
+ if (coerced1 !== undefined) {
+ data1 = coerced1;
+ data['caseSensitive'] = coerced1;
}
- var valid1 = errors === errs_1;
}
+ var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.https;
+ var data1 = data.http2;
if (data1 === undefined) {
valid1 = true;
} else {
var errs_1 = errors;
- var errs__1 = errors;
- var valid1 = true;
- var errs_2 = errors;
- var errs__2 = errors;
- var errs_3 = errors;
- var errs__3 = errors,
- prevValid3 = false,
- valid3 = false,
- passingSchemas3 = null;
- var errs_4 = errors;
if (typeof data1 !== "boolean") {
- var dataType4 = typeof data1;
- var coerced4 = undefined;
- if (coerced4 !== undefined);
- else if (data1 === 'false' || data1 === 0 || data1 === null) coerced4 = false;
- else if (data1 === 'true' || data1 === 1) coerced4 = true;
- else {
- var err = {};
- if (vErrors === null) vErrors = [err];
- else vErrors.push(err);
- errors++;
- }
- if (coerced4 !== undefined) {
- data1 = coerced4;
- data['https'] = coerced4;
- }
- }
- var valid4 = errors === errs_4;
- if (valid4) {
- valid3 = prevValid3 = true;
- passingSchemas3 = 0;
- }
- var errs_4 = errors;
- if (data1 !== null) {
- var dataType4 = typeof data1;
- var coerced4 = undefined;
- if (coerced4 !== undefined);
- else if (data1 === '' || data1 === 0 || data1 === false) coerced4 = null;
+ var dataType1 = typeof data1;
+ var coerced1 = undefined;
+ if (coerced1 !== undefined);
+ else if (data1 === 'false' || data1 === 0 || data1 === null) coerced1 = false;
+ else if (data1 === 'true' || data1 === 1) coerced1 = true;
else {
- var err = {};
- if (vErrors === null) vErrors = [err];
- else vErrors.push(err);
- errors++;
+ validate.errors = [{
+ keyword: 'type',
+ dataPath: (dataPath || '') + '.http2',
+ schemaPath: '#/properties/http2/type',
+ params: {
+ type: 'boolean'
+ },
+ message: 'should be boolean'
+ }];
+ return false;
}
- if (coerced4 !== undefined) {
- data1 = coerced4;
- data['https'] = coerced4;
+ if (coerced1 !== undefined) {
+ data1 = coerced1;
+ data['http2'] = coerced1;
}
}
- var valid4 = errors === errs_4;
- if (valid4 && prevValid3) {
- valid3 = false;
- passingSchemas3 = [passingSchemas3, 1];
+ var valid1 = errors === errs_1;
+ }
+ if (valid1) {
+ var data1 = data.https;
+ if (data1 === undefined) {
+ valid1 = true;
} else {
+ var errs_1 = errors;
+ var errs__1 = errors;
+ var valid1 = true;
+ var errs_2 = errors;
+ var errs__2 = errors;
+ var errs_3 = errors;
+ var errs__3 = errors,
+ prevValid3 = false,
+ valid3 = false,
+ passingSchemas3 = null;
+ var errs_4 = errors;
+ if (typeof data1 !== "boolean") {
+ var dataType4 = typeof data1;
+ var coerced4 = undefined;
+ if (coerced4 !== undefined);
+ else if (data1 === 'false' || data1 === 0 || data1 === null) coerced4 = false;
+ else if (data1 === 'true' || data1 === 1) coerced4 = true;
+ else {
+ var err = {};
+ if (vErrors === null) vErrors = [err];
+ else vErrors.push(err);
+ errors++;
+ }
+ if (coerced4 !== undefined) {
+ data1 = coerced4;
+ data['https'] = coerced4;
+ }
+ }
+ var valid4 = errors === errs_4;
if (valid4) {
valid3 = prevValid3 = true;
- passingSchemas3 = 1;
+ passingSchemas3 = 0;
}
var errs_4 = errors;
- if ((data1 && typeof data1 === "object" && !Array.isArray(data1))) {
- if (true) {
- var errs__4 = errors;
- var valid5 = true;
- for (var key4 in data1) {
- var isAdditional4 = !(false || key4 == 'allowHTTP1');
- if (isAdditional4) {
- delete data1[key4];
+ if (data1 !== null) {
+ var dataType4 = typeof data1;
+ var coerced4 = undefined;
+ if (coerced4 !== undefined);
+ else if (data1 === '' || data1 === 0 || data1 === false) coerced4 = null;
+ else {
+ var err = {};
+ if (vErrors === null) vErrors = [err];
+ else vErrors.push(err);
+ errors++;
+ }
+ if (coerced4 !== undefined) {
+ data1 = coerced4;
+ data['https'] = coerced4;
+ }
+ }
+ var valid4 = errors === errs_4;
+ if (valid4 && prevValid3) {
+ valid3 = false;
+ passingSchemas3 = [passingSchemas3, 1];
+ } else {
+ if (valid4) {
+ valid3 = prevValid3 = true;
+ passingSchemas3 = 1;
+ }
+ var errs_4 = errors;
+ if ((data1 && typeof data1 === "object" && !Array.isArray(data1))) {
+ if (true) {
+ var errs__4 = errors;
+ var valid5 = true;
+ for (var key4 in data1) {
+ var isAdditional4 = !(false || key4 == 'allowHTTP1');
+ if (isAdditional4) {
+ delete data1[key4];
+ }
}
- }
- if (valid5) {
- var data2 = data1.allowHTTP1;
- if (data2 === undefined) {
- valid5 = false;
- var err = {};
- if (vErrors === null) vErrors = [err];
- else vErrors.push(err);
- errors++;
- } else {
- var errs_5 = errors;
- if (typeof data2 !== "boolean") {
- var dataType5 = typeof data2;
- var coerced5 = undefined;
- if (coerced5 !== undefined);
- else if (data2 === 'false' || data2 === 0 || data2 === null) coerced5 = false;
- else if (data2 === 'true' || data2 === 1) coerced5 = true;
- else {
- var err = {};
- if (vErrors === null) vErrors = [err];
- else vErrors.push(err);
- errors++;
- }
- if (coerced5 !== undefined) {
- data2 = coerced5;
- data1['allowHTTP1'] = coerced5;
+ if (valid5) {
+ var data2 = data1.allowHTTP1;
+ if (data2 === undefined) {
+ valid5 = false;
+ var err = {};
+ if (vErrors === null) vErrors = [err];
+ else vErrors.push(err);
+ errors++;
+ } else {
+ var errs_5 = errors;
+ if (typeof data2 !== "boolean") {
+ var dataType5 = typeof data2;
+ var coerced5 = undefined;
+ if (coerced5 !== undefined);
+ else if (data2 === 'false' || data2 === 0 || data2 === null) coerced5 = false;
+ else if (data2 === 'true' || data2 === 1) coerced5 = true;
+ else {
+ var err = {};
+ if (vErrors === null) vErrors = [err];
+ else vErrors.push(err);
+ errors++;
+ }
+ if (coerced5 !== undefined) {
+ data2 = coerced5;
+ data1['allowHTTP1'] = coerced5;
+ }
}
+ var valid5 = errors === errs_5;
}
- var valid5 = errors === errs_5;
+ if (valid5) {}
}
- if (valid5) {}
+ if (errs__4 == errors) {}
}
- if (errs__4 == errors) {}
+ } else {
+ var err = {};
+ if (vErrors === null) vErrors = [err];
+ else vErrors.push(err);
+ errors++;
}
- } else {
+ if (errors === errs_4) {}
+ var valid4 = errors === errs_4;
+ if (valid4 && prevValid3) {
+ valid3 = false;
+ passingSchemas3 = [passingSchemas3, 2];
+ } else {
+ if (valid4) {
+ valid3 = prevValid3 = true;
+ passingSchemas3 = 2;
+ }
+ }
+ }
+ if (!valid3) {
var err = {};
if (vErrors === null) vErrors = [err];
else vErrors.push(err);
errors++;
+ } else {
+ errors = errs__3;
+ if (vErrors !== null) {
+ if (errs__3) vErrors.length = errs__3;
+ else vErrors = null;
+ }
}
- if (errors === errs_4) {}
- var valid4 = errors === errs_4;
- if (valid4 && prevValid3) {
- valid3 = false;
- passingSchemas3 = [passingSchemas3, 2];
+ if (errors === errs_3) {}
+ var valid3 = errors === errs_3;
+ if (valid3) {
+ var err = {};
+ if (vErrors === null) vErrors = [err];
+ else vErrors.push(err);
+ errors++;
} else {
- if (valid4) {
- valid3 = prevValid3 = true;
- passingSchemas3 = 2;
+ errors = errs__2;
+ if (vErrors !== null) {
+ if (errs__2) vErrors.length = errs__2;
+ else vErrors = null;
}
}
- }
- if (!valid3) {
- var err = {};
- if (vErrors === null) vErrors = [err];
- else vErrors.push(err);
- errors++;
- } else {
- errors = errs__3;
+ if (errors === errs_2) {}
+ var valid2 = errors === errs_2;
+ errors = errs__1;
if (vErrors !== null) {
- if (errs__3) vErrors.length = errs__3;
+ if (errs__1) vErrors.length = errs__1;
else vErrors = null;
}
- }
- if (errors === errs_3) {}
- var valid3 = errors === errs_3;
- if (valid3) {
- var err = {};
- if (vErrors === null) vErrors = [err];
- else vErrors.push(err);
- errors++;
- } else {
- errors = errs__2;
- if (vErrors !== null) {
- if (errs__2) vErrors.length = errs__2;
- else vErrors = null;
+ if (valid2) {
+ var errs_2 = errors;
+ customRule0.errors = null;
+ var errs__2 = errors;
+ var valid2;
+ valid2 = customRule0.call(self, validate.schema.properties.https.then.setDefaultValue, data1, validate.schema.properties.https.then, (dataPath || '') + '.https', data, 'https', rootData);
+ if (data) data1 = data['https'];
+ if (!valid2) {
+ validate.errors = [{
+ keyword: 'setDefaultValue',
+ dataPath: (dataPath || '') + '.https',
+ schemaPath: '#/properties/https/then/setDefaultValue',
+ params: {
+ keyword: 'setDefaultValue'
+ },
+ message: 'should pass "setDefaultValue" keyword validation'
+ }];
+ return false;
+ } else {}
+ if (errors === errs_2) {}
+ var valid2 = errors === errs_2;
+ valid1 = valid2;
}
- }
- if (errors === errs_2) {}
- var valid2 = errors === errs_2;
- errors = errs__1;
- if (vErrors !== null) {
- if (errs__1) vErrors.length = errs__1;
- else vErrors = null;
- }
- if (valid2) {
- var errs_2 = errors;
- customRule0.errors = null;
- var errs__2 = errors;
- var valid2;
- valid2 = customRule0.call(self, validate.schema.properties.https.then.setDefaultValue, data1, validate.schema.properties.https.then, (dataPath || '') + '.https', data, 'https', rootData);
- if (data) data1 = data['https'];
- if (!valid2) {
- validate.errors = [{
- keyword: 'setDefaultValue',
+ if (!valid1) {
+ var err = {
+ keyword: 'if',
dataPath: (dataPath || '') + '.https',
- schemaPath: '#/properties/https/then/setDefaultValue',
+ schemaPath: '#/properties/https/if',
params: {
- keyword: 'setDefaultValue'
+ failingKeyword: 'then'
},
- message: 'should pass "setDefaultValue" keyword validation'
- }];
+ message: 'should match "' + 'then' + '" schema'
+ };
+ if (vErrors === null) vErrors = [err];
+ else vErrors.push(err);
+ errors++;
+ validate.errors = vErrors;
return false;
} else {}
- if (errors === errs_2) {}
- var valid2 = errors === errs_2;
- valid1 = valid2;
- }
- if (!valid1) {
- var err = {
- keyword: 'if',
- dataPath: (dataPath || '') + '.https',
- schemaPath: '#/properties/https/if',
- params: {
- failingKeyword: 'then'
- },
- message: 'should match "' + 'then' + '" schema'
- };
- if (vErrors === null) vErrors = [err];
- else vErrors.push(err);
- errors++;
- validate.errors = vErrors;
- return false;
- } else {}
- if (errors === errs_1) {}
- var valid1 = errors === errs_1;
- }
- if (valid1) {
- var data1 = data.ignoreTrailingSlash;
- var errs_1 = errors;
- if (typeof data1 !== "boolean") {
- var dataType1 = typeof data1;
- var coerced1 = undefined;
- if (coerced1 !== undefined);
- else if (data1 === 'false' || data1 === 0 || data1 === null) coerced1 = false;
- else if (data1 === 'true' || data1 === 1) coerced1 = true;
- else {
- validate.errors = [{
- keyword: 'type',
- dataPath: (dataPath || '') + '.ignoreTrailingSlash',
- schemaPath: '#/properties/ignoreTrailingSlash/type',
- params: {
- type: 'boolean'
- },
- message: 'should be boolean'
- }];
- return false;
- }
- if (coerced1 !== undefined) {
- data1 = coerced1;
- data['ignoreTrailingSlash'] = coerced1;
- }
+ if (errors === errs_1) {}
+ var valid1 = errors === errs_1;
}
- var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.disableRequestLogging;
+ var data1 = data.ignoreTrailingSlash;
var errs_1 = errors;
if (typeof data1 !== "boolean") {
var dataType1 = typeof data1;
@@ -437,8 +437,8 @@ var validate = (function() {
else {
validate.errors = [{
keyword: 'type',
- dataPath: (dataPath || '') + '.disableRequestLogging',
- schemaPath: '#/properties/disableRequestLogging/type',
+ dataPath: (dataPath || '') + '.ignoreTrailingSlash',
+ schemaPath: '#/properties/ignoreTrailingSlash/type',
params: {
type: 'boolean'
},
@@ -448,12 +448,12 @@ var validate = (function() {
}
if (coerced1 !== undefined) {
data1 = coerced1;
- data['disableRequestLogging'] = coerced1;
+ data['ignoreTrailingSlash'] = coerced1;
}
}
var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.jsonShorthand;
+ var data1 = data.disableRequestLogging;
var errs_1 = errors;
if (typeof data1 !== "boolean") {
var dataType1 = typeof data1;
@@ -464,8 +464,8 @@ var validate = (function() {
else {
validate.errors = [{
keyword: 'type',
- dataPath: (dataPath || '') + '.jsonShorthand',
- schemaPath: '#/properties/jsonShorthand/type',
+ dataPath: (dataPath || '') + '.disableRequestLogging',
+ schemaPath: '#/properties/disableRequestLogging/type',
params: {
type: 'boolean'
},
@@ -475,65 +475,65 @@ var validate = (function() {
}
if (coerced1 !== undefined) {
data1 = coerced1;
- data['jsonShorthand'] = coerced1;
+ data['disableRequestLogging'] = coerced1;
}
}
var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.maxParamLength;
+ var data1 = data.jsonShorthand;
var errs_1 = errors;
- if ((typeof data1 !== "number" || (data1 % 1) || data1 !== data1)) {
+ if (typeof data1 !== "boolean") {
var dataType1 = typeof data1;
var coerced1 = undefined;
if (coerced1 !== undefined);
- else if (dataType1 == 'boolean' || data1 === null || (dataType1 == 'string' && data1 && data1 == +data1 && !(data1 % 1))) coerced1 = +data1;
+ else if (data1 === 'false' || data1 === 0 || data1 === null) coerced1 = false;
+ else if (data1 === 'true' || data1 === 1) coerced1 = true;
else {
validate.errors = [{
keyword: 'type',
- dataPath: (dataPath || '') + '.maxParamLength',
- schemaPath: '#/properties/maxParamLength/type',
+ dataPath: (dataPath || '') + '.jsonShorthand',
+ schemaPath: '#/properties/jsonShorthand/type',
params: {
- type: 'integer'
+ type: 'boolean'
},
- message: 'should be integer'
+ message: 'should be boolean'
}];
return false;
}
if (coerced1 !== undefined) {
data1 = coerced1;
- data['maxParamLength'] = coerced1;
+ data['jsonShorthand'] = coerced1;
}
}
var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.onProtoPoisoning;
+ var data1 = data.maxParamLength;
var errs_1 = errors;
- if (typeof data1 !== "string") {
+ if ((typeof data1 !== "number" || (data1 % 1) || data1 !== data1)) {
var dataType1 = typeof data1;
var coerced1 = undefined;
if (coerced1 !== undefined);
- else if (dataType1 == 'number' || dataType1 == 'boolean') coerced1 = '' + data1;
- else if (data1 === null) coerced1 = '';
+ else if (dataType1 == 'boolean' || data1 === null || (dataType1 == 'string' && data1 && data1 == +data1 && !(data1 % 1))) coerced1 = +data1;
else {
validate.errors = [{
keyword: 'type',
- dataPath: (dataPath || '') + '.onProtoPoisoning',
- schemaPath: '#/properties/onProtoPoisoning/type',
+ dataPath: (dataPath || '') + '.maxParamLength',
+ schemaPath: '#/properties/maxParamLength/type',
params: {
- type: 'string'
+ type: 'integer'
},
- message: 'should be string'
+ message: 'should be integer'
}];
return false;
}
if (coerced1 !== undefined) {
data1 = coerced1;
- data['onProtoPoisoning'] = coerced1;
+ data['maxParamLength'] = coerced1;
}
}
var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.onConstructorPoisoning;
+ var data1 = data.onProtoPoisoning;
var errs_1 = errors;
if (typeof data1 !== "string") {
var dataType1 = typeof data1;
@@ -544,8 +544,8 @@ var validate = (function() {
else {
validate.errors = [{
keyword: 'type',
- dataPath: (dataPath || '') + '.onConstructorPoisoning',
- schemaPath: '#/properties/onConstructorPoisoning/type',
+ dataPath: (dataPath || '') + '.onProtoPoisoning',
+ schemaPath: '#/properties/onProtoPoisoning/type',
params: {
type: 'string'
},
@@ -555,65 +555,65 @@ var validate = (function() {
}
if (coerced1 !== undefined) {
data1 = coerced1;
- data['onConstructorPoisoning'] = coerced1;
+ data['onProtoPoisoning'] = coerced1;
}
}
var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.pluginTimeout;
+ var data1 = data.onConstructorPoisoning;
var errs_1 = errors;
- if ((typeof data1 !== "number" || (data1 % 1) || data1 !== data1)) {
+ if (typeof data1 !== "string") {
var dataType1 = typeof data1;
var coerced1 = undefined;
if (coerced1 !== undefined);
- else if (dataType1 == 'boolean' || data1 === null || (dataType1 == 'string' && data1 && data1 == +data1 && !(data1 % 1))) coerced1 = +data1;
+ else if (dataType1 == 'number' || dataType1 == 'boolean') coerced1 = '' + data1;
+ else if (data1 === null) coerced1 = '';
else {
validate.errors = [{
keyword: 'type',
- dataPath: (dataPath || '') + '.pluginTimeout',
- schemaPath: '#/properties/pluginTimeout/type',
+ dataPath: (dataPath || '') + '.onConstructorPoisoning',
+ schemaPath: '#/properties/onConstructorPoisoning/type',
params: {
- type: 'integer'
+ type: 'string'
},
- message: 'should be integer'
+ message: 'should be string'
}];
return false;
}
if (coerced1 !== undefined) {
data1 = coerced1;
- data['pluginTimeout'] = coerced1;
+ data['onConstructorPoisoning'] = coerced1;
}
}
var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.requestIdHeader;
+ var data1 = data.pluginTimeout;
var errs_1 = errors;
- if (typeof data1 !== "string") {
+ if ((typeof data1 !== "number" || (data1 % 1) || data1 !== data1)) {
var dataType1 = typeof data1;
var coerced1 = undefined;
if (coerced1 !== undefined);
- else if (dataType1 == 'number' || dataType1 == 'boolean') coerced1 = '' + data1;
- else if (data1 === null) coerced1 = '';
+ else if (dataType1 == 'boolean' || data1 === null || (dataType1 == 'string' && data1 && data1 == +data1 && !(data1 % 1))) coerced1 = +data1;
else {
validate.errors = [{
keyword: 'type',
- dataPath: (dataPath || '') + '.requestIdHeader',
- schemaPath: '#/properties/requestIdHeader/type',
+ dataPath: (dataPath || '') + '.pluginTimeout',
+ schemaPath: '#/properties/pluginTimeout/type',
params: {
- type: 'string'
+ type: 'integer'
},
- message: 'should be string'
+ message: 'should be integer'
}];
return false;
}
if (coerced1 !== undefined) {
data1 = coerced1;
- data['requestIdHeader'] = coerced1;
+ data['pluginTimeout'] = coerced1;
}
}
var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.requestIdLogLabel;
+ var data1 = data.requestIdHeader;
var errs_1 = errors;
if (typeof data1 !== "string") {
var dataType1 = typeof data1;
@@ -624,8 +624,8 @@ var validate = (function() {
else {
validate.errors = [{
keyword: 'type',
- dataPath: (dataPath || '') + '.requestIdLogLabel',
- schemaPath: '#/properties/requestIdLogLabel/type',
+ dataPath: (dataPath || '') + '.requestIdHeader',
+ schemaPath: '#/properties/requestIdHeader/type',
params: {
type: 'string'
},
@@ -635,190 +635,101 @@ var validate = (function() {
}
if (coerced1 !== undefined) {
data1 = coerced1;
- data['requestIdLogLabel'] = coerced1;
+ data['requestIdHeader'] = coerced1;
}
}
var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.http2SessionTimeout;
+ var data1 = data.requestIdLogLabel;
var errs_1 = errors;
- if ((typeof data1 !== "number" || (data1 % 1) || data1 !== data1)) {
+ if (typeof data1 !== "string") {
var dataType1 = typeof data1;
var coerced1 = undefined;
if (coerced1 !== undefined);
- else if (dataType1 == 'boolean' || data1 === null || (dataType1 == 'string' && data1 && data1 == +data1 && !(data1 % 1))) coerced1 = +data1;
+ else if (dataType1 == 'number' || dataType1 == 'boolean') coerced1 = '' + data1;
+ else if (data1 === null) coerced1 = '';
else {
validate.errors = [{
keyword: 'type',
- dataPath: (dataPath || '') + '.http2SessionTimeout',
- schemaPath: '#/properties/http2SessionTimeout/type',
+ dataPath: (dataPath || '') + '.requestIdLogLabel',
+ schemaPath: '#/properties/requestIdLogLabel/type',
params: {
- type: 'integer'
+ type: 'string'
},
- message: 'should be integer'
+ message: 'should be string'
}];
return false;
}
if (coerced1 !== undefined) {
data1 = coerced1;
- data['http2SessionTimeout'] = coerced1;
+ data['requestIdLogLabel'] = coerced1;
}
}
var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.versioning;
- if (data1 === undefined) {
- valid1 = true;
- } else {
- var errs_1 = errors;
- if ((data1 && typeof data1 === "object" && !Array.isArray(data1))) {
- var missing1;
- if (((data1.storage === undefined) && (missing1 = '.storage')) || ((data1.deriveVersion === undefined) && (missing1 = '.deriveVersion'))) {
- validate.errors = [{
- keyword: 'required',
- dataPath: (dataPath || '') + '.versioning',
- schemaPath: '#/properties/versioning/required',
- params: {
- missingProperty: '' + missing1 + ''
- },
- message: 'should have required property \'' + missing1 + '\''
- }];
- return false;
- } else {
- var errs__1 = errors;
- var valid2 = true;
- for (var key1 in data1) {
- var isAdditional1 = !(false || key1 == 'storage' || key1 == 'deriveVersion');
- if (isAdditional1) {}
- }
- if (valid2) {
- if (valid2) {
- if (valid2) {}
- }
- }
- if (errs__1 == errors) {}
- }
- } else {
+ var data1 = data.http2SessionTimeout;
+ var errs_1 = errors;
+ if ((typeof data1 !== "number" || (data1 % 1) || data1 !== data1)) {
+ var dataType1 = typeof data1;
+ var coerced1 = undefined;
+ if (coerced1 !== undefined);
+ else if (dataType1 == 'boolean' || data1 === null || (dataType1 == 'string' && data1 && data1 == +data1 && !(data1 % 1))) coerced1 = +data1;
+ else {
validate.errors = [{
keyword: 'type',
- dataPath: (dataPath || '') + '.versioning',
- schemaPath: '#/properties/versioning/type',
+ dataPath: (dataPath || '') + '.http2SessionTimeout',
+ schemaPath: '#/properties/http2SessionTimeout/type',
params: {
- type: 'object'
+ type: 'integer'
},
- message: 'should be object'
+ message: 'should be integer'
}];
return false;
}
- if (errors === errs_1) {}
- var valid1 = errors === errs_1;
+ if (coerced1 !== undefined) {
+ data1 = coerced1;
+ data['http2SessionTimeout'] = coerced1;
+ }
}
+ var valid1 = errors === errs_1;
if (valid1) {
- var data1 = data.constraints;
+ var data1 = data.versioning;
if (data1 === undefined) {
valid1 = true;
} else {
var errs_1 = errors;
if ((data1 && typeof data1 === "object" && !Array.isArray(data1))) {
- var errs__1 = errors;
- var valid2 = true;
- for (var key1 in data1) {
- var data2 = data1[key1];
- var errs_2 = errors;
- if ((data2 && typeof data2 === "object" && !Array.isArray(data2))) {
- var missing2;
- if (((data2.storage === undefined) && (missing2 = '.storage')) || ((data2.validate === undefined) && (missing2 = '.validate')) || ((data2.deriveConstraint === undefined) && (missing2 = '.deriveConstraint'))) {
- validate.errors = [{
- keyword: 'required',
- dataPath: (dataPath || '') + '.constraints[\'' + key1 + '\']',
- schemaPath: '#/properties/constraints/additionalProperties/required',
- params: {
- missingProperty: '' + missing2 + ''
- },
- message: 'should have required property \'' + missing2 + '\''
- }];
- return false;
- } else {
- var errs__2 = errors;
- var valid3 = true;
- for (var key2 in data2) {
- var isAdditional2 = !(false || key2 == 'name' || key2 == 'storage' || key2 == 'validate' || key2 == 'deriveConstraint');
- if (isAdditional2) {}
- }
- if (valid3) {
- var data3 = data2.name;
- if (data3 === undefined) {
- valid3 = false;
- validate.errors = [{
- keyword: 'required',
- dataPath: (dataPath || '') + '.constraints[\'' + key1 + '\']',
- schemaPath: '#/properties/constraints/additionalProperties/required',
- params: {
- missingProperty: 'name'
- },
- message: 'should have required property \'name\''
- }];
- return false;
- } else {
- var errs_3 = errors;
- if (typeof data3 !== "string") {
- var dataType3 = typeof data3;
- var coerced3 = undefined;
- if (coerced3 !== undefined);
- else if (dataType3 == 'number' || dataType3 == 'boolean') coerced3 = '' + data3;
- else if (data3 === null) coerced3 = '';
- else {
- validate.errors = [{
- keyword: 'type',
- dataPath: (dataPath || '') + '.constraints[\'' + key1 + '\'].name',
- schemaPath: '#/properties/constraints/additionalProperties/properties/name/type',
- params: {
- type: 'string'
- },
- message: 'should be string'
- }];
- return false;
- }
- if (coerced3 !== undefined) {
- data3 = coerced3;
- data2['name'] = coerced3;
- }
- }
- var valid3 = errors === errs_3;
- }
- if (valid3) {
- if (valid3) {
- if (valid3) {
- if (valid3) {}
- }
- }
- }
- }
- if (errs__2 == errors) {}
+ var missing1;
+ if (((data1.storage === undefined) && (missing1 = '.storage')) || ((data1.deriveVersion === undefined) && (missing1 = '.deriveVersion'))) {
+ validate.errors = [{
+ keyword: 'required',
+ dataPath: (dataPath || '') + '.versioning',
+ schemaPath: '#/properties/versioning/required',
+ params: {
+ missingProperty: '' + missing1 + ''
+ },
+ message: 'should have required property \'' + missing1 + '\''
+ }];
+ return false;
+ } else {
+ var errs__1 = errors;
+ var valid2 = true;
+ for (var key1 in data1) {
+ var isAdditional1 = !(false || key1 == 'storage' || key1 == 'deriveVersion');
+ if (isAdditional1) {}
+ }
+ if (valid2) {
+ if (valid2) {
+ if (valid2) {}
}
- } else {
- validate.errors = [{
- keyword: 'type',
- dataPath: (dataPath || '') + '.constraints[\'' + key1 + '\']',
- schemaPath: '#/properties/constraints/additionalProperties/type',
- params: {
- type: 'object'
- },
- message: 'should be object'
- }];
- return false;
}
- if (errors === errs_2) {}
- var valid2 = errors === errs_2;
- if (!valid2) break;
+ if (errs__1 == errors) {}
}
- if (valid2) {}
- if (errs__1 == errors) {}
} else {
validate.errors = [{
keyword: 'type',
- dataPath: (dataPath || '') + '.constraints',
- schemaPath: '#/properties/constraints/type',
+ dataPath: (dataPath || '') + '.versioning',
+ schemaPath: '#/properties/versioning/type',
params: {
type: 'object'
},
@@ -829,7 +740,124 @@ var validate = (function() {
if (errors === errs_1) {}
var valid1 = errors === errs_1;
}
- if (valid1) {}
+ if (valid1) {
+ var data1 = data.constraints;
+ if (data1 === undefined) {
+ valid1 = true;
+ } else {
+ var errs_1 = errors;
+ if ((data1 && typeof data1 === "object" && !Array.isArray(data1))) {
+ var errs__1 = errors;
+ var valid2 = true;
+ for (var key1 in data1) {
+ var data2 = data1[key1];
+ var errs_2 = errors;
+ if ((data2 && typeof data2 === "object" && !Array.isArray(data2))) {
+ var missing2;
+ if (((data2.storage === undefined) && (missing2 = '.storage')) || ((data2.validate === undefined) && (missing2 = '.validate')) || ((data2.deriveConstraint === undefined) && (missing2 = '.deriveConstraint'))) {
+ validate.errors = [{
+ keyword: 'required',
+ dataPath: (dataPath || '') + '.constraints[\'' + key1 + '\']',
+ schemaPath: '#/properties/constraints/additionalProperties/required',
+ params: {
+ missingProperty: '' + missing2 + ''
+ },
+ message: 'should have required property \'' + missing2 + '\''
+ }];
+ return false;
+ } else {
+ var errs__2 = errors;
+ var valid3 = true;
+ for (var key2 in data2) {
+ var isAdditional2 = !(false || key2 == 'name' || key2 == 'storage' || key2 == 'validate' || key2 == 'deriveConstraint');
+ if (isAdditional2) {}
+ }
+ if (valid3) {
+ var data3 = data2.name;
+ if (data3 === undefined) {
+ valid3 = false;
+ validate.errors = [{
+ keyword: 'required',
+ dataPath: (dataPath || '') + '.constraints[\'' + key1 + '\']',
+ schemaPath: '#/properties/constraints/additionalProperties/required',
+ params: {
+ missingProperty: 'name'
+ },
+ message: 'should have required property \'name\''
+ }];
+ return false;
+ } else {
+ var errs_3 = errors;
+ if (typeof data3 !== "string") {
+ var dataType3 = typeof data3;
+ var coerced3 = undefined;
+ if (coerced3 !== undefined);
+ else if (dataType3 == 'number' || dataType3 == 'boolean') coerced3 = '' + data3;
+ else if (data3 === null) coerced3 = '';
+ else {
+ validate.errors = [{
+ keyword: 'type',
+ dataPath: (dataPath || '') + '.constraints[\'' + key1 + '\'].name',
+ schemaPath: '#/properties/constraints/additionalProperties/properties/name/type',
+ params: {
+ type: 'string'
+ },
+ message: 'should be string'
+ }];
+ return false;
+ }
+ if (coerced3 !== undefined) {
+ data3 = coerced3;
+ data2['name'] = coerced3;
+ }
+ }
+ var valid3 = errors === errs_3;
+ }
+ if (valid3) {
+ if (valid3) {
+ if (valid3) {
+ if (valid3) {}
+ }
+ }
+ }
+ }
+ if (errs__2 == errors) {}
+ }
+ } else {
+ validate.errors = [{
+ keyword: 'type',
+ dataPath: (dataPath || '') + '.constraints[\'' + key1 + '\']',
+ schemaPath: '#/properties/constraints/additionalProperties/type',
+ params: {
+ type: 'object'
+ },
+ message: 'should be object'
+ }];
+ return false;
+ }
+ if (errors === errs_2) {}
+ var valid2 = errors === errs_2;
+ if (!valid2) break;
+ }
+ if (valid2) {}
+ if (errs__1 == errors) {}
+ } else {
+ validate.errors = [{
+ keyword: 'type',
+ dataPath: (dataPath || '') + '.constraints',
+ schemaPath: '#/properties/constraints/type',
+ params: {
+ type: 'object'
+ },
+ message: 'should be object'
+ }];
+ return false;
+ }
+ if (errors === errs_1) {}
+ var valid1 = errors === errs_1;
+ }
+ if (valid1) {}
+ }
}
}
}
@@ -884,6 +912,10 @@ validate.schema = {
"default": 0,
"nullable": true
},
+ "requestTimeout": {
+ "type": "integer",
+ "default": 0
+ },
"bodyLimit": {
"type": "integer",
"default": 1048576
@@ -993,4 +1025,4 @@ function customRule0 (schemaParamValue, validatedParamValue, validationSchemaObj
return true
}
-module.exports.defaultInitOptions = {"connectionTimeout":0,"keepAliveTimeout":5000,"maxRequestsPerSocket":0,"bodyLimit":1048576,"caseSensitive":true,"disableRequestLogging":false,"jsonShorthand":true,"ignoreTrailingSlash":false,"maxParamLength":100,"onProtoPoisoning":"error","onConstructorPoisoning":"error","pluginTimeout":10000,"requestIdHeader":"request-id","requestIdLogLabel":"reqId","http2SessionTimeout":5000}
+module.exports.defaultInitOptions = {"connectionTimeout":0,"keepAliveTimeout":5000,"maxRequestsPerSocket":0,"requestTimeout":0,"bodyLimit":1048576,"caseSensitive":true,"disableRequestLogging":false,"jsonShorthand":true,"ignoreTrailingSlash":false,"maxParamLength":100,"onProtoPoisoning":"error","onConstructorPoisoning":"error","pluginTimeout":10000,"requestIdHeader":"request-id","requestIdLogLabel":"reqId","http2SessionTimeout":5000}
diff --git a/lib/server.js b/lib/server.js
index d8510af995..d34fabf99a 100644
--- a/lib/server.js
+++ b/lib/server.js
@@ -28,6 +28,7 @@ function createServer (options, httpHandler) {
} else {
server = http.createServer(httpHandler)
server.keepAliveTimeout = options.keepAliveTimeout
+ server.requestTimeout = options.requestTimeout
// we treat zero as null
// and null is the default setting from nodejs
// so we do not pass the option to server
diff --git a/test/internals/initialConfig.test.js b/test/internals/initialConfig.test.js
index 719d8f00ca..a2ddaf6b6c 100644
--- a/test/internals/initialConfig.test.js
+++ b/test/internals/initialConfig.test.js
@@ -25,6 +25,7 @@ test('without options passed to Fastify, initialConfig should expose default val
connectionTimeout: 0,
keepAliveTimeout: 5000,
maxRequestsPerSocket: 0,
+ requestTimeout: 0,
bodyLimit: 1024 * 1024,
caseSensitive: true,
disableRequestLogging: false,
@@ -242,6 +243,7 @@ test('Should not have issues when passing stream options to Pino.js', t => {
connectionTimeout: 0,
keepAliveTimeout: 5000,
maxRequestsPerSocket: 0,
+ requestTimeout: 0,
bodyLimit: 1024 * 1024,
caseSensitive: true,
disableRequestLogging: false,
diff --git a/test/requestTimeout.test.js b/test/requestTimeout.test.js
new file mode 100644
index 0000000000..7978ea3b48
--- /dev/null
+++ b/test/requestTimeout.test.js
@@ -0,0 +1,50 @@
+'use strict'
+
+const http = require('http')
+const { test } = require('tap')
+const Fastify = require('../fastify')
+
+test('requestTimeout passed to server', t => {
+ t.plan(4)
+
+ try {
+ Fastify({ requestTimeout: 500.1 })
+ t.fail('option must be an integer')
+ } catch (err) {
+ t.ok(err)
+ }
+
+ try {
+ Fastify({ requestTimeout: [] })
+ t.fail('option must be an integer')
+ } catch (err) {
+ t.ok(err)
+ }
+
+ const httpServer = Fastify({ requestTimeout: 1000 }).server
+ t.equal(httpServer.requestTimeout, 1000)
+
+ const serverFactory = (handler, _) => {
+ const server = http.createServer((req, res) => {
+ handler(req, res)
+ })
+ server.requestTimeout = 5000
+ return server
+ }
+ const customServer = Fastify({ requestTimeout: 4000, serverFactory }).server
+ t.equal(customServer.requestTimeout, 5000)
+})
+
+test('requestTimeout should be set', async (t) => {
+ t.plan(1)
+
+ const initialConfig = Fastify({ requestTimeout: 5000 }).initialConfig
+ t.same(initialConfig.requestTimeout, 5000)
+})
+
+test('requestTimeout should 0', async (t) => {
+ t.plan(1)
+
+ const initialConfig = Fastify().initialConfig
+ t.same(initialConfig.requestTimeout, 0)
+})