or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-http-parser-js

A pure JavaScript HTTP parser for Node.js, compatible replacement for http_parser.c

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/http-parser-js@0.5.x

To install, run

npx @tessl/cli install tessl/npm-http-parser-js@0.5.0

index.mddocs/

HTTP Parser JS

HTTP Parser JS is a pure JavaScript HTTP protocol parser for Node.js that serves as a compatible replacement for the native C++ http_parser.c. It provides more flexible and tolerant parsing of HTTP messages, making it ideal for working with legacy services that don't meet strict HTTP parsing standards.

Package Information

  • Package Name: http-parser-js
  • Package Type: npm
  • Language: JavaScript with TypeScript definitions
  • Installation:
    npm install http-parser-js

Core Imports

const { HTTPParser } = require("http-parser-js");

For accessing the methods array:

const { HTTPParser, methods } = require("http-parser-js");

Basic Usage

Monkey-patching Node.js HTTP Parser

The primary intended use is to replace Node.js's built-in HTTP parser:

// Monkey patch before requiring http for the first time
process.binding('http_parser').HTTPParser = require('http-parser-js').HTTPParser;

const http = require('http');
// Now Node.js will use the JavaScript parser

Standalone Usage

const { HTTPParser } = require('http-parser-js');

// Parse an HTTP request
const parser = new HTTPParser(HTTPParser.REQUEST);
let requestData = {};

parser[HTTPParser.kOnHeadersComplete] = function(req) {
  requestData.method = HTTPParser.methods[req.method];
  requestData.url = req.url;
  requestData.headers = req.headers;
  requestData.versionMajor = req.versionMajor;
  requestData.versionMinor = req.versionMinor;
};

parser[HTTPParser.kOnBody] = function(chunk, offset, length) {
  console.log('Body chunk:', chunk.slice(offset, offset + length));
};

parser[HTTPParser.kOnMessageComplete] = function() {
  console.log('Parsing complete');
};

// Execute parsing
const httpMessage = Buffer.from('GET / HTTP/1.1\\r\\nHost: example.com\\r\\n\\r\\n');
parser.execute(httpMessage);
parser.finish();

Architecture

HTTP Parser JS is designed around a single main class with callback-based event handling:

  • HTTPParser Class: Main parser that handles both REQUEST and RESPONSE parsing modes
  • Event-Driven Architecture: Uses callback functions for different parsing events (headers, body, completion)
  • State Machine: Internal state management for parsing different parts of HTTP messages
  • Compatibility Layer: Maintains API compatibility with Node.js's native http_parser
  • Error Tolerant: More lenient parsing compared to strict HTTP specification compliance

Capabilities

HTTPParser Constructor

Creates a new HTTP parser instance for parsing requests or responses.

/**
 * Creates a new HTTP parser instance
 * @param {string} [type] - Parser type: HTTPParser.REQUEST or HTTPParser.RESPONSE
 */
function HTTPParser(type) {}

// Static constants
HTTPParser.REQUEST = 'REQUEST';
HTTPParser.RESPONSE = 'RESPONSE';
HTTPParser.encoding = 'ascii';
HTTPParser.maxHeaderSize = 81920; // 80KB default

// Event constants
HTTPParser.kOnHeaders = 1;
HTTPParser.kOnHeadersComplete = 2;
HTTPParser.kOnBody = 3;
HTTPParser.kOnMessageComplete = 4;

Parser Initialization

Initialize or reinitialize the parser with a specific type.

/**
 * Initialize parser with type and optional async resource
 * @param {string} type - HTTPParser.REQUEST or HTTPParser.RESPONSE
 * @param {*} [async_resource] - Optional async resource for tracking
 */
initialize(type, async_resource) {}

/**
 * Reinitialize parser (alias to constructor)
 */
reinitialize(type) {}

HTTP Message Parsing

Execute parsing on HTTP data and signal completion.

/**
 * Parse HTTP data from buffer
 * @param {Buffer} chunk - Buffer containing HTTP data
 * @param {number} [start=0] - Start offset in buffer
 * @param {number} [length] - Length to parse, defaults to chunk.length
 * @returns {number|Error} Number of bytes parsed or Error object on failure
 */
execute(chunk, start, length) {}

/**
 * Signal end of HTTP message
 * @returns {void|Error} Error object if called in invalid state
 */
finish() {}

Event Handlers

Set callback functions for parsing events.

// Event handler properties (assign functions to these)
parser[HTTPParser.kOnHeaders] = function(headers, url) {
  // Called for trailer headers in chunked encoding
};

parser[HTTPParser.kOnHeadersComplete] = function(info) {
  // Called when all headers are parsed
  // info contains: versionMajor, versionMinor, headers, method, url, 
  // statusCode, statusMessage, upgrade, shouldKeepAlive
};

parser[HTTPParser.kOnBody] = function(chunk, offset, length) {
  // Called for each body data chunk
};

parser[HTTPParser.kOnMessageComplete] = function() {
  // Called when entire HTTP message is parsed
};

Header and Connection Analysis

Utilities for analyzing parsed HTTP data.

