11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ciconst http = require('http');
51cb0ef41Sopenharmony_ciconst net = require('net');
61cb0ef41Sopenharmony_ciconst assert = require('assert');
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci// The maximum http chunk extension size is set in `src/node_http_parser.cc`.
91cb0ef41Sopenharmony_ci// These tests assert that once the extension size is reached, an HTTP 413
101cb0ef41Sopenharmony_ci// response is returned.
111cb0ef41Sopenharmony_ci// Currently, the max size is set to 16KiB (16384).
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci// Verify that chunk extensions are limited in size when sent all together.
141cb0ef41Sopenharmony_ci{
151cb0ef41Sopenharmony_ci  const server = http.createServer((req, res) => {
161cb0ef41Sopenharmony_ci    req.on('end', () => {
171cb0ef41Sopenharmony_ci      res.writeHead(200, { 'Content-Type': 'text/plain' });
181cb0ef41Sopenharmony_ci      res.end('bye');
191cb0ef41Sopenharmony_ci    });
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci    req.resume();
221cb0ef41Sopenharmony_ci  });
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci  server.listen(0, () => {
251cb0ef41Sopenharmony_ci    const port = server.address().port;
261cb0ef41Sopenharmony_ci    const sock = net.connect(port);
271cb0ef41Sopenharmony_ci    let data = '';
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci    sock.on('data', (chunk) => data += chunk.toString('utf-8'));
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci    sock.on('end', common.mustCall(function() {
321cb0ef41Sopenharmony_ci      assert.strictEqual(data, 'HTTP/1.1 413 Payload Too Large\r\nConnection: close\r\n\r\n');
331cb0ef41Sopenharmony_ci      server.close();
341cb0ef41Sopenharmony_ci    }));
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci    sock.end('' +
371cb0ef41Sopenharmony_ci      'GET / HTTP/1.1\r\n' +
381cb0ef41Sopenharmony_ci      `Host: localhost:${port}\r\n` +
391cb0ef41Sopenharmony_ci      'Transfer-Encoding: chunked\r\n\r\n' +
401cb0ef41Sopenharmony_ci      '2;' + 'a'.repeat(17000) + '\r\n' + // Chunk size + chunk ext + CRLF
411cb0ef41Sopenharmony_ci      'AA\r\n' + // Chunk data
421cb0ef41Sopenharmony_ci      '0\r\n' + // Last chunk
431cb0ef41Sopenharmony_ci      '\r\n' // End of http message
441cb0ef41Sopenharmony_ci    );
451cb0ef41Sopenharmony_ci  });
461cb0ef41Sopenharmony_ci}
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci// Verify that chunk extensions are limited in size when sent in parts
491cb0ef41Sopenharmony_ci{
501cb0ef41Sopenharmony_ci  const server = http.createServer((req, res) => {
511cb0ef41Sopenharmony_ci    req.on('end', () => {
521cb0ef41Sopenharmony_ci      res.writeHead(200, { 'Content-Type': 'text/plain' });
531cb0ef41Sopenharmony_ci      res.end('bye');
541cb0ef41Sopenharmony_ci    });
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci    req.resume();
571cb0ef41Sopenharmony_ci  });
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  server.listen(0, () => {
601cb0ef41Sopenharmony_ci    const port = server.address().port;
611cb0ef41Sopenharmony_ci    const sock = net.connect(port);
621cb0ef41Sopenharmony_ci    let data = '';
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci    sock.on('data', (chunk) => data += chunk.toString('utf-8'));
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci    sock.on('end', common.mustCall(function() {
671cb0ef41Sopenharmony_ci      assert.strictEqual(data, 'HTTP/1.1 413 Payload Too Large\r\nConnection: close\r\n\r\n');
681cb0ef41Sopenharmony_ci      server.close();
691cb0ef41Sopenharmony_ci    }));
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci    sock.write('' +
721cb0ef41Sopenharmony_ci    'GET / HTTP/1.1\r\n' +
731cb0ef41Sopenharmony_ci    `Host: localhost:${port}\r\n` +
741cb0ef41Sopenharmony_ci    'Transfer-Encoding: chunked\r\n\r\n' +
751cb0ef41Sopenharmony_ci    '2;' // Chunk size + start of chunk-extension
761cb0ef41Sopenharmony_ci    );
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci    sock.write('A'.repeat(8500)); // Write half of the chunk-extension
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci    queueMicrotask(() => {
811cb0ef41Sopenharmony_ci      sock.write('A'.repeat(8500) + '\r\n' + // Remaining half of the chunk-extension
821cb0ef41Sopenharmony_ci      'AA\r\n' + // Chunk data
831cb0ef41Sopenharmony_ci      '0\r\n' + // Last chunk
841cb0ef41Sopenharmony_ci      '\r\n' // End of http message
851cb0ef41Sopenharmony_ci      );
861cb0ef41Sopenharmony_ci    });
871cb0ef41Sopenharmony_ci  });
881cb0ef41Sopenharmony_ci}
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci// Verify the chunk extensions is correctly reset after a chunk
911cb0ef41Sopenharmony_ci{
921cb0ef41Sopenharmony_ci  const server = http.createServer((req, res) => {
931cb0ef41Sopenharmony_ci    req.on('end', () => {
941cb0ef41Sopenharmony_ci      res.writeHead(200, { 'content-type': 'text/plain', 'connection': 'close', 'date': 'now' });
951cb0ef41Sopenharmony_ci      res.end('bye');
961cb0ef41Sopenharmony_ci    });
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci    req.resume();
991cb0ef41Sopenharmony_ci  });
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  server.listen(0, () => {
1021cb0ef41Sopenharmony_ci    const port = server.address().port;
1031cb0ef41Sopenharmony_ci    const sock = net.connect(port);
1041cb0ef41Sopenharmony_ci    let data = '';
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci    sock.on('data', (chunk) => data += chunk.toString('utf-8'));
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci    sock.on('end', common.mustCall(function() {
1091cb0ef41Sopenharmony_ci      assert.strictEqual(
1101cb0ef41Sopenharmony_ci        data,
1111cb0ef41Sopenharmony_ci        'HTTP/1.1 200 OK\r\n' +
1121cb0ef41Sopenharmony_ci        'content-type: text/plain\r\n' +
1131cb0ef41Sopenharmony_ci        'connection: close\r\n' +
1141cb0ef41Sopenharmony_ci        'date: now\r\n' +
1151cb0ef41Sopenharmony_ci        'Transfer-Encoding: chunked\r\n' +
1161cb0ef41Sopenharmony_ci        '\r\n' +
1171cb0ef41Sopenharmony_ci        '3\r\n' +
1181cb0ef41Sopenharmony_ci        'bye\r\n' +
1191cb0ef41Sopenharmony_ci        '0\r\n' +
1201cb0ef41Sopenharmony_ci        '\r\n',
1211cb0ef41Sopenharmony_ci      );
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci      server.close();
1241cb0ef41Sopenharmony_ci    }));
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ci    sock.end('' +
1271cb0ef41Sopenharmony_ci      'GET / HTTP/1.1\r\n' +
1281cb0ef41Sopenharmony_ci      `Host: localhost:${port}\r\n` +
1291cb0ef41Sopenharmony_ci      'Transfer-Encoding: chunked\r\n\r\n' +
1301cb0ef41Sopenharmony_ci      '2;' + 'A'.repeat(10000) + '=bar\r\nAA\r\n' +
1311cb0ef41Sopenharmony_ci      '2;' + 'A'.repeat(10000) + '=bar\r\nAA\r\n' +
1321cb0ef41Sopenharmony_ci      '2;' + 'A'.repeat(10000) + '=bar\r\nAA\r\n' +
1331cb0ef41Sopenharmony_ci      '0\r\n\r\n'
1341cb0ef41Sopenharmony_ci    );
1351cb0ef41Sopenharmony_ci  });
1361cb0ef41Sopenharmony_ci}
137