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.headersTimeout if the client
101cb0ef41Sopenharmony_ci// does not send headers before the timeout, and
111cb0ef41Sopenharmony_ci// that keep alive 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 headersTimeout = common.platformTimeout(5000);
281cb0ef41Sopenharmony_ciconst server = createServer({
291cb0ef41Sopenharmony_ci  headersTimeout,
301cb0ef41Sopenharmony_ci  requestTimeout: 0,
311cb0ef41Sopenharmony_ci  keepAliveTimeout: 0,
321cb0ef41Sopenharmony_ci  connectionsCheckingInterval: headersTimeout / 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.headersTimeout, headersTimeout);
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci// Check that timeout event is not triggered
411cb0ef41Sopenharmony_ciserver.once('timeout', common.mustNotCall((socket) => {
421cb0ef41Sopenharmony_ci  socket.destroy();
431cb0ef41Sopenharmony_ci}));
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ciserver.listen(0, common.mustCall(() => {
461cb0ef41Sopenharmony_ci  const client = connect(server.address().port);
471cb0ef41Sopenharmony_ci  let second = false;
481cb0ef41Sopenharmony_ci  let response = '';
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  client.setEncoding('utf8');
511cb0ef41Sopenharmony_ci  client.on('data', common.mustCallAtLeast((chunk) => {
521cb0ef41Sopenharmony_ci    response += chunk;
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci    // First response has ended
551cb0ef41Sopenharmony_ci    if (!second && response.endsWith('\r\n\r\n')) {
561cb0ef41Sopenharmony_ci      assert.strictEqual(
571cb0ef41Sopenharmony_ci        response.split('\r\n')[0],
581cb0ef41Sopenharmony_ci        'HTTP/1.1 200 OK'
591cb0ef41Sopenharmony_ci      );
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci      const defer = headersTimeout * 1.5;
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci      // Wait some time to make sure headersTimeout
641cb0ef41Sopenharmony_ci      // does not interfere with keep alive
651cb0ef41Sopenharmony_ci      setTimeout(() => {
661cb0ef41Sopenharmony_ci        response = '';
671cb0ef41Sopenharmony_ci        second = true;
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci        // Perform a second request expected to finish after headersTimeout
701cb0ef41Sopenharmony_ci        performRequestWithDelay(
711cb0ef41Sopenharmony_ci          client,
721cb0ef41Sopenharmony_ci          headersTimeout / 5,
731cb0ef41Sopenharmony_ci          headersTimeout,
741cb0ef41Sopenharmony_ci          true
751cb0ef41Sopenharmony_ci        );
761cb0ef41Sopenharmony_ci      }, defer).unref();
771cb0ef41Sopenharmony_ci    }
781cb0ef41Sopenharmony_ci  }, 1));
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  const errOrEnd = common.mustCall(function(err) {
811cb0ef41Sopenharmony_ci    assert.strictEqual(second, true);
821cb0ef41Sopenharmony_ci    assert.strictEqual(
831cb0ef41Sopenharmony_ci      response,
841cb0ef41Sopenharmony_ci      'HTTP/1.1 408 Request Timeout\r\nConnection: close\r\n\r\n'
851cb0ef41Sopenharmony_ci    );
861cb0ef41Sopenharmony_ci    server.close();
871cb0ef41Sopenharmony_ci  });
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  client.on('error', errOrEnd);
901cb0ef41Sopenharmony_ci  client.on('end', errOrEnd);
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  // Perform a second request expected to finish before headersTimeout
931cb0ef41Sopenharmony_ci  performRequestWithDelay(
941cb0ef41Sopenharmony_ci    client,
951cb0ef41Sopenharmony_ci    headersTimeout / 5,
961cb0ef41Sopenharmony_ci    headersTimeout / 5,
971cb0ef41Sopenharmony_ci    false
981cb0ef41Sopenharmony_ci  );
991cb0ef41Sopenharmony_ci}));
100