diff --git a/VERSION b/VERSION
index 63815a2..c5f04ce 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.2503.230337
+0.2503.230355
diff --git a/src/Http/Routing/Filters/PatternFilter.php b/src/Http/Routing/Filters/PatternFilter.php
index 74e024e..2df350d 100644
--- a/src/Http/Routing/Filters/PatternFilter.php
+++ b/src/Http/Routing/Filters/PatternFilter.php
@@ -1,7 +1,7 @@
 <?php
 // PatternFilter.php
 // Created: 2024-03-28
-// Updated: 2025-03-07
+// Updated: 2025-03-23
 
 namespace Index\Http\Routing\Filters;
 
@@ -18,14 +18,14 @@ class PatternFilter extends FilterAttribute {
     /**
      * @param string $pattern URI path pattern.
      * @param bool $raw If true, $pattern is taken as is, if false, $pattern is prefixed with #^ and suffixed with #u or $#uD
-     * @param bool $prefix Only has effect if $raw is false. If true is #u appended to $pattern, otherwise $#uD.
+     * @param bool $prefix Only has effect if $raw is false. If true is #u appended to $pattern, otherwise /?$#uD.
      */
     public function __construct(
         string $pattern,
         bool $raw = false,
         bool $prefix = true,
     ) {
-        $this->pattern = $raw ? $pattern : sprintf('#^%s%s', $pattern, $prefix ? '#u' : '$#uD');
+        $this->pattern = $raw ? $pattern : sprintf('#^%s%s', $pattern, $prefix ? '#u' : '/?$#uD');
     }
 
     public function createInstance(Closure $handler): FilterInfo {
diff --git a/src/Http/Routing/Routes/PatternRoute.php b/src/Http/Routing/Routes/PatternRoute.php
index 4df90cf..523f51f 100644
--- a/src/Http/Routing/Routes/PatternRoute.php
+++ b/src/Http/Routing/Routes/PatternRoute.php
@@ -1,7 +1,7 @@
 <?php
 // PatternRoute.php
 // Created: 2024-03-28
-// Updated: 2025-03-07
+// Updated: 2025-03-23
 
 namespace Index\Http\Routing\Routes;
 
@@ -19,13 +19,15 @@ class PatternRoute extends RouteAttribute {
      * @param string $method HTTP Method.
      * @param string $pattern URI path pattern.
      * @param bool $raw If true, $pattern is taken as is, if false, $pattern is prefixed with #^ and suffixed with $#uD
+     * @param bool $slash Only has effect if $raw is false. If true /? is appended to $pattern to allow for trailing slashes.
      */
     public function __construct(
         private string $method,
         string $pattern,
-        bool $raw = false
+        bool $raw = false,
+        bool $slash = true,
     ) {
-        $this->pattern = $raw ? $pattern : sprintf('#^%s$#uD', $pattern);
+        $this->pattern = $raw ? $pattern : sprintf('#^%s%s$#uD', $pattern, $slash ? '/?' : '');
     }
 
     public function createInstance(Closure $handler): RouteInfo {
diff --git a/src/Http/Routing/UriMatchers/ExactPathUriMatcher.php b/src/Http/Routing/UriMatchers/ExactPathUriMatcher.php
index f71f8d4..ef7289d 100644
--- a/src/Http/Routing/UriMatchers/ExactPathUriMatcher.php
+++ b/src/Http/Routing/UriMatchers/ExactPathUriMatcher.php
@@ -1,7 +1,7 @@
 <?php
 // ExactPathUriMatcher.php
 // Created: 2025-03-07
-// Updated: 2025-03-07
+// Updated: 2025-03-23
 
 namespace Index\Http\Routing\UriMatchers;
 
@@ -19,6 +19,7 @@ class ExactPathUriMatcher implements UriMatcher {
     ) {}
 
     public function match(UriInterface $uri): array|bool {
-        return $uri->getPath() === $this->path;
+        $path = $uri->getPath();
+        return $path === $this->path || $path === ($this->path . '/');
     }
 }
diff --git a/tests/RouterTest.php b/tests/RouterTest.php
index 28941f5..298fb2b 100644
--- a/tests/RouterTest.php
+++ b/tests/RouterTest.php
@@ -139,6 +139,12 @@ final class RouterTest extends TestCase {
                 return 'hit pattern';
             }
 
+            #[ExactRoute('GET', '/assets/avatar')]
+            #[PatternRoute('GET', '/assets/avatar/([0-9]+)(?:\.[a-z]+)?')]
+            public function getTrailingSlash(): string {
+                return 'hit';
+            }
+
             public function hasNoAttr(): string {
                 return 'not a route';
             }
@@ -163,6 +169,8 @@ final class RouterTest extends TestCase {
         $this->assertSame('1RJNSRYmxrvXUr////jpg', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/uploads/1RJNSRYmxrvXUr.jpg'))->getBody());
         $this->assertSame('hit exact', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/messages/stats'))->getBody());
         $this->assertSame('hit pattern', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/messages/soaps'))->getBody());
+        $this->assertSame('hit', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/assets/avatar/'))->getBody());
+        $this->assertSame('hit', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/assets/avatar/123/'))->getBody());
     }
 
     public function testEEPROMSituation(): void {