Skip to content

fix: enforce Content-Type singleton guard in response.set() object form#1982

Open
JSap0914 wants to merge 1 commit into
koajs:masterfrom
JSap0914:fix/content-type-array-check-object-form
Open

fix: enforce Content-Type singleton guard in response.set() object form#1982
JSap0914 wants to merge 1 commit into
koajs:masterfrom
JSap0914:fix/content-type-array-check-object-form

Conversation

@JSap0914

@JSap0914 JSap0914 commented Jun 23, 2026

Copy link
Copy Markdown

Problem

PR #1899 added an assertion to prevent Content-Type from being set to an array via the string form of response.set():

ctx.set('Content-Type', ['text/html', 'text/plain'])  // throws ✓

However, the same protection was missing in the object form:

ctx.set({ 'Content-Type': ['text/html', 'text/plain'] })  // silently writes array ✗

Node.js allows res.setHeader to accept arrays, so this call succeeds and produces an invalid multi-value Content-Type header, violating RFC 9110 (Content-Type is a singleton header).

Fix

Apply the same assert(!Array.isArray(val), …) check inside the else branch of response.set(), keyed case-insensitively against each header name in the passed object.

Testing

  • New unit tests cover both 'Content-Type' and 'content-type' (case-insensitive) key spellings in the object form.
  • All 442 existing tests pass with no modification.

Closes #1973


AI-assisted contribution (fix derived from manual code audit).

Summary by Sourcery

Enforce Content-Type header singleton behavior when using the object form of response.set().

Bug Fixes:

  • Prevent Content-Type from being set to an array via the object form of response.set(), matching the existing guard on the string form.

Tests:

  • Add tests ensuring response.set(object) throws when Content-Type is provided as an array, including case-insensitive header name variants.

Summary by CodeRabbit

  • Tests

    • Added comprehensive test suite validating Content-Type header assignment restrictions across different header casing formats.
  • Bug Fixes

    • Enhanced Content-Type header validation to prevent multiple values in object-form setter, ensuring consistent behavior.

When ctx.set(field, val) is called with field as an object, the
Content-Type singleton validation introduced in koajs#1899 was bypassed.
Setting ctx.set({ 'Content-Type': ['text/html', 'text/plain'] })
silently wrote an array value for Content-Type, violating the HTTP
spec and circumventing the existing assert.

Apply the same Array.isArray guard in the object-form branch,
checking each header key case-insensitively.

Closes koajs#1973
Copilot AI review requested due to automatic review settings June 23, 2026 12:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 30744067-794b-424b-b089-ecd2b4895dc5

📥 Commits

Reviewing files that changed from the base of the PR and between 52d5e8f and 6e6f353.

📒 Files selected for processing (2)
  • __tests__/response/set.test.js
  • lib/response.js

📝 Walkthrough

Walkthrough

The PR extends the Content-Type singleton enforcement in response.set() to cover the object-form call signature. Previously, passing { 'Content-Type': ['text/html', 'text/plain'] } to ctx.set() would bypass the existing array-value restriction that applied only to the string-form ctx.set('Content-Type', [...]). The object-form branch now iterates its keys and throws the same error (Assign multiple Content-Type for response header is not allowed) when a content-type key maps to an array value. Two new test cases confirm the guard fires for both Content-Type and content-type key casing.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: enforcing Content-Type singleton guard in the object form of response.set().
Linked Issues check ✅ Passed The PR directly addresses issue #1973 by implementing stricter validation for HTTP singleton headers (Content-Type) across all API calling conventions.
Out of Scope Changes check ✅ Passed All changes are in-scope: test file additions verify Content-Type validation, and response.js modifications implement the singleton guard in object form only.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai

sourcery-ai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Reviewer's Guide

Enforces the existing Content-Type singleton guard for response.set() when using the object form and adds tests to ensure case-insensitive behavior.

File-Level Changes

Change Details Files
Enforce Content-Type singleton guard for object-form response.set() and add corresponding tests.
  • Wrap the object-form response.set() header iteration with a case-insensitive check for the Content-Type header and assert that its value is not an array before calling setHeader.
  • Keep existing behavior for all other headers by still delegating directly to res.setHeader for non-Content-Type keys.
  • Add unit tests to verify that response.set() throws when Content-Type is provided as an array in the object form, including lowercase 'content-type' to confirm case-insensitive enforcement.
lib/response.js
__tests__/response/set.test.js

Assessment against linked issues

Issue Objective Addressed Explanation
#1973 Enforce strict validation to prevent setting multiple values for HTTP singleton headers (such as Content-Type) in all response.set() call forms The PR adds an assertion only for the Content-Type header when using the object form of response.set(), complementing an existing check in the string form. It does not add validations for other singleton headers nor establish a general mechanism for all singleton headers, so the broader objective of enforcing singleton semantics for all such headers across all forms is only partially met.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.90%. Comparing base (52d5e8f) to head (6e6f353).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1982   +/-   ##
=======================================
  Coverage   99.90%   99.90%           
=======================================
  Files           9        9           
  Lines        2109     2114    +5     
=======================================
+ Hits         2107     2112    +5     
  Misses          2        2           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] HTTP singleton header validations

2 participants