module-phpbrowser icon indicating copy to clipboard operation
module-phpbrowser copied to clipboard

SendPost() Alters Array Structure in Multipart Requests

Open leobedrosian opened this issue 1 year ago • 1 comments

When transmitting a mulitpart/form-data request using PhpBrowser::sendPost($url, $body, $files) with a $body that has nested arrays (ie a collection of objects) , the resulting multipart message has the array order reversed in its individual parts.

So this:

Array
(
    [users] => Array
        (
            [0] => Array
                (
                    [id] => 0
                    [name] => John Doe
                )
            [1] => Array
                (
                    [id] => 1
                    [name] => Jane Doe
                )
        )
)

Becomes this (as seen on the server):

Array
(
    [users] => Array
        (
            [1] => Array
                (
                    [name] => Jane Doe
                    [id] => 1
                )
            [0] => Array
                (
                    [name] => John Doe
                    [id] => 0
                )
        )
)

Multipart Request Formatting

We can see the cause of this inversion more clearly by examining the actual message constructed by the PhpBrowser module.

This is how the multipart request should be formatted (note the indexes of the array are in the right order):

--7c0cf7b98838b9468eff59ab518a464e8f1f4022
content-type: text/plain
Content-Disposition: form-data; name="file"; filename="file.txt"
Content-Length: 9

test data
--7c0cf7b98838b9468eff59ab518a464e8f1f4022
Content-Disposition: form-data; name="users[0][id]"
Content-Length: 1

0
--7c0cf7b98838b9468eff59ab518a464e8f1f4022
Content-Disposition: form-data; name="users[0][name]"
Content-Length: 8

John Doe
--7c0cf7b98838b9468eff59ab518a464e8f1f4022
Content-Disposition: form-data; name="users[1][id]"
Content-Length: 1

1
--7c0cf7b98838b9468eff59ab518a464e8f1f4022
Content-Disposition: form-data; name="users[1][name]"
Content-Length: 8

Jane Doe
--7c0cf7b98838b9468eff59ab518a464e8f1f4022--

But this is how the multipart request is presently being formatted:

--81d652d4b030eeb33144e71b51d759f925cf2955
Content-Disposition: form-data; name="users[1][name]"
Content-Length: 8

Jane Doe
--81d652d4b030eeb33144e71b51d759f925cf2955
Content-Disposition: form-data; name="users[1][id]"
Content-Length: 1

1
--81d652d4b030eeb33144e71b51d759f925cf2955
Content-Disposition: form-data; name="users[0][name]"
Content-Length: 8

John Doe
--81d652d4b030eeb33144e71b51d759f925cf2955
Content-Disposition: form-data; name="users[0][id]"
Content-Length: 1

0
--81d652d4b030eeb33144e71b51d759f925cf2955
content-type: text/plain
Content-Disposition: form-data; name="file"; filename="file.txt"
Content-Length: 9

test data
--81d652d4b030eeb33144e71b51d759f925cf2955--

The Problem

Reversing the order of array elements doesn't necessarily present a problem for a PHP application. But it becomes a problem when data type matters, like when validating data sent to an API endpoint against a schema that distinguishes between an array and an object.

Since typing isn't possible in multipart/form-data requests, the type has to be inferred. So when trying to distinguish between an array and an object, array keys are examined to determine if the array is associative or not. An associative array is the semantic equivalent of an object for the purposes of data type validation.

It's possible to try and account for this on the validation side, but the PhpBrowser module really shouldn't be altering the format of the data like it is and requiring the application to be tailored to the test suite. So ideally, the fix should be applied here. Fortunately, it's a very easy fix, and I'll draft a PR for it.

leobedrosian avatar Oct 04 '24 01:10 leobedrosian

@Naktibalda any thoughts on this issue and/or merging the PR to fix it? Are you still maintaining this module repository?

leobedrosian avatar Oct 09 '24 19:10 leobedrosian