or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

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

0

# HTTP Parser JS

1

2

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.

3

4

## Package Information

5

6

- **Package Name**: http-parser-js

7

- **Package Type**: npm

8

- **Language**: JavaScript with TypeScript definitions

9

- **Installation**: `npm install http-parser-js`

10

11

## Core Imports

12

13

```javascript

14

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

15

```

16

17

For accessing the methods array:

18

19

```javascript

20

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

21

```

22

23

## Basic Usage

24

25

### Monkey-patching Node.js HTTP Parser

26

27

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

28

29

```javascript

30

// Monkey patch before requiring http for the first time

31

process.binding('http_parser').HTTPParser = require('http-parser-js').HTTPParser;

32

33

const http = require('http');

34

// Now Node.js will use the JavaScript parser

35

```

36

37

### Standalone Usage

38

39

```javascript

40

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

41

42

// Parse an HTTP request

43

const parser = new HTTPParser(HTTPParser.REQUEST);

44

let requestData = {};

45

46

parser[HTTPParser.kOnHeadersComplete] = function(req) {

47

requestData.method = HTTPParser.methods[req.method];

48

requestData.url = req.url;

49

requestData.headers = req.headers;

50

requestData.versionMajor = req.versionMajor;

51

requestData.versionMinor = req.versionMinor;

52

};

53

54

parser[HTTPParser.kOnBody] = function(chunk, offset, length) {

55

console.log('Body chunk:', chunk.slice(offset, offset + length));

56

};

57

58

parser[HTTPParser.kOnMessageComplete] = function() {

59

console.log('Parsing complete');

60

};

61

62

// Execute parsing

63

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

64

parser.execute(httpMessage);

65

parser.finish();

66

```

67

68

## Architecture

69

70

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

71

72

- **HTTPParser Class**: Main parser that handles both REQUEST and RESPONSE parsing modes

73

- **Event-Driven Architecture**: Uses callback functions for different parsing events (headers, body, completion)

74

- **State Machine**: Internal state management for parsing different parts of HTTP messages

75

- **Compatibility Layer**: Maintains API compatibility with Node.js's native http_parser

76

- **Error Tolerant**: More lenient parsing compared to strict HTTP specification compliance

77

78

## Capabilities

79

80

### HTTPParser Constructor

81

82

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

83

84

```javascript { .api }

85

/**

86

* Creates a new HTTP parser instance

87

* @param {string} [type] - Parser type: HTTPParser.REQUEST or HTTPParser.RESPONSE

88

*/

89

function HTTPParser(type) {}

90

91

// Static constants

92

HTTPParser.REQUEST = 'REQUEST';

93

HTTPParser.RESPONSE = 'RESPONSE';

94

HTTPParser.encoding = 'ascii';

95

HTTPParser.maxHeaderSize = 81920; // 80KB default

96

97

// Event constants

98

HTTPParser.kOnHeaders = 1;

99

HTTPParser.kOnHeadersComplete = 2;

100

HTTPParser.kOnBody = 3;

101

HTTPParser.kOnMessageComplete = 4;

102

```

103

104

### Parser Initialization

105

106

Initialize or reinitialize the parser with a specific type.

107

108

```javascript { .api }

109

/**

110

* Initialize parser with type and optional async resource

111

* @param {string} type - HTTPParser.REQUEST or HTTPParser.RESPONSE

112

* @param {*} [async_resource] - Optional async resource for tracking

113

*/

114

initialize(type, async_resource) {}

115

116

/**

117

* Reinitialize parser (alias to constructor)

118

*/

119

reinitialize(type) {}

120

```

121

122

### HTTP Message Parsing

123

124

Execute parsing on HTTP data and signal completion.

125

126

```javascript { .api }

127

/**

128

* Parse HTTP data from buffer

129

* @param {Buffer} chunk - Buffer containing HTTP data

130

* @param {number} [start=0] - Start offset in buffer

131

* @param {number} [length] - Length to parse, defaults to chunk.length

132

* @returns {number|Error} Number of bytes parsed or Error object on failure

133

*/

134

execute(chunk, start, length) {}

135

136

/**

137

* Signal end of HTTP message

138

* @returns {void|Error} Error object if called in invalid state

139

*/

140

finish() {}

141

```

142

143

### Event Handlers

144

145

Set callback functions for parsing events.

146

147

```javascript { .api }

148

// Event handler properties (assign functions to these)

149

parser[HTTPParser.kOnHeaders] = function(headers, url) {

150

// Called for trailer headers in chunked encoding

151

};

152

153

parser[HTTPParser.kOnHeadersComplete] = function(info) {

154

// Called when all headers are parsed

155

// info contains: versionMajor, versionMinor, headers, method, url,

156

// statusCode, statusMessage, upgrade, shouldKeepAlive

157

};

158

159

parser[HTTPParser.kOnBody] = function(chunk, offset, length) {

160

// Called for each body data chunk

161

};

162

163

parser[HTTPParser.kOnMessageComplete] = function() {

164

// Called when entire HTTP message is parsed

165

};

166

```

167

168

### Header and Connection Analysis

169

170

Utilities for analyzing parsed HTTP data.

171

172

```javascript { .api }

173

/**

174

* Parse individual header line

175

* @param {string} line - Header line to parse

176

* @param {string[]} headers - Array to append parsed header to

177

*/

178

parseHeader(line, headers) {}

179

180

/**

181

* Check if connection should be kept alive

182

* @returns {boolean} True if connection should persist

183

*/

184

shouldKeepAlive() {}

185

186

/**

187

* Complete current message and prepare for next request

188

*/

189

nextRequest() {}

190

191

/**

192

* Consume a line from the input buffer (internal method)

193

* @returns {string|void} Parsed line or undefined if incomplete

194

*/

195

consumeLine() {}

196

```

197

198

### Instance Properties and Configuration

199

200

Parser configuration and state properties.

201

202

```javascript { .api }

203

// Instance properties

204

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

205

206

// Compatibility stub methods (no-ops)

207

parser.close = function() {};

208

parser.pause = function() {};

209

parser.resume = function() {};

210

parser.remove = function() {};

211

parser.free = function() {};

212

parser.consume = function() {};

213

parser.unconsume = function() {};

214

parser.getCurrentBuffer = function() {};

215

parser.getAsyncId = function() { return 0; };

216

```

217

218

### HTTP Methods Array

219

220

Array of all supported HTTP methods.

221

222

```javascript { .api }

223

/**

224

* Array of supported HTTP method strings

225

*/

226

const methods = [

227

'DELETE', 'GET', 'HEAD', 'POST', 'PUT', 'CONNECT', 'OPTIONS', 'TRACE',

228

'COPY', 'LOCK', 'MKCOL', 'MOVE', 'PROPFIND', 'PROPPATCH', 'SEARCH', 'UNLOCK',

229

'BIND', 'REBIND', 'UNBIND', 'ACL', 'REPORT', 'MKACTIVITY', 'CHECKOUT', 'MERGE',

230

'M-SEARCH', 'NOTIFY', 'SUBSCRIBE', 'UNSUBSCRIBE', 'PATCH', 'PURGE', 'MKCALENDAR',

231

'LINK', 'UNLINK', 'SOURCE'

232

];

233

234

// Also available as HTTPParser.methods

235

```

236

237

### Error Utilities

238

239

Internal error handling utilities.

240

241

```javascript { .api }

242

/**

243

* Create a standardized parse error with error code

244

* @param {string} code - Error code (HPE_LF_EXPECTED, HPE_INVALID_CONSTANT, etc.)

245

* @returns {Error} Error object with code property

246

*/

247

function parseErrorCode(code) {}

248

```

249

250

### Internal Parsing Methods

251

252

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

253

254

```javascript { .api }

255

/**

256

* Parse HTTP request line (internal state method)

257

*/

258

REQUEST_LINE() {}

259

260

/**

261

* Parse HTTP response line (internal state method)

262

*/

263

RESPONSE_LINE() {}

264

265

/**

266

* Parse header lines (internal state method)

267

* @returns {void|boolean} May return true to indicate upgrade request

268

*/

269

HEADER() {}

270

271

/**

272

* Parse chunked transfer encoding header (internal state method)

273

*/

274

BODY_CHUNKHEAD() {}

275

276

/**

277

* Parse chunked transfer encoding body (internal state method)

278

*/

279

BODY_CHUNK() {}

280

281

/**

282

* Parse empty line after chunk (internal state method)

283

*/

284

BODY_CHUNKEMPTYLINE() {}

285

286

/**

287

* Parse chunked transfer encoding trailers (internal state method)

288

*/

289

BODY_CHUNKTRAILERS() {}

290

291

/**

292

* Parse raw body data (internal state method)

293

*/

294

BODY_RAW() {}

295

296

/**

297

* Parse sized body data (internal state method)

298

*/

299

BODY_SIZED() {}

300

```

301

302

### Legacy Compatibility

303

304

Getter/setter properties for older Node.js versions.

305

306

```javascript { .api }

307

// Legacy callback properties (Node.js < 0.11.6)

308

parser.onHeaders = function(headers, url) {};

309

parser.onHeadersComplete = function(info) {};

310

parser.onBody = function(chunk, offset, length) {};

311

parser.onMessageComplete = function() {};

312

```

313

314

## Types

315

316

```typescript { .api }

317

type ParserType = 'REQUEST' | 'RESPONSE';

318

319

type RequestMethod =

320

| 'DELETE' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'CONNECT' | 'OPTIONS' | 'TRACE'

321

| 'COPY' | 'LOCK' | 'MKCOL' | 'MOVE' | 'PROPFIND' | 'PROPPATCH' | 'SEARCH' | 'UNLOCK'

322

| 'BIND' | 'REBIND' | 'UNBIND' | 'ACL' | 'REPORT' | 'MKACTIVITY' | 'CHECKOUT' | 'MERGE'

323

| 'M-SEARCH' | 'NOTIFY' | 'SUBSCRIBE' | 'UNSUBSCRIBE' | 'PATCH' | 'PURGE' | 'MKCALENDAR'

324

| 'LINK' | 'UNLINK' | 'SOURCE'

325

| string;

326

327

type HeaderObject = Array<string>;

328

329

interface HeaderInfo {

330

versionMajor: number;

331

versionMinor: number;

332

headers: HeaderObject;

333

method: number;

334

url: string;

335

statusCode: number;

336

statusMessage: string;

337

upgrade: boolean;

338

shouldKeepAlive: boolean;

339

}

340

341

type OnHeadersCompleteParser = (info: HeaderInfo) => number | void;

342

type OnBodyParser = (chunk: Buffer, offset: number, length: number) => void;

343

type OnHeadersParser = (headers: string[], url: string) => void;

344

type OnMessageCompleteParser = () => void;

345

346

interface HTTPParserConstructor {

347

new(type?: ParserType): HTTPParser;

348

(type?: ParserType): void;

349

350

readonly REQUEST: 'REQUEST';

351

readonly RESPONSE: 'RESPONSE';

352

readonly methods: RequestMethod[];

353

354

encoding: string;

355

maxHeaderSize: number;

356

357

readonly kOnHeaders: 1;

358

readonly kOnHeadersComplete: 2;

359

readonly kOnBody: 3;

360

readonly kOnMessageComplete: 4;

361

}

362

363

interface HTTPParser {

364

initialize(type: ParserType, async_resource?: unknown): void;

365

execute(chunk: Buffer, start?: number, length?: number): number | Error;

366

finish(): void | Error;

367

368

maxHeaderSize: number;

369

370

[HTTPParser.kOnHeaders]: OnHeadersParser;

371

[HTTPParser.kOnHeadersComplete]: OnHeadersCompleteParser;

372

[HTTPParser.kOnBody]: OnBodyParser;

373

[HTTPParser.kOnMessageComplete]: OnMessageCompleteParser;

374

375

// Legacy compatibility

376

onHeaders: OnHeadersParser;

377

onHeadersComplete: OnHeadersCompleteParser;

378

onBody: OnBodyParser;

379

onMessageComplete: OnMessageCompleteParser;

380

381

// Utility methods

382

parseHeader(line: string, headers: string[]): void;

383

shouldKeepAlive(): boolean;

384

userCall<T>(): (ret?: T) => T;

385

nextRequest(): void;

386

consumeLine(): string | void;

387

388

// Internal properties

389

_compatMode0_11: boolean;

390

391

// Stub methods

392

reinitialize(type: ParserType): void;

393

close(): void;

394

pause(): void;

395

resume(): void;

396

remove(): void;

397

free(): void;

398

consume(): void;

399

unconsume(): void;

400

getCurrentBuffer(): void;

401

getAsyncId(): number;

402

}

403

```

404

405

## Usage Examples

406

407

### Parsing HTTP Request

408

409

```javascript

410

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

411

412

function parseRequest(input) {

413

const parser = new HTTPParser(HTTPParser.REQUEST);

414

let complete = false;

415

let shouldKeepAlive, method, url, headers = [], bodyChunks = [];

416

417

parser[HTTPParser.kOnHeadersComplete] = function(req) {

418

shouldKeepAlive = req.shouldKeepAlive;

419

method = HTTPParser.methods[req.method];

420

url = req.url;

421

headers = req.headers;

422

};

423

424

parser[HTTPParser.kOnBody] = function(chunk, offset, length) {

425

bodyChunks.push(chunk.slice(offset, offset + length));

426

};

427

428

parser[HTTPParser.kOnMessageComplete] = function() {

429

complete = true;

430

};

431

432

parser.execute(input);

433

parser.finish();

434

435

if (!complete) {

436

throw new Error('Could not parse request');

437

}

438

439

return {

440

shouldKeepAlive,

441

method,

442

url,

443

headers,

444

body: Buffer.concat(bodyChunks)

445

};

446

}

447

448

// Usage

449

const request = Buffer.from('GET /path HTTP/1.1\\r\\nHost: example.com\\r\\n\\r\\n');

450

const parsed = parseRequest(request);

451

console.log(parsed.method); // 'GET'

452

console.log(parsed.url); // '/path'

453

```

454

455

### Parsing HTTP Response

456

457

```javascript

458

function parseResponse(input) {

459

const parser = new HTTPParser(HTTPParser.RESPONSE);

460

let complete = false;

461

let statusCode, statusMessage, headers = [], bodyChunks = [];

462

463

parser[HTTPParser.kOnHeadersComplete] = function(res) {

464

statusCode = res.statusCode;

465

statusMessage = res.statusMessage;

466

headers = res.headers;

467

};

468

469

parser[HTTPParser.kOnBody] = function(chunk, offset, length) {

470

bodyChunks.push(chunk.slice(offset, offset + length));

471

};

472

473

parser[HTTPParser.kOnMessageComplete] = function() {

474

complete = true;

475

};

476

477

parser.execute(input);

478

parser.finish();

479

480

return {

481

statusCode,

482

statusMessage,

483

headers,

484

body: Buffer.concat(bodyChunks)

485

};

486

}

487

488

// Usage

489

const response = Buffer.from('HTTP/1.1 200 OK\\r\\nContent-Length: 5\\r\\n\\r\\nHello');

490

const parsed = parseResponse(response);

491

console.log(parsed.statusCode); // 200

492

console.log(parsed.statusMessage); // 'OK'

493

console.log(parsed.body.toString()); // 'Hello'

494

```

495

496

## Error Handling

497

498

The parser returns Error objects for various parsing failures:

499

500

```javascript

501

const result = parser.execute(malformedData);

502

if (result instanceof Error) {

503

console.error('Parse error:', result.message);

504

if (result.code) {

505

console.error('Error code:', result.code);

506

}

507

}

508

509

// Common error codes

510

// HPE_LF_EXPECTED - Line feed expected

511

// HPE_INVALID_CONSTANT - Invalid HTTP constant

512

// HPE_UNEXPECTED_CONTENT_LENGTH - Duplicate/conflicting Content-Length headers

513

```

514

515

## Compatibility Notes

516

517

- **Node.js Support**: Works with Node.js v6-v11, v13-v14 via monkey-patching

518

- **Node.js v12**: Requires `--http-parser=legacy` flag for monkey-patching

519

- **Tolerant Parsing**: More lenient than Node's strict parser for malformed HTTP data

520

- **Header Size Limits**: Configurable via `maxHeaderSize` property (default 80KB)

521

- **Chunked Transfer Encoding**: Full support including trailer headers

522

- **Connection Management**: Automatic keep-alive detection based on HTTP version and headers