Skip to content

SendPost() Alters Array Structure in Multipart Requests #38

Open
@leobedrosian

Description

@leobedrosian

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions