Not so Static Assets with Laravel

Not so Static Assets with Laravel
Photo by Zach Vessels / Unsplash

Handling Laravel routing in ReactPHP, I missed a particular use case: managing the assets usually sitting in the public/ folder. Publishing a regular application with a regular web server it takes care to directly fetch and serve the files from the filesystem, but wrapping the application into a ReactPHP loop it is required to handle those paths explicitely.

So I had to create an extra Controller, and provide a few extra routes for it.

Route::get('css/{filename}', 'AssetsController@css')->where('filename', '(.*)')->name('assets.css');
Route::get('js/{filename}', 'AssetsController@js')->where('filename', '(.*)')->name('assets.js');
Route::get('fonts/{filename}', 'AssetsController@fonts')->where('filename', '(.*)')->name('assets.fonts');

Here we manage contents from css/, js/ and fonts/ folder. Please note that files may be in subfolders, so the {filename} parameter must include even / characters (which indeed are usually used to separate parameters: without this care, the routing rule will not match for subfolders).

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use League\MimeTypeDetection\GeneratedExtensionToMimeTypeMap;

class AssetsController extends Controller
{
    private function localAssets($folder, $filename)
    {
        $path = public_path($folder . '/' . $filename);
        if (file_exists($path)) {
            $map = new GeneratedExtensionToMimeTypeMap();
            $ext = pathinfo(public_path($filename), PATHINFO_EXTENSION);
            $mime = $map->lookupMimeType($ext);
            if (empty($mime)) {
                abort(404);
            }

            return response()->download($path, basename($filename), ['Content-Type' => $mime]);
        }
        else {
            abort(404);
        }
    }

    public function css(Request $request, $filename)
    {
        return $this->localAssets('css', $filename);
    }

    public function js(Request $request, $filename)
    {
        return $this->localAssets('js', $filename);
    }

    public function fonts(Request $request, $filename)
    {
        return $this->localAssets('fonts', $filename);
    }
}

This is a very simple function wrapping the public_path() folder, and the only care is getting MIME types using the mime-type-detection package provided by The League of Extraordinary Packages.