🌻

symfony/http-kernelをアップデートしたらJPEGファイルのLaravel MIMEバリデーションが通らなくなった

2 min read

発生した事象

Laravelアプリケーションにて、symfony/http-kernel ライブラリをアップデートしたら
ファイルアップロード時のバリデーションで、JPEGファイルがバリデーションで落ちるようになった。

原因

該当箇所は Illuminate\Foundation\Http\FormRequest を継承したクラスにて

    public function rules()
    {
        return [
            'file' => 'required|mimes:jpeg,png',
        ];
    }

と記載していた。

symfony/http-kernel ライブラリをアップデートしたところ
依存ライブラリとして、symfony/mime もバージョンが上がり
以下コミットが含まれていた。

[Mime] Prefer .jpg instead of .jpeg · symfony/mime@aa1d922

@@ -1320,7 +1320,7 @@ public function guessMimeType(string $path): ?string
        'image/ief' => ['ief'],
        'image/jls' => ['jls'],
        'image/jp2' => ['jp2', 'jpg2'],
-        'image/jpeg' => ['jpeg', 'jpg', 'jpe'],
+        'image/jpeg' => ['jpg', 'jpeg', 'jpe'],
        'image/jpeg2000' => ['jp2', 'jpg2'],
        'image/jpeg2000-image' => ['jp2', 'jpg2'],
        'image/jph' => ['jph'],

このコミットが入ったのは、v5.2.0

https://github.com/symfony/mime/compare/v5.1.11...v5.2.0

これがなぜ影響するかというと、ファイルアップロード時のMIMEの判定は
以下の場所で行っている。

https://github.com/symfony/symfony/blob/0486a532124e65526f0c231546524e5025496aa8/src/Symfony/Component/HttpFoundation/File/UploadedFile.php#L140
return MimeTypes::getDefault()->getExtensions($this->getClientMimeType())[0] ?? null;

MimeTypes::getDefault()->getExtensions() で返ってきた配列の最初の要素([0]でデリファレンスしている)で判定している。

で、この実装はどうなっているかというと

https://github.com/symfony/mime/blob/aa1d922a7c32aedc10f6647ded250535ee3c6346/MimeTypes.php#L84-L91
    public function getExtensions(string $mimeType): array
    {
        if ($this->extensions) {
            $extensions = $this->extensions[$mimeType] ?? $this->extensions[$lcMimeType = strtolower($mimeType)] ?? null;
        }

        return $extensions ?? self::$map[$mimeType] ?? self::$map[$lcMimeType ?? strtolower($mimeType)] ?? [];
    }

となっていて、通常は self::$map[$mimeType] が返る。
この MimeTypes::$map 配列が、冒頭であげたコミットで image/jpeg キーの配列の最初の要素が jpeg から jpg に変わってしまったため
LaravelのRule定義で required|mimes:jpeg,png を満たさなくなり、バリデーションエラーになってしまっていた。

対応方法

rule定義を jpeg から jpg に変えるか、併記する。

    public function rules()
    {
        return [
            'file' => 'required|mimes:jpeg,jpg,png',
        ];
    }

蛇足

該当のコミット、コミッターを見ると、Fabien Potencier。
お・・・おぅ・・・
そんな「.jpegより.jpgの方がいいよね」なんて軽いノリで変えないでくれよ… 😭