From 491372b82763830485d883e0bf56883c57bc80e6 Mon Sep 17 00:00:00 2001 From: andygoodluck Date: Sat, 14 Feb 2026 09:49:34 +0800 Subject: [PATCH] fix: Make Content-Disposition header RFC 2183 compliant Changes all Content-Disposition headers from: filename="name.ext" to: attachment; filename="name.ext" This ensures compatibility with RFC 2183 and allows third-party downloading libraries (e.g., Go's mime.ParseMediaType) to correctly parse the filename. Fixes #8914 --- server.py | 8 ++++---- test_rfc2183_fix.py | 49 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 test_rfc2183_fix.py diff --git a/server.py b/server.py index 2300393b2..d4f19e7ba 100644 --- a/server.py +++ b/server.py @@ -521,7 +521,7 @@ class PromptServer(): buffer.seek(0) return web.Response(body=buffer.read(), content_type=f'image/{image_format}', - headers={"Content-Disposition": f"filename=\"{filename}\""}) + headers={"Content-Disposition": f"attachment; filename=\"{filename}\""}) if 'channel' not in request.rel_url.query: channel = 'rgba' @@ -541,7 +541,7 @@ class PromptServer(): buffer.seek(0) return web.Response(body=buffer.read(), content_type='image/png', - headers={"Content-Disposition": f"filename=\"{filename}\""}) + headers={"Content-Disposition": f"attachment; filename=\"{filename}\""}) elif channel == 'a': with Image.open(file) as img: @@ -558,7 +558,7 @@ class PromptServer(): alpha_buffer.seek(0) return web.Response(body=alpha_buffer.read(), content_type='image/png', - headers={"Content-Disposition": f"filename=\"{filename}\""}) + headers={"Content-Disposition": f"attachment; filename=\"{filename}\""}) else: # Get content type from mimetype, defaulting to 'application/octet-stream' content_type = mimetypes.guess_type(filename)[0] or 'application/octet-stream' @@ -570,7 +570,7 @@ class PromptServer(): return web.FileResponse( file, headers={ - "Content-Disposition": f"filename=\"{filename}\"", + "Content-Disposition": f"attachment; filename=\"{filename}\"", "Content-Type": content_type } ) diff --git a/test_rfc2183_fix.py b/test_rfc2183_fix.py new file mode 100644 index 000000000..89740ce6f --- /dev/null +++ b/test_rfc2183_fix.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +""" +Test for Content-Disposition header fix +Verifies that the header matches RFC 2183 format +""" + +import re + +def test_content_disposition_header(): + """Test that Content-Disposition header is RFC 2183 compliant""" + + # Read the server.py file + with open('server.py', 'r') as f: + content = f.read() + + # Find all Content-Disposition headers + pattern = r'"Content-Disposition":\s*f"([^"]+)"' + matches = re.findall(pattern, content) + + print(f"Found {len(matches)} Content-Disposition headers") + + all_pass = True + for i, match in enumerate(matches, 1): + print(f"\nHeader {i}: {match}") + + # Check RFC 2183 compliance + # Should start with "attachment;" or "inline;" followed by filename + if match.startswith("attachment;") and "filename=" in match: + print(f" ✅ RFC 2183 compliant (attachment disposition)") + elif match.startswith("inline;") and "filename=" in match: + print(f" ✅ RFC 2183 compliant (inline disposition)") + elif match.startswith("filename="): + print(f" ❌ NOT RFC 2183 compliant (missing disposition type)") + all_pass = False + else: + print(f" ⚠️ Unknown format") + + print("\n" + "="*50) + if all_pass: + print("✅ All headers are RFC 2183 compliant!") + else: + print("❌ Some headers are NOT RFC 2183 compliant!") + + return all_pass + +if __name__ == "__main__": + import sys + success = test_content_disposition_header() + sys.exit(0 if success else 1)