CodeSleeve / asset-pipeline

This Laravel 4 package provides a very simple and easy to use asset pipeline. It was heavily inspired by the Rails asset pipeline. We make use of the wonderful Assetic package to help with pre-compliation!
http://www.codesleeve.com
MIT License
489 stars 53 forks source link

Serving Flash-related files as downloads causes occasional problems #69

Closed KingMob closed 10 years ago

KingMob commented 10 years ago

Basically, without adding the file extensions to the filters list, asset-pipeline will ignore them. (And shouldn't a log message be generated if you request a file asset-pipeline can't deliver?)

E.g., I'm using a couple libraries that involve coordinated Javascript and Flash (FusionCharts, the TableTools extra for DataTables). The Javascript code will attempt to download "../swf/some_flash_file.swf", and asset-pipeline qill quietly return nothing.

It seems to me Flash should be covered by asset-pipeline (Adobe hasn't totally killed it yet).

The fix is as simple as appending

        ".swf" => array(
            // don't minify files with this extension
        ),
        ".as" => array(
            // don't minify files with this extension
        ),
        ".swc" => array(
            // don't minify files with this extension
        ),

to the filters list. I'm not sure if ActionScript files (.as) can be safely minimized or not, so I left it alone.

If you have no objections, I'll fork, fix, and submit a pull request.

kdocki commented 10 years ago

These files should just be downloadable ... not sure why you are having to specify them in your filters array. Let me look into this...

KingMob commented 10 years ago

Just double-checked this morning. I commented out the flash-related lines in config.php, ran "php artisan assets:clean", and all my Flash files refused to download on my pages. BUT, if I request the files straight from the browser location bar, they download just fine(!). Once I enabled the flash config lines again, my pages resumed working.

So, the thing is, I'm using a library called FusionCharts. I supply it the url of a .swf file, but I think it has its own Flash-based wrapper/loader, because it doesn't generate normal XHR that Chrome's dev tools can see. (This is true even when it's working fine.) Unfortunately, as a closed-source project, I can't see the Flash code, and the associated .js is all minified, so I'm not totally sure what kind of requests it's making of the server. But looking at the Apache logs, the requests seem ok: "GET /assets/StackedBar2D.swf HTTP/1.1" 200 80216

Any ideas? I've definitely double-checked that including the flash file extensions in the "filters" array causes everything to work for me, and leaving them out doesn't, even though I can still request the files in the browser bar, so in theory the config lines shouldn't be necessary.

KingMob commented 10 years ago

I think I found the cause of the problem. Essentially, if something isn't javascript or a stylesheet, AssetPipelineController treats it as a file download, using Response::download(). Perhaps this causes subtle, occasional problems, because they're not actually meant to be saved by the users? It sets extra headers that aren't set by the server when requesting the .swf files normally: Content-Disposition, Cache-Control, and Content-Transfer-Encoding look like suspicious candidates.

In this case, I was using the TableTools extension for DataTables, which relies on a small .swf file. When I served the .swf file from outside /assets, everything worked fine. When served from /assets, nothing worked, even though in both cases it requested the .swf file, and got it with a HTTP 200 response.

In AssetPipelineController::file(), if I change

return Response::download($file);

to

return new \Symfony\Component\HttpFoundation\BinaryFileResponse($file, 200);

the .swf files start working again.

I'm not sure what the optimal global solution is (Stop using Response::download for things that aren't meant to be saved by the user? Treat Flash files specially, like js/css?), but at least for my particular combination of Mac/Chrome, .swf files don't work if treated as downloads.

KingMob commented 10 years ago

Well, I forked asset-pipeline a couple days ago, made the change, and things seem to be running well on our end. With the switch to returning a BinaryFileResponse, it works without any extra lines in the filters array. Not sure why that helped in the past.

Let me know if you want a pull request. (And anything else. E.g., need a unit test for it?)

kdocki commented 10 years ago

@KingMob ah, thanks for debugging this for me. I've been refactoring so I just now making it to this story. I don't personally use flash stuff all that often so I haven't ran into this issue yet but I will take your word on it and swap out the Response::download($file) with the Symfony BinaryFileResponse.

KingMob commented 10 years ago

Great! Let me know if you have any questions or need anything.

kdocki commented 10 years ago

fixed in v1.4.2