dify - ✅(Solved) Fix plug-in header with the same name is overwritten bug [2 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
langgenius/dify#35722Fetched 2026-05-01 05:53:31
View on GitHub
Comments
1
Participants
2
Timeline
8
Reactions
1
Author
Timeline (top)
cross-referenced ×2labeled ×2closed ×1commented ×1

Fix Action

Fixed

PR fix notes

PR #35724: fix: fix response header overwrite

Description (problem / solution / changelog)

[!IMPORTANT]

  1. Make sure you have read our contribution guidelines
  2. Ensure there is an associated issue and you have been assigned to it
  3. Use the correct syntax to link this PR: Fixes #<issue number>.

Summary

fix #35722 response header is overwrite

Screenshots

BeforeAfter
......

Checklist

  • This change requires a documentation update, included: Dify Document
  • I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.
  • I ran make lint && make type-check (backend) and cd web && pnpm exec vp staged (frontend) to appease the lint gods

Changed files

  • api/core/plugin/utils/http_parser.py (modified, +2/-1)

PR #35726: fix(plugin): preserve multi-value HTTP response headers

Description (problem / solution / changelog)

Summary

Closes #35722. deserialize_response in api/core/plugin/utils/http_parser.py used dict-style assignment (response.headers[name] = value.strip()) on a flask.Response object. Same-named headers — most importantly Set-Cookie, but also any custom multi-value header — were silently overwritten so only the last occurrence survived.

close https://github.com/langgenius/dify/pull/35724

Root cause

The parser splits header_data on \r\n and produces one entry per line, so multiple Set-Cookie lines do reach the loop. The defect is the dict-style assignment in the loop body, which clobbers prior values for duplicate keys. Sibling function deserialize_request already uses headers.add() (line 68), so this is purely a correctness gap in deserialize_response.

Fix

Switch to Headers.add(), but first call response.headers.clear() to drop the defaults Flask injects in Response(...) (Content-Type: text/html; charset=utf-8 and Content-Length). Without clear(), every plugin response would acquire a duplicate Content-Type header.

Changes

  • api/core/plugin/utils/http_parser.py: response.headers.clear() then response.headers.add(name, value) per parsed header
  • api/tests/unit_tests/core/plugin/utils/test_http_parser.py: 3 new tests
    • duplicate Set-Cookie headers preserved
    • duplicate generic headers (X-Custom) preserved
    • default Content-Type not injected when the upstream response had none

Test plan

  • cd api && PYTHONPATH=. python3 -m pytest tests/unit_tests/core/plugin/utils/test_http_parser.py -v → 43/43 pass
  • ruff check and ruff format --check clean (per api/.ruff.toml)
  • No other dict-style headers[...] = assignments in the file (grep confirmed)
  • Verified the only caller (TriggerDispatchResponse.convert_response in core/plugin/entities/request.py) intends to faithfully relay the plugin's response, so dropping Flask's injected default Content-Type is a positive correction, not a regression.

Compliance with HTTP semantics

  • Set-Cookie cannot be comma-merged (RFC 6265 §3), so the Headers.add() approach (one entry per occurrence) is the correct preservation strategy.
  • werkzeug.Headers.items() yields each occurrence individually, so downstream serialize_response continues to round-trip multi-value headers correctly.

Changed files

  • api/core/plugin/utils/http_parser.py (modified, +7/-1)
  • api/tests/unit_tests/core/plugin/utils/test_http_parser.py (modified, +44/-0)
RAW_BUFFERClick to expand / collapse

Self Checks

  • I have read the Contributing Guide and Language Policy.
  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report, otherwise it will be closed.
  • 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

1.14.0

Cloud or Self Hosted

Self Hosted (Docker)

Steps to reproduce

  1. Added 2 headers with the same name to the plugin
  2. Browser intelligence receives one
  3. bug code location api/core/plugin/utils/http_parser.py line 161 response.headers[name] = value.strip()

✔️ Expected Behavior

The header of the same name can be received by the browser

❌ Actual Behavior

plug-in header with the same name is overwritten

extent analysis

TL;DR

The issue can be fixed by modifying the http_parser.py file to handle headers with the same name correctly.

Guidance

  • The problem lies in the line response.headers[name] = value.strip() where the header value is overwritten when a header with the same name is encountered.
  • To fix this, the code should be modified to handle multiple headers with the same name, possibly by storing them in a list or concatenating their values.
  • The http_parser.py file should be updated to reflect this change, specifically at line 161.
  • The fix should ensure that all headers, including those with the same name, are properly received by the browser.

Example

# Example of how to handle multiple headers with the same name
if name in response.headers:
    if not isinstance(response.headers[name], list):
        response.headers[name] = [response.headers[name]]
    response.headers[name].append(value.strip())
else:
    response.headers[name] = value.strip()

Notes

This fix assumes that the http_parser.py file is the correct location for the change and that the issue is indeed caused by the overwrite of header values.

Recommendation

Apply workaround: The provided example code can be used as a temporary workaround to handle multiple headers with the same name until a more permanent fix is implemented.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

dify - ✅(Solved) Fix plug-in header with the same name is overwritten bug [2 pull requests, 1 comments, 2 participants]