From 59da7666b5773a9b7063185d7585ed664d351062 Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Mon, 25 Sep 2023 13:48:23 +0100
Subject: [PATCH] Uploads: Added user-facing message for Laravel post limit
 handling

Uploads over the post max size Would previously error without a
clean user facing message. This catches that error to provide a
user friendly message, compatible with our common error handling.

Tested on image manager handling.
Added test to cover.
---
 app/Exceptions/Handler.php |  7 ++++++-
 lang/en/errors.php         |  1 +
 tests/ErrorTest.php        | 13 +++++++++++++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php
index 36bdf845d..385720643 100644
--- a/app/Exceptions/Handler.php
+++ b/app/Exceptions/Handler.php
@@ -6,6 +6,7 @@ use Exception;
 use Illuminate\Auth\AuthenticationException;
 use Illuminate\Database\Eloquent\ModelNotFoundException;
 use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
+use Illuminate\Http\Exceptions\PostTooLargeException;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
 use Illuminate\Validation\ValidationException;
@@ -59,6 +60,10 @@ class Handler extends ExceptionHandler
      */
     public function render($request, Throwable $e)
     {
+        if ($e instanceof PostTooLargeException) {
+            $e = new NotifyException(trans('errors.server_post_limit'), '/', 413);
+        }
+
         if ($this->isApiRequest($request)) {
             return $this->renderApiException($e);
         }
@@ -71,7 +76,7 @@ class Handler extends ExceptionHandler
      */
     protected function isApiRequest(Request $request): bool
     {
-        return strpos($request->path(), 'api/') === 0;
+        return str_starts_with($request->path(), 'api/');
     }
 
     /**
diff --git a/lang/en/errors.php b/lang/en/errors.php
index 4cde4cea3..1f7404697 100644
--- a/lang/en/errors.php
+++ b/lang/en/errors.php
@@ -44,6 +44,7 @@ return [
     'cannot_get_image_from_url' => 'Cannot get image from :url',
     'cannot_create_thumbs' => 'The server cannot create thumbnails. Please check you have the GD PHP extension installed.',
     'server_upload_limit' => 'The server does not allow uploads of this size. Please try a smaller file size.',
+    'server_post_limit' => 'The server cannot receive the provided amount of data. Try again with less data or a smaller file.',
     'uploaded'  => 'The server does not allow uploads of this size. Please try a smaller file size.',
 
     // Drawing & Images
diff --git a/tests/ErrorTest.php b/tests/ErrorTest.php
index 6ba01dd88..0d2ef808c 100644
--- a/tests/ErrorTest.php
+++ b/tests/ErrorTest.php
@@ -2,6 +2,7 @@
 
 namespace Tests;
 
+use Illuminate\Foundation\Http\Middleware\ValidatePostSize;
 use Illuminate\Support\Facades\Log;
 
 class ErrorTest extends TestCase
@@ -45,4 +46,16 @@ class ErrorTest extends TestCase
         $resp->assertStatus(404);
         $resp->assertSeeText('Image Not Found');
     }
+
+    public function test_posts_above_php_limit_shows_friendly_error()
+    {
+        // Fake super large JSON request
+        $resp = $this->asEditor()->call('GET', '/books', [], [], [], [
+            'CONTENT_LENGTH' => '10000000000',
+            'HTTP_ACCEPT' => 'application/json',
+        ]);
+
+        $resp->assertStatus(413);
+        $resp->assertJson(['error' => 'The server cannot receive the provided amount of data. Try again with less data or a smaller file.']);
+    }
 }