Skip to content

fix: RFC 2183 compliant Content-Disposition header in /view endpoint#13080

Open
TJUEZ wants to merge 1 commit intoComfy-Org:masterfrom
TJUEZ:fix/content-disposition-rfc2183
Open

fix: RFC 2183 compliant Content-Disposition header in /view endpoint#13080
TJUEZ wants to merge 1 commit intoComfy-Org:masterfrom
TJUEZ:fix/content-disposition-rfc2183

Conversation

@TJUEZ
Copy link

@TJUEZ TJUEZ commented Mar 20, 2026

Fix: RFC 2183 compliant Content-Disposition header

Issue

Fixes #8914

Problem

The Content-Disposition header set by the /view endpoint was not RFC 2183 compliant:

  • Before: Content-Disposition: filename="name.ext"
  • After: Content-Disposition: attachment; filename="name.ext"

This caused issues with third-party libraries (e.g., Go's mime.ParseMediaType) that properly validate RFC 2183 headers.

Changes

Modified server.py to use RFC 2183 compliant format in 4 places within the view_image function:

  1. Preview image response (line ~558)
  2. RGB channel image response (line ~578)
  3. Alpha channel image response (line ~595)
  4. FileResponse for general files (line ~612)

Testing

Added tests/test_view_content_disposition.py with tests that verify:

  • The /view endpoint returns RFC 2183 compliant Content-Disposition headers
  • Works correctly with subfolder parameter

Note: Tests require the full ComfyUI environment (torch, etc.) to run. They validate that the header format is exactly attachment; filename="<filename>".

Checklist

  • Code changes follow the project style
  • Tests added/updated
  • Documentation updated if needed
  • No breaking changes

Fixes the Content-Disposition header format in the view_image function
to comply with RFC 2183. Previously used 'filename="name.ext"' which
is not RFC 2183 compliant. Now uses 'attachment; filename="name.ext"'.

Fixes Comfy-Org#8914
@coderabbitai
Copy link

coderabbitai bot commented Mar 20, 2026

📝 Walkthrough

Walkthrough

This pull request modifies the Content-Disposition response header in the view_image function to prepend attachment; to the existing filename="<name>" format across all image response variants. A new integration test module is added to validate this header change by spinning up a local server, creating a test PNG fixture, issuing HTTP GET requests to the /view endpoint with query parameters, and asserting that the returned header conforms to RFC 2183-style attachment formatting.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding RFC 2183 compliance to the Content-Disposition header in the /view endpoint, which matches the core objective of the changeset.
Description check ✅ Passed The description is directly related to the changeset, detailing the specific changes made to server.py and tests, referencing issue #8914, and explaining the RFC 2183 compliance fix with before/after examples.
Linked Issues check ✅ Passed The changeset successfully addresses all coding objectives from issue #8914: modifies server.py to emit RFC 2183 compliant Content-Disposition headers in four locations within view_image, and adds comprehensive tests verifying the header format matches attachment; filename="".
Out of Scope Changes check ✅ Passed All code changes are directly scoped to resolving the RFC 2183 compliance issue: server.py modifications update Content-Disposition headers as required, and new test file validates the fix without introducing unrelated changes.

✏️ 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 and usage tips.

Tip

CodeRabbit can approve the review once all CodeRabbit's comments are resolved.

Enable the reviews.request_changes_workflow setting to automatically approve the review once all CodeRabbit's comments are resolved.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/test_view_content_disposition.py (1)

91-151: Test coverage misses 3 changed /view branches (preview, channel=rgb, channel=a).

Since this PR updates Content-Disposition in four branches, consider extending this suite to assert the same header format for each variant.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_view_content_disposition.py` around lines 91 - 151, Add assertions
covering the other /view code paths that were changed: call the /view endpoint
with params that exercise preview mode (params include "preview": "true") and
with channel set to "rgb" and "a" (params include "channel": "rgb" and
"channel": "a"), and for each response assert status_code == 200 and that the
Content-Disposition header equals attachment; filename="<filename>" (same
expected_prefix logic used in test_view_content_disposition_is_attachment_format
and test_view_with_subfolder_content_disposition). Place these new assertions as
additional test cases (or extend the existing tests) so the branches exercised
by preview, channel=rgb, and channel=a verify RFC 2183 compliant
Content-Disposition.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/test_view_content_disposition.py`:
- Around line 63-77: The client fixture retries GET /system_stats but currently
returns the session even if no attempt returned HTTP 200 (only ConnectionError
triggers raise); update the logic in client to fail fast when readiness never
reaches 200 by keeping track of the last response (resp) or a success flag
inside the retry loop and after the loop raise an exception (or call
pytest.fail) if no resp.status_code == 200 was observed; reference the client
function, n_tries, resp, session and the requests.exceptions.ConnectionError
handling so the test stops early with a clear error instead of returning a
session.

---

Nitpick comments:
In `@tests/test_view_content_disposition.py`:
- Around line 91-151: Add assertions covering the other /view code paths that
were changed: call the /view endpoint with params that exercise preview mode
(params include "preview": "true") and with channel set to "rgb" and "a" (params
include "channel": "rgb" and "channel": "a"), and for each response assert
status_code == 200 and that the Content-Disposition header equals attachment;
filename="<filename>" (same expected_prefix logic used in
test_view_content_disposition_is_attachment_format and
test_view_with_subfolder_content_disposition). Place these new assertions as
additional test cases (or extend the existing tests) so the branches exercised
by preview, channel=rgb, and channel=a verify RFC 2183 compliant
Content-Disposition.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c60a67f4-e99e-4b2a-bdc9-a68ffaded75d

📥 Commits

Reviewing files that changed from the base of the PR and between c646d21 and 1f8a74b.

📒 Files selected for processing (2)
  • server.py
  • tests/test_view_content_disposition.py

Comment on lines +63 to +77
def client(self, server_url, _server):
"""Create HTTP client with retry."""
import requests
session = requests.Session()
n_tries = 10
for i in range(n_tries):
time.sleep(2)
try:
resp = session.get(f"{server_url}/system_stats", timeout=5)
if resp.status_code == 200:
break
except requests.exceptions.ConnectionError:
if i == n_tries - 1:
raise
return session
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fail fast when server readiness never reaches 200.

If no attempt gets HTTP 200 (but no ConnectionError is thrown), the fixture still returns a session and tests fail later with less-clear errors.

Proposed fix
 `@pytest.fixture`(scope="class")
 def client(self, server_url, _server):
     """Create HTTP client with retry."""
     import requests
     session = requests.Session()
     n_tries = 10
     for i in range(n_tries):
         time.sleep(2)
         try:
             resp = session.get(f"{server_url}/system_stats", timeout=5)
             if resp.status_code == 200:
                 break
         except requests.exceptions.ConnectionError:
             if i == n_tries - 1:
+                session.close()
                 raise
-    return session
+    else:
+        session.close()
+        pytest.fail(f"Server at {server_url} did not become ready after {n_tries} attempts")
+
+    try:
+        yield session
+    finally:
+        session.close()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_view_content_disposition.py` around lines 63 - 77, The client
fixture retries GET /system_stats but currently returns the session even if no
attempt returned HTTP 200 (only ConnectionError triggers raise); update the
logic in client to fail fast when readiness never reaches 200 by keeping track
of the last response (resp) or a success flag inside the retry loop and after
the loop raise an exception (or call pytest.fail) if no resp.status_code == 200
was observed; reference the client function, n_tries, resp, session and the
requests.exceptions.ConnectionError handling so the test stops early with a
clear error instead of returning a session.

@isaac-mcfadyen
Copy link

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.

"Content-Disposition" Header set in view_image function not matching RFC2183 rules

2 participants