Recently I had to add imgproxy
to a section of a Laravel which hosts CMS content through a WYSIWYG and is persisted as html.
I decided to use a middleware to rewrite the content, I used the following (well rated) packages to help:
imgproxy
For local development, I obviously use docker.
The following variables will need to be added to .env
file for your Laravel project (and they are the same that we will pass to our imgproxy service later):
IMGPROXY_KEY=
IMGPROXY_SALT=
IMGPROXY_SIGNATURE_SIZE=32
For IMGPROXY_KEY
and IMGPROXY_SALT
I use the following to generate values:
echo $(xxd -g 2 -l 64 -p /dev/random | tr -d '\n')
I don’t need to run it all the time, so this will suffice:
docker run --rm --env-file /path/to/laravel-site/.env -p 8888:8080 darthsim/imgproxy:latest
Since I use valet, I need to proxy since serving http content on https is tricky.
valet proxy --secure imgproxy.ac93 http://localhost:8888
This will mean that https://imgproxy.ac93.test
will be what will used in the Laravel app to host our images through imgproxy. Add it to the .env
.
IMGPROXY_URL=https://imgproxy.ac93.test
Add the following to a relevant config
file, e.g. config/services.php
:
<?php
return [
'imgproxy' => [
'url' => env('IMGPROXY_URL'),
'salt' => env('IMGPROXY_SALT'),
'key' => env('IMGPROXY_KEY'),
],
];
And finally, a little bit of dependency injection:
app/Providers/AppServiceProvider.php
:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Imgproxy\UrlBuilder;
use Illuminate\Foundation\Application;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
$this->app->bind(UrlBuilder::class, function (Application $app) {
return new UrlBuilder(
config('services.imgproxy.url'),
config('services.imgproxy.key'),
config('services.imgproxy.salt')
);
});
}
}
Middleware
The middleware is relatively simple.
|
|
You can add ?no_imgproxy
to url to skip the middleware for testing, etc.
|
|
Get the response content and load it into the DOM parser.
|
|
For each img
in the DOM, don’t change svg
and only rewrite images which are hosted on our site, i.e. in public
; or hosted on our bucket.
imgproxy
can be configured to host s3 content directly, but out of scope here, and serving public files is advantageous in this scenario.
|
|
Since this middleware is only applied to one section of the site which has a known max-width.
- Line 49: width - 896px, i.e. tailwind
max-w-4xl
; we constrain all images to this width - Line 50: height - 0px, i.e. do not resize to a fixed height; aspect ratio will be respected
|
|
You can see the middleware gist.