/**
 * Parse individual header line
 * @param {string} line - Header line to parse
 * @param {string[]} headers - Array to append parsed header to
 */
parseHeader(line, headers) {}

/**
 * Check if connection should be kept alive
 * @returns {boolean} True if connection should persist
 */
shouldKeepAlive() {}

/**
 * Complete current message and prepare for next request
 */
nextRequest() {}

/**
 * Consume a line from the input buffer (internal method)
 * @returns {string|void} Parsed line or undefined if incomplete
 */
consumeLine() {}

Instance Properties and Configuration

Parser configuration and state properties.

// Instance properties
parser.maxHeaderSize = 81920; // Max header size in bytes

// Compatibility stub methods (no-ops)
parser.close = function() {};
parser.pause = function() {};
parser.resume = function() {};
parser.remove = function() {};
parser.free = function() {};
parser.consume = function() {};
parser.unconsume = function() {};
parser.getCurrentBuffer = function() {};
parser.getAsyncId = function() { return 0; };

HTTP Methods Array

Array of all supported HTTP methods.

/**
 * Array of supported HTTP method strings
 */
const methods = [
  'DELETE', 'GET', 'HEAD', 'POST', 'PUT', 'CONNECT', 'OPTIONS', 'TRACE',
  'COPY', 'LOCK', 'MKCOL', 'MOVE', 'PROPFIND', 'PROPPATCH', 'SEARCH', 'UNLOCK',
  'BIND', 'REBIND', 'UNBIND', 'ACL', 'REPORT', 'MKACTIVITY', 'CHECKOUT', 'MERGE',
  'M-SEARCH', 'NOTIFY', 'SUBSCRIBE', 'UNSUBSCRIBE', 'PATCH', 'PURGE', 'MKCALENDAR',
  'LINK', 'UNLINK', 'SOURCE'
];

// Also available as HTTPParser.methods

Error Utilities

Internal error handling utilities.

/**
 * Create a standardized parse error with error code
 * @param {string} code - Error code (HPE_LF_EXPECTED, HPE_INVALID_CONSTANT, etc.)
 * @returns {Error} Error object with code property
 */
function parseErrorCode(code) {}

Internal Parsing Methods

Internal state machine methods used during HTTP parsing. These methods are called automatically by the parser and generally should not be called directly.

/**
 * Parse HTTP request line (internal state method)
 */
REQUEST_LINE() {}

/**
 * Parse HTTP response line (internal state method)
 */
RESPONSE_LINE() {}

/**
 * Parse header lines (internal state method)
 * @returns {void|boolean} May return true to indicate upgrade request
 */
HEADER() {}

/**
 * Parse chunked transfer encoding header (internal state method)
 */
BODY_CHUNKHEAD() {}

/**
 * Parse chunked transfer encoding body (internal state method)
 */
BODY_CHUNK() {}

/**
 * Parse empty line after chunk (internal state method)
 */
BODY_CHUNKEMPTYLINE() {}

/**
 * Parse chunked transfer encoding trailers (internal state method)
 */
BODY_CHUNKTRAILERS() {}

/**
 * Parse raw body data (internal state method)
 */
BODY_RAW() {}

/**
 * Parse sized body data (internal state method)
 */
BODY_SIZED() {}

Legacy Compatibility

Getter/setter properties for older Node.js versions.

// Legacy callback properties (Node.js < 0.11.6)
parser.onHeaders = function(headers, url) {};
parser.onHeadersComplete = function(info) {};
parser.onBody = function(chunk, offset, length) {};
parser.onMessageComplete = function() {};

Types

type ParserType = 'REQUEST' | 'RESPONSE';

type RequestMethod = 
  | 'DELETE' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'CONNECT' | 'OPTIONS' | 'TRACE'
  | 'COPY' | 'LOCK' | 'MKCOL' | 'MOVE' | 'PROPFIND' | 'PROPPATCH' | 'SEARCH' | 'UNLOCK'
  | 'BIND' | 'REBIND' | 'UNBIND' | 'ACL' | 'REPORT' | 'MKACTIVITY' | 'CHECKOUT' | 'MERGE'
  | 'M-SEARCH' | 'NOTIFY' | 'SUBSCRIBE' | 'UNSUBSCRIBE' | 'PATCH' | 'PURGE' | 'MKCALENDAR'
  | 'LINK' | 'UNLINK' | 'SOURCE'
  | string;

type HeaderObject = Array<string>;

interface HeaderInfo {
  versionMajor: number;
  versionMinor: number;
  headers: HeaderObject;
  method: number;
  url: string;
  statusCode: number;
  statusMessage: string;
  upgrade: boolean;
  shouldKeepAlive: boolean;
}

type OnHeadersCompleteParser = (info: HeaderInfo) => number | void;
type OnBodyParser = (chunk: Buffer, offset: number, length: number) => void;
type OnHeadersParser = (headers: string[], url: string) => void;
type OnMessageCompleteParser = () => void;

interface HTTPParserConstructor {
  new(type?: ParserType): HTTPParser;
  (type?: ParserType): void;
  
