Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

felixele217's avatar

Set Response Headers for statically served JS build assets

Hey guys,

I have the following problem:

I have two different subdomains: partner.foo.test and office.foo.test

I want to write a Dusk Browser test, where I make a get request to partner.foo.test/login. The partner subdomain receives its JS build assets from office.too.test.

Because I do not have configured

Access-Control-Allow-Origin: * // or anything that would work

I get the following error:

    {
        "level": "SEVERE",
        "message": "http:\/\/partner.foo.test:8008\/login 52 Access to script at 'http:\/\/office.foo.test:8008\/build\/assets\/inertia-C288X464.js' from origin 'http:\/\/partner.foo.test:8008' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.",
        "source": "javascript",
        "timestamp": 1761742816007
    },

The Dusk Server that serves the assets is started like this:

php artisan serve --env=testing --port 8008

and the JS build is made with vite.

I have tried three things so far:

  1. Configuring "server" property in vite.config.js
server: {
        cors: true, //also tried with cors: false
        headers: {
            'Access-Control-Allow-Origin': '*',
        },
    },
  1. Writing global middleware to set response headers
$response = $next($request);
$response->header('Access-Control-Allow-Origin, '*');
return $response;

The statically accessed JS file does not trigger dd() inside the middleware when accessing

  1. Setting response header variable in the Dusk Test itself
header('Access-Control-Allow-Origin, '*')

All of them did not work.

Any ideas what I could try?

0 likes
2 replies
JussiMannisto's avatar

Laravel's middleware won't work because static files aren't served through the framework. Vite configuration also won't help because you're dealing with built assets. In production, you'd set the headers in the web server config, but artisan serve uses the built-in PHP server, which doesn't have config files. However, you can pass in a custom PHP router script to handle requests.

Out of curiosity, I looked into how the serve command works. There is a way to set headers for statically served files using a custom router, but it's a bit hacky. Just be warned.

The serve command selects a router script to pass to the built-in server. It first looks for a server.php file in the project root. If it doesn't exist, the default router script is used. You can copy the default server.php to the project root, then modify a part of it to serve JS files manually:

if ($uri !== '/' && file_exists($publicPath.$uri)) {
	$path = $publicPath.$uri;

	if (pathinfo($path, PATHINFO_EXTENSION) === 'js') {
		header('Access-Control-Allow-Origin: *');
		header('Content-Length: '.filesize($path));
		header('Content-Type: application/javascript');

		readfile($path);
		return true;
	}

	return false;
}

Returning true means "I've handled this request", while false means "You handle it".

If you do this, you should see the Access-Control-Allow-Origin header on JS files when using the serve command.

2 likes
felixele217's avatar

Thanks, that is working. I am iterating on you to use that in the most proper way, but you made it possible! :)

Please or to participate in this conversation.