Skip to content

feat: handle utgoingMessage.prototype._headers, OutgoingMessage.prototype._headerNames depreciation #128

@AugustinMauroy

Description

@AugustinMauroy

Description

Since OutgoingMessage.prototype._headers and OutgoingMessage.prototype._headerNames are deprecated (DEP0066) and have reached End-of-Life status, we should provide a codemod to replace them.

  • The codemod should replace all instances of ._headers with appropriate public methods like .getHeaders(), .getHeader(), .hasHeader(), etc.
  • The codemod should replace all instances of ._headerNames with .getHeaderNames().
  • The codemod should handle different usage patterns (reading, checking existence, iteration, etc.).
  • The codemod should work for both http.ClientRequest and http.ServerResponse objects that extend OutgoingMessage.

Additional Information

Note that OutgoingMessage.prototype._headers and OutgoingMessage.prototype._headerNames were removed in Node.js v24.0.0. These properties were never documented as officially supported APIs and were considered internal implementation details. The modern public API provides better encapsulation and consistency.

The _headers property provided direct access to the internal headers object, while _headerNames provided access to the original casing of header names. The public API methods offer the same functionality in a supported and documented way.

Examples

Case 1: Reading all headers

Before:

const headers = response._headers;
console.log(headers);

After:

const headers = response.getHeaders();
console.log(headers);

Case 2: Reading a specific header

Before:

const contentType = response._headers['content-type'];

After:

const contentType = response.getHeader('content-type');

Case 3: Checking if a header exists

Before:

if ('content-length' in response._headers) {
  // do something
}

After:

if (response.hasHeader('content-length')) {
  // do something
}

Case 4: Getting header names

Before:

const names = response._headerNames;

After:

const names = response.getHeaderNames();

Case 5: Getting raw header names (with original casing)

Before:

const rawNames = response._headerNames;

After:

const rawNames = response.getRawHeaderNames();

Case 6: Iterating over headers

Before:

for (const name in request._headers) {
  console.log(name, request._headers[name]);
}

After:

const headers = request.getHeaders();
for (const name in headers) {
  console.log(name, headers[name]);
}

Case 7: Checking header count

Before:

const headerCount = Object.keys(response._headers).length;

After:

const headerCount = response.getHeaderNames().length;

Case 8: Complex header manipulation

Before:

if (request._headers) {
  const headers = request._headers;
  if (headers['user-agent']) {
    console.log('User agent:', headers['user-agent']);
  }
}

After:

if (request.getHeaderNames().length > 0) {
  const userAgent = request.getHeader('user-agent');
  if (userAgent) {
    console.log('User agent:', userAgent);
  }
}

Case 9: Mixed usage with public and private APIs

Before:

const req = http.request(options);
req.setHeader('Content-Type', 'application/json');
console.log(req._headers);
console.log(req._headerNames);

After:

const req = http.request(options);
req.setHeader('Content-Type', 'application/json');
console.log(req.getHeaders());
console.log(req.getHeaderNames());

Case 10: Conditional header access

Before:

const headers = response._headers || {};
const contentType = headers['content-type'];

After:

const contentType = response.getHeader('content-type');

Refs

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status

    🔖 Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions