mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-01-11 06:40:48 +08:00
fix: Content-Disposition header format to comply with RFC 2183
Fixes #8914 The Content-Disposition header was set to `filename="name.ext"` which doesn't match RFC 2183 specification. This caused third-party libraries (e.g., Go's mime.ParseMediaType) to fail parsing the header. Changed to `inline; filename="name.ext"` format which properly includes the disposition-type as required by RFC 2183.
This commit is contained in:
parent
3a5f239cb6
commit
8595a48795
@ -511,7 +511,7 @@ class PromptServer():
|
|||||||
buffer.seek(0)
|
buffer.seek(0)
|
||||||
|
|
||||||
return web.Response(body=buffer.read(), content_type=f'image/{image_format}',
|
return web.Response(body=buffer.read(), content_type=f'image/{image_format}',
|
||||||
headers={"Content-Disposition": f"filename=\"{filename}\""})
|
headers={"Content-Disposition": f"inline; filename=\"{filename}\""})
|
||||||
|
|
||||||
if 'channel' not in request.rel_url.query:
|
if 'channel' not in request.rel_url.query:
|
||||||
channel = 'rgba'
|
channel = 'rgba'
|
||||||
@ -531,7 +531,7 @@ class PromptServer():
|
|||||||
buffer.seek(0)
|
buffer.seek(0)
|
||||||
|
|
||||||
return web.Response(body=buffer.read(), content_type='image/png',
|
return web.Response(body=buffer.read(), content_type='image/png',
|
||||||
headers={"Content-Disposition": f"filename=\"{filename}\""})
|
headers={"Content-Disposition": f"inline; filename=\"{filename}\""})
|
||||||
|
|
||||||
elif channel == 'a':
|
elif channel == 'a':
|
||||||
with Image.open(file) as img:
|
with Image.open(file) as img:
|
||||||
@ -548,7 +548,7 @@ class PromptServer():
|
|||||||
alpha_buffer.seek(0)
|
alpha_buffer.seek(0)
|
||||||
|
|
||||||
return web.Response(body=alpha_buffer.read(), content_type='image/png',
|
return web.Response(body=alpha_buffer.read(), content_type='image/png',
|
||||||
headers={"Content-Disposition": f"filename=\"{filename}\""})
|
headers={"Content-Disposition": f"inline; filename=\"{filename}\""})
|
||||||
else:
|
else:
|
||||||
# Get content type from mimetype, defaulting to 'application/octet-stream'
|
# Get content type from mimetype, defaulting to 'application/octet-stream'
|
||||||
content_type = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
|
content_type = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
|
||||||
@ -560,7 +560,7 @@ class PromptServer():
|
|||||||
return web.FileResponse(
|
return web.FileResponse(
|
||||||
file,
|
file,
|
||||||
headers={
|
headers={
|
||||||
"Content-Disposition": f"filename=\"{filename}\"",
|
"Content-Disposition": f"inline; filename=\"{filename}\"",
|
||||||
"Content-Type": content_type
|
"Content-Type": content_type
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
75
tests-unit/server_test/test_content_disposition.py
Normal file
75
tests-unit/server_test/test_content_disposition.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
"""Tests for Content-Disposition header format (RFC 2183 compliance)
|
||||||
|
|
||||||
|
Relates to issue #8914: Content-Disposition Header not matching RFC2183 rules
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
class TestContentDispositionHeader:
|
||||||
|
"""Test Content-Disposition header format compliance with RFC 2183."""
|
||||||
|
|
||||||
|
def test_rfc2183_format_with_inline(self):
|
||||||
|
"""Verify inline disposition type format matches RFC 2183."""
|
||||||
|
filename = "test_image.png"
|
||||||
|
header = f'inline; filename="{filename}"'
|
||||||
|
|
||||||
|
# RFC 2183 requires disposition-type followed by parameters
|
||||||
|
# Format: disposition-type ";" disposition-parm
|
||||||
|
pattern = r'^(inline|attachment);\s*filename="[^"]*"$'
|
||||||
|
assert re.match(pattern, header), f"Header '{header}' does not match RFC 2183 format"
|
||||||
|
|
||||||
|
def test_rfc2183_format_with_attachment(self):
|
||||||
|
"""Verify attachment disposition type format matches RFC 2183."""
|
||||||
|
filename = "download.mp4"
|
||||||
|
header = f'attachment; filename="{filename}"'
|
||||||
|
|
||||||
|
pattern = r'^(inline|attachment);\s*filename="[^"]*"$'
|
||||||
|
assert re.match(pattern, header), f"Header '{header}' does not match RFC 2183 format"
|
||||||
|
|
||||||
|
def test_invalid_format_missing_disposition_type(self):
|
||||||
|
"""Verify that format without disposition type is invalid."""
|
||||||
|
filename = "test.jpg"
|
||||||
|
invalid_header = f'filename="{filename}"'
|
||||||
|
|
||||||
|
pattern = r'^(inline|attachment);\s*filename="[^"]*"$'
|
||||||
|
assert not re.match(pattern, invalid_header), \
|
||||||
|
"Header without disposition type should not match RFC 2183 format"
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("filename", [
|
||||||
|
"image.png",
|
||||||
|
"video.mp4",
|
||||||
|
"file with spaces.jpg",
|
||||||
|
"special_chars-123.webp",
|
||||||
|
])
|
||||||
|
def test_various_filenames(self, filename):
|
||||||
|
"""Test RFC 2183 format with various filename patterns."""
|
||||||
|
header = f'inline; filename="{filename}"'
|
||||||
|
|
||||||
|
# Should have disposition type before filename
|
||||||
|
assert header.startswith("inline; ") or header.startswith("attachment; ")
|
||||||
|
assert f'filename="{filename}"' in header
|
||||||
|
|
||||||
|
|
||||||
|
class TestContentDispositionParsing:
|
||||||
|
"""Test that Content-Disposition headers can be parsed by standard libraries."""
|
||||||
|
|
||||||
|
def test_parse_inline_disposition(self):
|
||||||
|
"""Test parsing inline disposition header."""
|
||||||
|
header = 'inline; filename="test.png"'
|
||||||
|
|
||||||
|
# Simple parsing test - split by semicolon
|
||||||
|
parts = [p.strip() for p in header.split(';')]
|
||||||
|
assert parts[0] in ('inline', 'attachment')
|
||||||
|
assert 'filename=' in parts[1]
|
||||||
|
|
||||||
|
def test_extract_filename(self):
|
||||||
|
"""Test extracting filename from header."""
|
||||||
|
filename = "my_image.jpg"
|
||||||
|
header = f'inline; filename="{filename}"'
|
||||||
|
|
||||||
|
# Extract filename using regex
|
||||||
|
match = re.search(r'filename="([^"]*)"', header)
|
||||||
|
assert match is not None
|
||||||
|
assert match.group(1) == filename
|
||||||
Loading…
Reference in New Issue
Block a user