Skip to content

node:http: IncomingMessage.headers is undefined (rawHeaders works) — breaks Hono/Express adapters #3272

Closed

Description

@proggeramlug

Summary

On a node:http server, IncomingMessage.headers is undefined in a Perry-compiled binary, although req.method and req.url are correct and req.rawHeaders is fully populated. This breaks every HTTP framework that reads req.headers (Hono/Express adapters, cookie/auth parsing, host resolution).

Repro

import { createServer } from 'node:http';
const server = createServer((req, res) => {
  let out = '';
  out += 'typeof req.headers = ' + (typeof req.headers) + '\n';     // undefined
  out += 'req.method = ' + req.method + '\n';                        // GET  ✅
  out += 'req.url = ' + req.url + '\n';                              // /probe ✅
  out += 'typeof req.rawHeaders = ' + (typeof req.rawHeaders) + '\n';// object ✅
  out += 'rawHeaders = ' + JSON.stringify(req.rawHeaders) + '\n';    // ["host","127.0.0.1:3138","user-agent",...] ✅
  res.end(out);
});
server.listen(3138, '127.0.0.1', () => console.log('listening'));
$ curl -s -H 'X-Test: hi' http://127.0.0.1:3138/probe
typeof req.headers = undefined
req.method = GET
req.url = /probe
typeof req.rawHeaders = object
rawHeaders = ["host","127.0.0.1:3138","user-agent","curl/8.7.1","accept","*/*","x-test","hi"]

Expected

req.headers should be a lowercased-key object (Node semantics), e.g. { host: "127.0.0.1:3138", "user-agent": "curl/8.7.1", accept: "*/*", "x-test": "hi" }.

Workaround

Rebuild from req.rawHeaders (the flat [k,v,k,v,…] array), which is correct. But most third-party adapters read req.headers directly, so they break out of the box.

Environment

Perry 0.5.1039 (origin/main e824b66 + local fix for the unrelated querystring duplicate-fn build break), macOS arm64. node:http server via libperry_ext_http.

Activity

  1. andrewtdiz commented on May 31, 2026

    @andrewtdiz
    Contributor

    I'm taking this in a focused node:http IncomingMessage body/header semantics PR with #3272, #3273, and #3416. Scope: server request headers, request data chunk shape, and client response setEncoding decoded chunks.

  2. andrewtdiz commented on May 31, 2026

    @andrewtdiz
    Contributor

    Opened PR #3525 for this IncomingMessage cluster.\n\nVerification: focused http/incoming-message parity passes 2/2 (report test-parity/reports/parity_report_20260531_050116.json); broad http parity passes 9/10 with only the existing http/server/upgrade-websocket mismatch remaining (report test-parity/reports/parity_report_20260531_050245.json); affected cargo check and hygiene checks pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions