Compare commits
3 Commits
developmen
...
bugfix/S3C
Author | SHA1 | Date |
---|---|---|
Dora Korpar | 5d7fe79115 | |
Jonathan Gramain | 633b9c377e | |
Jonathan Gramain | 2d9e91b855 |
|
@ -88,4 +88,16 @@ module.exports = {
|
||||||
's3:ObjectRemoved:DeleteMarkerCreated',
|
's3:ObjectRemoved:DeleteMarkerCreated',
|
||||||
]),
|
]),
|
||||||
notificationArnPrefix: 'arn:scality:bucketnotif',
|
notificationArnPrefix: 'arn:scality:bucketnotif',
|
||||||
|
// HTTP server keep-alive timeout is set to a higher value than
|
||||||
|
// client's free sockets timeout to avoid the risk of triggering
|
||||||
|
// ECONNRESET errors if the server closes the connection at the
|
||||||
|
// exact moment clients attempt to reuse an established connection
|
||||||
|
// for a new request.
|
||||||
|
//
|
||||||
|
// Note: the ability to close inactive connections on the client
|
||||||
|
// after httpClientFreeSocketsTimeout milliseconds requires the
|
||||||
|
// use of "agentkeepalive" module instead of the regular node.js
|
||||||
|
// http.Agent.
|
||||||
|
httpServerKeepAliveTimeout: 60000,
|
||||||
|
httpClientFreeSocketTimeout: 55000,
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,6 +43,7 @@ class Server {
|
||||||
this._address = checkSupportIPv6() ? '::' : '0.0.0.0';
|
this._address = checkSupportIPv6() ? '::' : '0.0.0.0';
|
||||||
this._server = null;
|
this._server = null;
|
||||||
this._logger = logger;
|
this._logger = logger;
|
||||||
|
this._keepAliveTimeout = null; // null: use default node.js value
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,6 +58,19 @@ class Server {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the keep-alive timeout after which inactive client
|
||||||
|
* connections are automatically closed (default should be
|
||||||
|
* 5 seconds in node.js)
|
||||||
|
*
|
||||||
|
* @param {number} keepAliveTimeout - keep-alive timeout in milliseconds
|
||||||
|
* @return {Server} - returns this
|
||||||
|
*/
|
||||||
|
setKeepAliveTimeout(keepAliveTimeout) {
|
||||||
|
this._keepAliveTimeout = keepAliveTimeout;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Getter to access to the http/https server
|
* Getter to access to the http/https server
|
||||||
*
|
*
|
||||||
|
@ -401,6 +415,9 @@ class Server {
|
||||||
this._server = http.createServer(
|
this._server = http.createServer(
|
||||||
(req, res) => this._onRequest(req, res));
|
(req, res) => this._onRequest(req, res));
|
||||||
}
|
}
|
||||||
|
if (this._keepAliveTimeout) {
|
||||||
|
this._server.keepAliveTimeout = this._keepAliveTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
this._server.on('error', err => this._onError(err));
|
this._server.on('error', err => this._onError(err));
|
||||||
this._server.on('secureConnection',
|
this._server.on('secureConnection',
|
||||||
|
|
|
@ -13,6 +13,7 @@ const _actionMap = {
|
||||||
bucketGet: 's3:ListBucket',
|
bucketGet: 's3:ListBucket',
|
||||||
bucketGetACL: 's3:GetBucketAcl',
|
bucketGetACL: 's3:GetBucketAcl',
|
||||||
bucketGetCors: 's3:GetBucketCORS',
|
bucketGetCors: 's3:GetBucketCORS',
|
||||||
|
bucketGetNotificationConfiguration: 's3:GetBucketNotificationConfiguration',
|
||||||
bucketGetObjectLock: 's3:GetBucketObjectLockConfiguration',
|
bucketGetObjectLock: 's3:GetBucketObjectLockConfiguration',
|
||||||
bucketGetVersioning: 's3:GetBucketVersioning',
|
bucketGetVersioning: 's3:GetBucketVersioning',
|
||||||
bucketGetWebsite: 's3:GetBucketWebsite',
|
bucketGetWebsite: 's3:GetBucketWebsite',
|
||||||
|
@ -21,6 +22,7 @@ const _actionMap = {
|
||||||
bucketPut: 's3:CreateBucket',
|
bucketPut: 's3:CreateBucket',
|
||||||
bucketPutACL: 's3:PutBucketAcl',
|
bucketPutACL: 's3:PutBucketAcl',
|
||||||
bucketPutCors: 's3:PutBucketCORS',
|
bucketPutCors: 's3:PutBucketCORS',
|
||||||
|
bucketPutNotificationConfiguration: 's3:PutBucketNotificationConfiguration',
|
||||||
bucketPutObjectLock: 's3:PutBucketObjectLockConfiguration',
|
bucketPutObjectLock: 's3:PutBucketObjectLockConfiguration',
|
||||||
// for bucketDeleteCors need s3:PutBucketCORS permission
|
// for bucketDeleteCors need s3:PutBucketCORS permission
|
||||||
// see http://docs.aws.amazon.com/AmazonS3/latest/API/
|
// see http://docs.aws.amazon.com/AmazonS3/latest/API/
|
||||||
|
|
|
@ -180,4 +180,39 @@ describe('network.Server: ', () => {
|
||||||
res.end('done');
|
res.end('done');
|
||||||
}).start();
|
}).start();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should automatically close idle connections with setKeepAliveTimeout()', done => {
|
||||||
|
const ws = new Server(3000, log);
|
||||||
|
ws.setKeepAliveTimeout(1000);
|
||||||
|
ws.onError(done).onListening(() => {
|
||||||
|
const options = {
|
||||||
|
hostname: '127.0.0.1',
|
||||||
|
port: 3000,
|
||||||
|
path: '/',
|
||||||
|
agent: new http.Agent({ keepAlive: true }),
|
||||||
|
};
|
||||||
|
const req = http.request(options, res => {
|
||||||
|
res.on('data', () => {});
|
||||||
|
res.on('end', () => {});
|
||||||
|
});
|
||||||
|
req.on('error', err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
});
|
||||||
|
req.end();
|
||||||
|
}).onRequest((req, res) => {
|
||||||
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||||
|
res.end();
|
||||||
|
assert.strictEqual(ws._server._connections, 1);
|
||||||
|
setTimeout(() => {
|
||||||
|
// client connection should remain open after less than 1000ms
|
||||||
|
assert.strictEqual(ws._server._connections, 1);
|
||||||
|
setTimeout(() => {
|
||||||
|
// client connection should have been closed after more than 1000ms
|
||||||
|
assert.strictEqual(ws._server.connections, 0);
|
||||||
|
ws.stop();
|
||||||
|
ws.onStop(done);
|
||||||
|
}, 200);
|
||||||
|
}, 900);
|
||||||
|
}).start();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue