-
Notifications
You must be signed in to change notification settings - Fork 0
Demo pr #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Demo pr #11
Conversation
WalkthroughThe pull request introduces a new feature for handling multipart file uploads by allowing additional headers for each file part, excluding "Content-Type". The `MultipartField` class and its constructor are updated to support these headers, and a `ValueError` is raised if "Content-Type" is included. The `FileTypes` type alias is updated to a 4-tuple format. New tests are added to verify the correct handling of headers and ensure constraints are enforced.Changes
Sequence DiagramsequenceDiagram
participant Client
participant MultipartField
participant Tests
Client->>MultipartField: Create with file and headers
MultipartField->>MultipartField: Validate headers
alt Headers include "Content-Type"
MultipartField-->>Client: Raise ValueError
else
MultipartField-->>Client: Accept headers
end
Tests->>MultipartField: Run tests for header handling
MultipartField-->>Tests: Return results
Tests-->>Client: Verify correct behavior
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commits
Files that changed from the base of the PR and between Base and 807cc83 commits: 3Files Selected For Review: 3
- httpx/_multipart.py with diff length 2384.
- httpx/_types.py with diff length 378.
- tests/test_multipart.py with diff length 2099.
Review comments generated: 5
- Review: 1
- LGTM: 4
- Identified issue already discussed: 0
Tips
Chat with Deeployed Bot (@reviewed-deeployed)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@reviewed-deeployedin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
reviewed-deeployed: ignoreanywhere in the PR description to pause further reviews from the bot.
| @pytest.mark.parametrize("content_type", [None, "text/plain"]) | ||
| @pytest.mark.parametrize( | ||
| "headers", | ||
| [ | ||
| {"content-type": "text/plain"}, | ||
| {"Content-Type": "text/plain"}, | ||
| {"CONTENT-TYPE": "text/plain"}, | ||
| ], | ||
| ) | ||
| def test_multipart_headers_include_content_type( | ||
| content_type: typing.Optional[str], headers: typing.Dict[str, str] | ||
| ) -> None: | ||
| """Including contet-type in the multipart headers should not be allowed""" | ||
| client = httpx.Client(transport=httpx.MockTransport(echo_request_content)) | ||
|
|
||
| files = {"file": ("test.txt", b"content", content_type, headers)} | ||
| pat = "Content-Type cannot be included in multipart headers" | ||
| with pytest.raises(ValueError, match=pat): | ||
| client.post("http://127.0.0.1:8000/", files=files) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a typo in the docstring of the test_multipart_headers_include_content_type function. The word "contet-type" should be corrected to "content-type".
"""Including contet-type in the multipart headers should not be allowed"""
+ """Including content-type in the multipart headers should not be allowed"""
atakanserifoglu
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ Conditional approval has been given. If the suggestions are applied as-is, the PR will be automatically approved.
httpx/_multipart.py
Outdated
| content_type = self.content_type.encode() | ||
| parts.extend([b"\r\nContent-Type: ", content_type]) | ||
| for header_name, header_value in self.headers.items(): | ||
| key, val = f"\r\n{header_name}: ".encode(), header_value.encode() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check should be case insensitive to header name
| key, val = f"\r\n{header_name}: ".encode(), header_value.encode() | |
| key, val = f"\r\n{header_name.lower()}: ".encode(), header_value.encode() |
[cond-approve] Suggestions from @atakanserifoglu
atakanserifoglu
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Auto-approved by GitHub App after suggestions from @atakanserifoglu were merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Files Selected For Review: 6
- httpx/_multipart.py with diff length 2393.
- httpx/_types.py with diff length 378.
- tests/test_multipart.py with diff length 2099.
- httpx/_multipart.py with diff length 2393.
- httpx/_types.py with diff length 378.
- tests/test_multipart.py with diff length 2099.
Review comments generated: 12
- Review: 4
- LGTM: 8
- Identified issue already discussed: 0
Tips
Chat with Deeployed Bot (@reviewed-deeployed)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@reviewed-deeployedin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
reviewed-deeployed: ignoreanywhere in the PR description to pause further reviews from the bot.
| @pytest.mark.parametrize("content_type", [None, "text/plain"]) | ||
| @pytest.mark.parametrize( | ||
| "headers", | ||
| [ | ||
| {"content-type": "text/plain"}, | ||
| {"Content-Type": "text/plain"}, | ||
| {"CONTENT-TYPE": "text/plain"}, | ||
| ], | ||
| ) | ||
| def test_multipart_headers_include_content_type( | ||
| content_type: typing.Optional[str], headers: typing.Dict[str, str] | ||
| ) -> None: | ||
| """Including contet-type in the multipart headers should not be allowed""" | ||
| client = httpx.Client(transport=httpx.MockTransport(echo_request_content)) | ||
|
|
||
| files = {"file": ("test.txt", b"content", content_type, headers)} | ||
| pat = "Content-Type cannot be included in multipart headers" | ||
| with pytest.raises(ValueError, match=pat): | ||
| client.post("http://127.0.0.1:8000/", files=files) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a typo in the docstring of the test_multipart_headers_include_content_type function. The word "contet-type" should be corrected to "content-type".
"""Including contet-type in the multipart headers should not be allowed"""
+ """Including content-type in the multipart headers should not be allowed"""| if isinstance(value, tuple): | ||
| try: | ||
| filename, fileobj, content_type = value # type: ignore | ||
| filename, fileobj, content_type, headers = value # type: ignore | ||
| except ValueError: | ||
| filename, fileobj = value # type: ignore | ||
| content_type = guess_content_type(filename) | ||
| try: | ||
| filename, fileobj, content_type = value # type: ignore | ||
| except ValueError: | ||
| filename, fileobj = value # type: ignore | ||
| else: | ||
| headers = {k.title(): v for k, v in headers.items()} | ||
| if "Content-Type" in headers: | ||
| raise ValueError( | ||
| "Content-Type cannot be included in multipart headers" | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for handling the tuple unpacking and the subsequent checks for headers is correct. However, the indentation for the else block seems off. It should align with the try block to ensure proper execution flow.
filename, fileobj, content_type, headers = value # type: ignore
except ValueError:
try:
filename, fileobj, content_type = value # type: ignore
except ValueError:
filename, fileobj = value # type: ignore
else:
headers = {k.title(): v for k, v in headers.items()}
if "Content-Type" in headers:
raise ValueError(
"Content-Type cannot be included in multipart headers"
)| if self.filename: | ||
| filename = format_form_param("filename", self.filename) | ||
| parts.extend([b"; ", filename]) | ||
| if self.content_type is not None: | ||
| content_type = self.content_type.encode() | ||
| parts.extend([b"\r\nContent-Type: ", content_type]) | ||
| for header_name, header_value in self.headers.items(): | ||
| key, val = f"\r\n{header_name.lower()}: ".encode(), header_value.encode() | ||
| parts.extend([key, val]) | ||
| parts.append(b"\r\n\r\n") | ||
| self._headers = b"".join(parts) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The conversion of header names to lowercase before encoding is correct, but it might be more efficient to perform this operation once when setting the headers, rather than during each call to this method. Consider adjusting the logic to handle this earlier in the process.
for header_name, header_value in self.headers.items():
key, val = f"\r\n{header_name.lower()}: ".encode(), header_value.encode()
parts.extend([key, val])| @pytest.mark.parametrize("content_type", [None, "text/plain"]) | ||
| @pytest.mark.parametrize( | ||
| "headers", | ||
| [ | ||
| {"content-type": "text/plain"}, | ||
| {"Content-Type": "text/plain"}, | ||
| {"CONTENT-TYPE": "text/plain"}, | ||
| ], | ||
| ) | ||
| def test_multipart_headers_include_content_type( | ||
| content_type: typing.Optional[str], headers: typing.Dict[str, str] | ||
| ) -> None: | ||
| """Including contet-type in the multipart headers should not be allowed""" | ||
| client = httpx.Client(transport=httpx.MockTransport(echo_request_content)) | ||
|
|
||
| files = {"file": ("test.txt", b"content", content_type, headers)} | ||
| pat = "Content-Type cannot be included in multipart headers" | ||
| with pytest.raises(ValueError, match=pat): | ||
| client.post("http://127.0.0.1:8000/", files=files) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a typo in the docstring of the test_multipart_headers_include_content_type function. The word "contet-type" should be corrected to "content-type".
"""Including contet-type in the multipart headers should not be allowed"""
+ """Including content-type in the multipart headers should not be allowed"""
👍 Conditional Approval Checklist
Summary by Reviewed
New Feature
Test
ValueError.These changes improve the flexibility and robustness of multipart file uploads by allowing more granular control over headers, while ensuring compliance with header constraints.