@@ -11,8 +11,6 @@ const dbg = require('../util/debug_module')(__filename);
11
11
if ( ! dbg . get_process_name ( ) ) dbg . set_process_name ( 'Endpoint' ) ;
12
12
13
13
const util = require ( 'util' ) ;
14
- const http = require ( 'http' ) ;
15
- const https = require ( 'https' ) ;
16
14
const os = require ( 'os' ) ;
17
15
18
16
const P = require ( '../util/promise' ) ;
@@ -28,7 +26,7 @@ const StsSDK = require('../sdk/sts_sdk');
28
26
const ObjectIO = require ( '../sdk/object_io' ) ;
29
27
const ObjectSDK = require ( '../sdk/object_sdk' ) ;
30
28
const xml_utils = require ( '../util/xml_utils' ) ;
31
- const ssl_utils = require ( '../util/ssl_utils ' ) ;
29
+ const http_utils = require ( '../util/http_utils ' ) ;
32
30
const net_utils = require ( '../util/net_utils' ) ;
33
31
const addr_utils = require ( '../util/addr_utils' ) ;
34
32
const fork_utils = require ( '../util/fork_utils' ) ;
@@ -57,7 +55,8 @@ if (process.env.NOOBAA_LOG_LEVEL) {
57
55
const SERVICES_TYPES_ENUM = Object . freeze ( {
58
56
S3 : 'S3' ,
59
57
STS : 'STS' ,
60
- IAM : 'IAM'
58
+ IAM : 'IAM' ,
59
+ METRICS : 'METRICS'
61
60
} ) ;
62
61
63
62
const new_umask = process . env . NOOBAA_ENDPOINT_UMASK || 0o000 ;
@@ -66,7 +65,7 @@ let fork_count;
66
65
dbg . log0 ( 'endpoint: replacing old umask: ' , old_umask . toString ( 8 ) , 'with new umask: ' , new_umask . toString ( 8 ) ) ;
67
66
68
67
/**
69
- * @typedef {http.IncomingMessage & {
68
+ * @typedef {import(' http') .IncomingMessage & {
70
69
* object_sdk?: ObjectSDK;
71
70
* func_sdk?: FuncSDK;
72
71
* sts_sdk?: StsSDK;
@@ -79,7 +78,7 @@ dbg.log0('endpoint: replacing old umask: ', old_umask.toString(8), 'with new uma
79
78
/**
80
79
* @typedef {(
81
80
* req: EndpointRequest,
82
- * res: http.ServerResponse
81
+ * res: import(' http') .ServerResponse
83
82
* ) => void | Promise<void>} EndpointHandler
84
83
*/
85
84
@@ -89,18 +88,14 @@ dbg.log0('endpoint: replacing old umask: ', old_umask.toString(8), 'with new uma
89
88
* https_port?: number;
90
89
* https_port_sts?: number;
91
90
* https_port_iam?: number;
92
- * metrics_port?: number;
91
+ * http_metrics_port?: number;
92
+ * https_metrics_port?: number;
93
93
* nsfs_config_root?: string;
94
94
* init_request_sdk?: EndpointHandler;
95
95
* forks?: number;
96
96
* }} EndpointOptions
97
97
*/
98
98
99
- // An internal function to prevent code duplication
100
- async function create_https_server ( ssl_cert_info , honorCipherOrder , endpoint_handler ) {
101
- const ssl_options = { ...ssl_cert_info . cert , honorCipherOrder : honorCipherOrder } ;
102
- return https . createServer ( ssl_options , endpoint_handler ) ;
103
- }
104
99
105
100
/**
106
101
* @param {EndpointOptions } options
@@ -117,7 +112,8 @@ async function main(options = {}) {
117
112
118
113
// the primary just forks and returns, workers will continue to serve
119
114
fork_count = options . forks ?? config . ENDPOINT_FORKS ;
120
- const metrics_port = options . metrics_port || config . EP_METRICS_SERVER_PORT ;
115
+ const http_metrics_port = options . http_metrics_port || config . EP_METRICS_SERVER_PORT ;
116
+ const https_metrics_port = options . https_metrics_port || config . EP_METRICS_SERVER_SSL_PORT ;
121
117
/**
122
118
* Please notice that we can run the main in 2 states:
123
119
* 1. Only the primary process runs the main (fork is 0 or undefined) - everything that
@@ -127,7 +123,8 @@ async function main(options = {}) {
127
123
* fork_utils.start_workers because the primary process returns after start_workers
128
124
* and the forks will continue executing the code lines in this function
129
125
* */
130
- const is_workers_started_from_primary = await fork_utils . start_workers ( metrics_port , fork_count ) ;
126
+ const is_workers_started_from_primary = await fork_utils . start_workers ( http_metrics_port , https_metrics_port ,
127
+ options . nsfs_config_root , fork_count ) ;
131
128
if ( is_workers_started_from_primary ) return ;
132
129
133
130
const endpoint_group_id = process . env . ENDPOINT_GROUP_ID || 'default-endpoint-group' ;
@@ -200,17 +197,15 @@ async function main(options = {}) {
200
197
const https_port_sts = options . https_port_sts || config . ENDPOINT_SSL_STS_PORT ;
201
198
const https_port_iam = options . https_port_iam || config . ENDPOINT_SSL_IAM_PORT ;
202
199
203
- await start_server_and_cert ( SERVICES_TYPES_ENUM . S3 , init_request_sdk ,
200
+ await start_endpoint_server_and_cert ( SERVICES_TYPES_ENUM . S3 , init_request_sdk ,
204
201
{ ...options , https_port : https_port_s3 , http_port : http_port_s3 , virtual_hosts, bucket_logger, notification_logger } ) ;
205
- await start_server_and_cert ( SERVICES_TYPES_ENUM . STS , init_request_sdk , { https_port : https_port_sts , virtual_hosts } ) ;
206
- await start_server_and_cert ( SERVICES_TYPES_ENUM . IAM , init_request_sdk , { https_port : https_port_iam } ) ;
202
+ await start_endpoint_server_and_cert ( SERVICES_TYPES_ENUM . STS , init_request_sdk , { https_port : https_port_sts , virtual_hosts } ) ;
203
+ await start_endpoint_server_and_cert ( SERVICES_TYPES_ENUM . IAM , init_request_sdk , { https_port : https_port_iam } ) ;
207
204
208
205
209
206
// START METRICS SERVER
210
- if ( metrics_port > 0 && cluster . isPrimary ) {
211
- dbg . log0 ( 'Starting metrics server' , metrics_port ) ;
212
- await prom_reporting . start_server ( metrics_port , false ) ;
213
- dbg . log0 ( 'Started metrics server successfully' ) ;
207
+ if ( ( http_metrics_port > 0 || https_metrics_port > 0 ) && cluster . isPrimary ) {
208
+ await prom_reporting . start_server ( http_metrics_port , https_metrics_port , false , options . nsfs_config_root ) ;
214
209
}
215
210
216
211
// TODO: currently NC NSFS deployments don't have internal_rpc_client nor db,
@@ -249,40 +244,26 @@ async function main(options = {}) {
249
244
}
250
245
251
246
/**
252
- * start_server_and_cert starts the server by type and options and creates a certificate if required
247
+ * start_endpoint_server_and_cert starts the server by type and options and creates a certificate if required
253
248
* @param {('S3'|'IAM'|'STS') } server_type
254
249
* @param {EndpointHandler } init_request_sdk
255
250
* @param {{ http_port?: number, https_port?: number, virtual_hosts?: readonly string[],
256
251
* bucket_logger?: PersistentLogger, notification_logger?: PersistentLogger,
257
252
* nsfs_config_root?: string}} options
258
253
*/
259
- async function start_server_and_cert ( server_type , init_request_sdk , options = { } ) {
254
+ async function start_endpoint_server_and_cert ( server_type , init_request_sdk , options = { } ) {
260
255
const { http_port, https_port, nsfs_config_root } = options ;
261
256
const endpoint_request_handler = create_endpoint_handler ( server_type , init_request_sdk , options ) ;
262
257
263
258
if ( server_type === SERVICES_TYPES_ENUM . S3 ) {
264
259
if ( nsfs_config_root && ! config . ALLOW_HTTP ) {
265
260
dbg . warn ( 'HTTP is not allowed for NC NSFS.' ) ;
266
261
} else {
267
- const http_server = http . createServer ( endpoint_request_handler ) ;
268
- if ( http_port > 0 ) {
269
- dbg . log0 ( `Starting ${ server_type } HTTP - ${ http_port } ` ) ;
270
- await listen_http ( http_port , http_server ) ;
271
- dbg . log0 ( `Started ${ server_type } HTTP successfully` ) ;
272
- }
262
+ await http_utils . start_http_server ( http_port , server_type , endpoint_request_handler ) ;
273
263
}
274
264
}
275
265
if ( https_port > 0 ) {
276
- const ssl_cert_info = await ssl_utils . get_ssl_cert_info ( server_type , nsfs_config_root ) ;
277
- const https_server = await create_https_server ( ssl_cert_info , true , endpoint_request_handler ) ;
278
- ssl_cert_info . on ( 'update' , updated_ssl_cert_info => {
279
- dbg . log0 ( `Setting updated ${ server_type } ssl certs for endpoint.` ) ;
280
- const updated_ssl_options = { ...updated_ssl_cert_info . cert , honorCipherOrder : true } ;
281
- https_server . setSecureContext ( updated_ssl_options ) ;
282
- } ) ;
283
- dbg . log0 ( `Starting ${ server_type } HTTPS - ${ https_port } ` ) ;
284
- await listen_http ( https_port , https_server ) ;
285
- dbg . log0 ( `Started ${ server_type } HTTPS successfully` ) ;
266
+ await http_utils . start_https_server ( https_port , server_type , endpoint_request_handler , nsfs_config_root ) ;
286
267
}
287
268
}
288
269
@@ -506,68 +487,6 @@ function unavailable_handler(req, res) {
506
487
res . end ( reply ) ;
507
488
}
508
489
509
- function listen_http ( port , server ) {
510
- return new Promise ( ( resolve , reject ) => {
511
- setup_http_server ( server ) ;
512
- server . listen ( port , err => {
513
- if ( err ) {
514
- dbg . error ( 'ENDPOINT FAILED to listen' , err ) ;
515
- reject ( err ) ;
516
- } else {
517
- resolve ( ) ;
518
- }
519
- } ) ;
520
- } ) ;
521
- }
522
-
523
- function setup_http_server ( server ) {
524
- // Handle 'Expect' header different than 100-continue to conform with AWS.
525
- // Consider any expect value as if the client is expecting 100-continue.
526
- // See https://github.com/ceph/s3-tests/blob/master/s3tests/functional/test_headers.py:
527
- // - test_object_create_bad_expect_mismatch()
528
- // - test_object_create_bad_expect_empty()
529
- // - test_object_create_bad_expect_none()
530
- // - test_object_create_bad_expect_unreadable()
531
- // See https://nodejs.org/api/http.html#http_event_checkexpectation
532
- server . on ( 'checkExpectation' , function on_s3_check_expectation ( req , res ) {
533
- res . writeContinue ( ) ;
534
- server . emit ( 'request' , req , res ) ;
535
- } ) ;
536
-
537
- // See https://nodejs.org/api/http.html#http_event_clienterror
538
- server . on ( 'clientError' , function on_s3_client_error ( err , socket ) {
539
-
540
- // On parsing errors we reply 400 Bad Request to conform with AWS
541
- // These errors come from the nodejs native http parser.
542
- if ( typeof err . code === 'string' &&
543
- err . code . startsWith ( 'HPE_INVALID_' ) &&
544
- err . bytesParsed > 0 ) {
545
- console . error ( 'ENDPOINT CLIENT ERROR - REPLY WITH BAD REQUEST' , err ) ;
546
- socket . write ( 'HTTP/1.1 400 Bad Request\r\n' ) ;
547
- socket . write ( `Date: ${ new Date ( ) . toUTCString ( ) } \r\n` ) ;
548
- socket . write ( 'Connection: close\r\n' ) ;
549
- socket . write ( 'Content-Length: 0\r\n' ) ;
550
- socket . end ( '\r\n' ) ;
551
- }
552
-
553
- // in any case we destroy the socket
554
- socket . destroy ( ) ;
555
- } ) ;
556
-
557
- server . keepAliveTimeout = config . ENDPOINT_HTTP_SERVER_KEEPALIVE_TIMEOUT ;
558
- server . requestTimeout = config . ENDPOINT_HTTP_SERVER_REQUEST_TIMEOUT ;
559
- server . maxRequestsPerSocket = config . ENDPOINT_HTTP_MAX_REQUESTS_PER_SOCKET ;
560
-
561
- server . on ( 'error' , handle_server_error ) ;
562
-
563
- // This was an attempt to read from the socket in large chunks,
564
- // but it seems like it has no effect and we still get small chunks
565
- // server.on('connection', function on_s3_connection(socket) {
566
- // socket._readableState.highWaterMark = 1024 * 1024;
567
- // socket.setNoDelay(true);
568
- // });
569
- }
570
-
571
490
exports . main = main ;
572
491
exports . create_endpoint_handler = create_endpoint_handler ;
573
492
exports . create_init_request_sdk = create_init_request_sdk ;
0 commit comments