11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ciconst assert = require('assert');
51cb0ef41Sopenharmony_ciconst { createServer } = require('http');
61cb0ef41Sopenharmony_ciconst { connect } = require('net');
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci// This test validates that the server returns 408
91cb0ef41Sopenharmony_ci// after server.requestTimeout if the client
101cb0ef41Sopenharmony_ci// does not complete a request, and that keep alive
111cb0ef41Sopenharmony_ci// works properly.
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cifunction performRequestWithDelay(client, firstDelay, secondDelay, closeAfter) {
141cb0ef41Sopenharmony_ci  client.resume();
151cb0ef41Sopenharmony_ci  client.write('GET / HTTP/1.1\r\n');
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci  setTimeout(() => {
181cb0ef41Sopenharmony_ci    client.write('Connection: ');
191cb0ef41Sopenharmony_ci  }, firstDelay).unref();
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci  // Complete the request
221cb0ef41Sopenharmony_ci  setTimeout(() => {
231cb0ef41Sopenharmony_ci    client.write(`${closeAfter ? 'close' : 'keep-alive'}\r\n\r\n`);
241cb0ef41Sopenharmony_ci  }, firstDelay + secondDelay).unref();
251cb0ef41Sopenharmony_ci}
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ciconst requestTimeout = common.platformTimeout(5000);
281cb0ef41Sopenharmony_ciconst server = createServer({
291cb0ef41Sopenharmony_ci  headersTimeout: 0,
301cb0ef41Sopenharmony_ci  requestTimeout,
311cb0ef41Sopenharmony_ci  keepAliveTimeout: 0,
321cb0ef41Sopenharmony_ci  connectionsCheckingInterval: requestTimeout / 4
331cb0ef41Sopenharmony_ci}, common.mustCallAtLeast((req, res) => {
341cb0ef41Sopenharmony_ci  res.writeHead(200, { 'Content-Type': 'text/plain' });
351cb0ef41Sopenharmony_ci  res.end();
361cb0ef41Sopenharmony_ci}));
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ciassert.strictEqual(server.requestTimeout, requestTimeout);
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci// Make sure keepAliveTimeout is big enough for the requestTimeout.
411cb0ef41Sopenharmony_ciserver.keepAliveTimeout = 0;
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ciserver.listen(0, common.mustCall(() => {
441cb0ef41Sopenharmony_ci  const client = connect(server.address().port);
451cb0ef41Sopenharmony_ci  let second = false;
461cb0ef41Sopenharmony_ci  let response = '';
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  client.setEncoding('utf8');
491cb0ef41Sopenharmony_ci  client.on('data', common.mustCallAtLeast((chunk) => {
501cb0ef41Sopenharmony_ci    response += chunk;
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci    // First response has ended
531cb0ef41Sopenharmony_ci    if (!second && response.endsWith('\r\n\r\n')) {
541cb0ef41Sopenharmony_ci      assert.strictEqual(
551cb0ef41Sopenharmony_ci        response.split('\r\n')[0],
561cb0ef41Sopenharmony_ci        'HTTP/1.1 200 OK'
571cb0ef41Sopenharmony_ci      );
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci      const defer = requestTimeout * 1.5;
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci      // Wait some time to make sure requestTimeout
621cb0ef41Sopenharmony_ci      // does not interfere with keep alive
631cb0ef41Sopenharmony_ci      setTimeout(() => {
641cb0ef41Sopenharmony_ci        response = '';
651cb0ef41Sopenharmony_ci        second = true;
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci        // Perform a second request expected to finish after requestTimeout
681cb0ef41Sopenharmony_ci        performRequestWithDelay(
691cb0ef41Sopenharmony_ci          client,
701cb0ef41Sopenharmony_ci          requestTimeout / 5,
711cb0ef41Sopenharmony_ci          requestTimeout * 2,
721cb0ef41Sopenharmony_ci          true
731cb0ef41Sopenharmony_ci        );
741cb0ef41Sopenharmony_ci      }, defer).unref();
751cb0ef41Sopenharmony_ci    }
761cb0ef41Sopenharmony_ci  }, 1));
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci  const errOrEnd = common.mustCall(function(err) {
791cb0ef41Sopenharmony_ci    assert.strictEqual(second, true);
801cb0ef41Sopenharmony_ci    assert.strictEqual(
811cb0ef41Sopenharmony_ci      response,
821cb0ef41Sopenharmony_ci      'HTTP/1.1 408 Request Timeout\r\nConnection: close\r\n\r\n'
831cb0ef41Sopenharmony_ci    );
841cb0ef41Sopenharmony_ci    server.close();
851cb0ef41Sopenharmony_ci  });
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  client.on('error', errOrEnd);
881cb0ef41Sopenharmony_ci  client.on('end', errOrEnd);
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  // Perform a first request which is completed immediately
911cb0ef41Sopenharmony_ci  performRequestWithDelay(
921cb0ef41Sopenharmony_ci    client,
931cb0ef41Sopenharmony_ci    requestTimeout / 5,
941cb0ef41Sopenharmony_ci    requestTimeout / 5,
951cb0ef41Sopenharmony_ci    false
961cb0ef41Sopenharmony_ci  );
971cb0ef41Sopenharmony_ci}));
98