-
Notifications
You must be signed in to change notification settings - Fork 11k
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
Fix hasFile
Method to Accurately Identify Files in Request
#52445
base: 11.x
Are you sure you want to change the base?
Fix hasFile
Method to Accurately Identify Files in Request
#52445
Conversation
58ad393
to
bc8306d
Compare
@@ -666,11 +666,28 @@ public function testFilesCanBeAttached() | |||
$this->factory->assertSent(function (Request $request) { | |||
return $request->url() === 'http://foo.com/file' && | |||
Str::startsWith($request->header('Content-Type')[0], 'multipart') && | |||
$request[0]['name'] === 'foo' && |
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.
Why was this test changed?
I understand the premise of the PR, but this test case is named "files can be attached", and the condition to check for an attached file is removed?
In the best case, no previous test cases should be changed, but again, I see from your proposed changes why you did it.
Either this test case should be renamed or removed.
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.
In this test, we check some of the other assertions related to attaching a file in a request, while in the new test, we focus solely on the functionality of the hasFile method itself. In my opinion, these tests complement each other and test different aspects of the framework. However, they could be merged into a single test that checks the entire process of attaching files.
@@ -149,7 +149,8 @@ public function hasFile($name, $value = null, $filename = null) | |||
return collect($this->data)->reject(function ($file) use ($name, $value, $filename) { | |||
return $file['name'] != $name || | |||
($value && $file['contents'] != $value) || | |||
($filename && $file['filename'] != $filename); | |||
($filename && $file['filename'] != $filename) || | |||
! is_resource($file['contents']) && json_encode($file['contents']) !== false; |
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.
As the previous checks are using OR (||
), shouldn't these last two be wrapped in parentheses?
Also, in your description you mention the json_encode()
is "retained", but the GIT diff doesn't show it on the previous version...
- Where did it come from?
- Isn't trying to encode every attachment as JSON, expecting it to fail, as a condition inside a
Collection@reject()
callback, an expensive operation?
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.
Regarding your first point, I see what you mean, and I will use parentheses for that. However, regarding your second point, there was a misunderstanding in my explanation. I intended to use json_encode to ensure that we only check the file attachments rather than other fields in the request body, and I didn't mean to imply that this function was already used.
This approach enhances the logic of the code by ensuring that we check whether the request contains a specific file, which is the expected functionality of this method.
I am not sure if I follow the reasoning. The component being changed is the Currently, if one needs to send a simple string as an attachment, per a 3rd party API constraint, for example, one could just call If this PR gets merged, one would need to create either a real or a temp file, and attach its handler, to have the What is the actual benefit? |
Although there is no change in the method signature, the behavior is hugely changed, IMO it is a breaking change. It is not an improvement per se, or a bug fix, but a behavior change. It might be the desired behavior, and if so, should be merged. But nonetheless, it seems like a behavior change that can cause previous code to stop working. |
Thank you for your questions and for taking the time to review the proposed changes. You're correct that Illuminate\Http\Client\Request is responsible for sending requests out of the application. The hasFile() method is designed to check if a request contains a file attachment, which is useful in certain scenarios, especially when interacting with APIs that require file uploads. The problem with the current implementation of hasFile() is that it does not accurately distinguish between actual file uploads and simple string data. For instance, if a request contains a string value that is expected to be a file, hasFile() might incorrectly return true, even though the string is not a file. This could lead to unexpected behavior, especially when the application or a third-party API expects a real file upload. The key benefit is that this change improves the accuracy and reliability of the hasFile() method. It eliminates the risk of false positives when dealing with file uploads, ensuring that the method only confirms the presence of real files. This is particularly important when working with APIs that have strict file upload requirements. In scenarios where you're attaching a string due to third-party API constraints, this change encourages more explicit handling of file uploads by requiring a file resource. This makes the code more predictable and reduces the potential for errors when working with file uploads in HTTP requests |
You’re correct that this could be considered a breaking change since it modifies how hasFile() interprets what constitutes a file. Code that previously passed a string and expected hasFile() to return true might now fail unless an actual file resource is used. The primary reason for this change is to improve the accuracy of the hasFile() method in identifying genuine file uploads. The current behavior can lead to false positives, which could result in bugs, especially when interfacing with APIs that strictly require files and not strings. In conclusion while the change is intended to improve the robustness and accuracy of file handling, it’s clear that this could impact existing applications that rely on the current behavior. If this is the desired direction, we should clearly communicate the change to users and consider the best way to introduce it without causing disruption. |
Sure, but if all one wants is to attach some string to be sent as a file, on a multipart request body, and later check if they have attached it, the current implementation has them covered up. As this object is constructed by the application developer, and not by parsing external input such as its But let's wait for the maintainers' verdict. |
Can you describe what is actually going wrong in your production app with the current method and how to reproduce? |
Please mark as ready for review when you want me to take another look. |
sure, create a form with multiple non-file fields (e.g., text, arrays, or JSON data). |
Can you show how to "create a form", for the HTTP Client component, with code? |
Also, how are you accessing the And therefore the Is it from a Guzzle Middleware? |
Yeah a simple copy and paste reproduction would be helpful. |
Summary
This pull request addresses an issue in the
Illuminate\Http\Client\Request
class where thehasFile
method could incorrectly identify non-file data as a file when checking for multipart form data. The fix enhances the logic in thehasFile
method to ensure that only actual file uploads are recognized as files, preventing false positives.Problem
The
hasFile
method relied on checking whether thecontents
of a request's data matched certain criteria, but it lacked a robust mechanism to differentiate between actual file uploads and plain string data. This led to scenarios where non-file data with the same key as an expected file could be misinterpreted as a file, resulting in inaccurate behavior.Solution
The proposed fix introduces the following improvements:
Impact
Backward Compatibility: This change does not introduce any breaking changes and is fully backward compatible.
Accuracy Improvement: The method now more accurately identifies file uploads, leading to better reliability in handling multipart form data in HTTP requests.