  readonly REQUEST: 'REQUEST';
  readonly RESPONSE: 'RESPONSE';
  readonly methods: RequestMethod[];
  
  encoding: string;
  maxHeaderSize: number;
  
  readonly kOnHeaders: 1;
  readonly kOnHeadersComplete: 2;
  readonly kOnBody: 3;
  readonly kOnMessageComplete: 4;
}

interface HTTPParser {
  initialize(type: ParserType, async_resource?: unknown): void;
  execute(chunk: Buffer, start?: number, length?: number): number | Error;
  finish(): void | Error;
  
  maxHeaderSize: number;
  
  [HTTPParser.kOnHeaders]: OnHeadersParser;
  [HTTPParser.kOnHeadersComplete]: OnHeadersCompleteParser;
  [HTTPParser.kOnBody]: OnBodyParser;
  [HTTPParser.kOnMessageComplete]: OnMessageCompleteParser;
  
  // Legacy compatibility
  onHeaders: OnHeadersParser;
  onHeadersComplete: OnHeadersCompleteParser;
  onBody: OnBodyParser;
  onMessageComplete: OnMessageCompleteParser;
  
  // Utility methods
  parseHeader(line: string, headers: string[]): void;
  shouldKeepAlive(): boolean;
  userCall<T>(): (ret?: T) => T;
  nextRequest(): void;
  consumeLine(): string | void;
  
  // Internal properties
  _compatMode0_11: boolean;
  
  // Stub methods
  reinitialize(type: ParserType): void;
  close(): void;
  pause(): void;
  resume(): void;
  remove(): void;
  free(): void;
  consume(): void;
  unconsume(): void;
  getCurrentBuffer(): void;
  getAsyncId(): number;
}

Usage Examples

Parsing HTTP Request

const { HTTPParser } = require('http-parser-js');

function parseRequest(input) {
  const parser = new HTTPParser(HTTPParser.REQUEST);
  let complete = false;
  let shouldKeepAlive, method, url, headers = [], bodyChunks = [];

  parser[HTTPParser.kOnHeadersComplete] = function(req) {
    shouldKeepAlive = req.shouldKeepAlive;
    method = HTTPParser.methods[req.method];
    url = req.url;
    headers = req.headers;
  };

  parser[HTTPParser.kOnBody] = function(chunk, offset, length) {
    bodyChunks.push(chunk.slice(offset, offset + length));
  };

  parser[HTTPParser.kOnMessageComplete] = function() {
    complete = true;
  };

  parser.execute(input);
  parser.finish();

  if (!complete) {
    throw new Error('Could not parse request');
  }

  return {
    shouldKeepAlive,
    method,
    url,
    headers,
    body: Buffer.concat(bodyChunks)
  };
}

// Usage
const request = Buffer.from('GET /path HTTP/1.1\\r\\nHost: example.com\\r\\n\\r\\n');
const parsed = parseRequest(request);
console.log(parsed.method); // 'GET'
console.log(parsed.url);    // '/path'

Parsing HTTP Response

function parseResponse(input) {
  const parser = new HTTPParser(HTTPParser.RESPONSE);
  let complete = false;
  let statusCode, statusMessage, headers = [], bodyChunks = [];

  parser[HTTPParser.kOnHeadersComplete] = function(res) {
    statusCode = res.statusCode;
    statusMessage = res.statusMessage;
    headers = res.headers;
  };

  parser[HTTPParser.kOnBody] = function(chunk, offset, length) {
    bodyChunks.push(chunk.slice(offset, offset + length));
  };

  parser[HTTPParser.kOnMessageComplete] = function() {
    complete = true;
  };

  parser.execute(input);
  parser.finish();

  return {
    statusCode,
    statusMessage,
    headers,
    body: Buffer.concat(bodyChunks)
  };
}

// Usage
const response = Buffer.from('HTTP/1.1 200 OK\\r\\nContent-Length: 5\\r\\n\\r\\nHello');
const parsed = parseResponse(response);
console.log(parsed.statusCode);    // 200
console.log(parsed.statusMessage); // 'OK'
console.log(parsed.body.toString()); // 'Hello'

Error Handling

The parser returns Error objects for various parsing failures:

const result = parser.execute(malformedData);
if (result instanceof Error) {
  console.error('Parse error:', result.message);
  if (result.code) {
    console.error('Error code:', result.code);
  }
}

// Common error codes
// HPE_LF_EXPECTED - Line feed expected
// HPE_INVALID_CONSTANT - Invalid HTTP constant
// HPE_UNEXPECTED_CONTENT_LENGTH - Duplicate/conflicting Content-Length headers

Compatibility Notes

  • Node.js Support: Works with Node.js v6-v11, v13-v14 via monkey-patching
  • Node.js v12: Requires
    --http-parser=legacy
    flag for monkey-patching
  • Tolerant Parsing: More lenient than Node's strict parser for malformed HTTP data
  • Header Size Limits: Configurable via
    maxHeaderSize
    property (default 80KB)
  • Chunked Transfer Encoding: Full support including trailer headers
  • Connection Management: Automatic keep-alive detection based on HTTP version and headers