Skip to content

[Bug]: File uploads causing empty request body with incorrect $_SERVER['CONTENT_TYPE'] #1648

@bluesheep100

Description

@bluesheep100

What Happened

I was producing the following test:

it('can be created by an authenticated user', function () {
    actingAs($user = User::factory()->create());
    Tag::findOrCreateFromString('Testing', locale: app()->getLocale());

    visit(route('posts.index'))
        ->click('.create-post')
        ->type('#post_title', 'Test title')
        ->click('#tag_options > button:first-child')
        ->type('#post_content .ql-editor[contenteditable=true]', 'Testing content.')
        ->attach('#post_banner', resource_path('/images/image-placeholder.jpg'))
        ->click('#create-post')
        ->assertSee('Test title')
        ->assertSee('Test content.')
        ->assertSee('Testing')
        ->assertSee($user->name);
});

However, this test fails at the first assertSee(), due to every validation error for "required" failing. Removing the ->attach() resolves the issue, but obviously I need to be able to upload a file for this test.

After investigation I found that specifically during testing, the output of $request->headers->get('Content-Type') does not match $request->server('CONTENT_TYPE') (or `$_SERVER['CONTENT_TYPE']).

dd(
    $request->headers->get('Content-Type'),
    $request->server('CONTENT_TYPE'),
);

If I use the form normally, both of these output multipart/form-data; boundary=----WebKitBoundary...., but when running the test, the latter is application/x-www-form-urlencoded instead, and the request body is completely empty. (because the client is attempting to send multipart data, presumably)

I thought initially that this was an issue with Sail or my InertiaJS/Vue stack, but the issue persists in a barebones application with a simple form and no starter kit.

How to Reproduce

Clone the sample repository, then:

composer install
composer run setup
npm install
npx playwright install chromium
composer run dev

Run the test with php artisan test tests/Feature/ExampleTest.php. The test should fail, although for some reason it will stall after attaching the image, indefinitely, until a hot reload is caused. (by editing welcome.blade.php for example) I have no idea why this happens? It seems it might also be interfering with the test.

If you modify the test to visit http://localhost:8000 instead of route('welcome'), you circumvent the dynamic port that is apparently suffixed to the path automatically, and the test runs without issues. However, it's not a viable workaround, because it breaks actingAs(), and so won't fix the original case.

Sample Repository

https://github.com/bluesheep100/pest-browser-contenttype-issue

Pest Version

4.4.1

PHP Version

8.4.17 NTS (Zend Engine v4.4.17)

Operation System

Linux, Windows

Notes

  • There seems to be no difference between localhost and 127.0.0.1 in these scenarios
  • Why does Playwright/Pest access the site via a dynamic port and not what is configured as APP_URL?
  • This occurred initially in CI/CD running on an Ubuntu server, with Inertia's SSR mode running. I don't believe that WSL or no WSL has any impact on this issue.
  • Why does the test stall forever, unless I cause a reload by editing files?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions