 jsonapi.info.yml                               |  2 +-
 jsonapi.services.yml                           |  7 ---
 src/Routing/Routes.php                         |  3 +
 src/StackMiddleware/FormatSetter.php           | 82 --------------------------
 tests/src/Functional/InternalEntitiesTest.php  | 17 +++---
 tests/src/Functional/JsonApiFunctionalTest.php | 10 +---
 tests/src/Functional/MessageTest.php           |  3 +-
 tests/src/Functional/ResourceTestBase.php      | 13 ++--
 8 files changed, 22 insertions(+), 115 deletions(-)

diff --git a/jsonapi.info.yml b/jsonapi.info.yml
index f7d37b8..d4f175f 100644
--- a/jsonapi.info.yml
+++ b/jsonapi.info.yml
@@ -4,7 +4,7 @@ description: Provides a JSON API standards-compliant API for accessing and manip
 core: 8.x
 package: Web services
 dependencies:
-  - drupal:system (>=8.5.0)
+  - drupal:system (>=8.5.4)
   - drupal:serialization
 test_dependencies:
   - schemata:schemata_json_schema
diff --git a/jsonapi.services.yml b/jsonapi.services.yml
index 841b72c..6f47a83 100644
--- a/jsonapi.services.yml
+++ b/jsonapi.services.yml
@@ -133,13 +133,6 @@ services:
     tags:
       - { name: event_subscriber }
     arguments: ['@jsonapi.serializer_do_not_use_removal_imminent', '%serializer.formats%']
-  jsonapi.http_middleware.format_setter:
-    class: Drupal\jsonapi\StackMiddleware\FormatSetter
-    arguments: ['%jsonapi.base_path%']
-    tags:
-      # Set priority to 201 so it happens right before the page cache
-      # middleware (priority 200)has the opportunity to respond.
-      - { name: http_middleware, priority: 201 }
 
   logger.channel.jsonapi:
     parent: logger.channel_base
diff --git a/src/Routing/Routes.php b/src/Routing/Routes.php
index 9c8a829..2bb2e9a 100644
--- a/src/Routing/Routes.php
+++ b/src/Routing/Routes.php
@@ -111,6 +111,9 @@ class Routes implements ContainerInjectionInterface {
     // Flag every route as belonging to the JSON API module.
     $routes->addDefaults([static::JSON_API_ROUTE_FLAG_KEY => TRUE]);
 
+    // All routes serve only the JSON API media type.
+    $routes->addRequirements(['_format' => 'api_json']);
+
     // Require the JSON API media type header on every route.
     $routes->addRequirements(['_content_type_format' => 'api_json']);
 
diff --git a/src/StackMiddleware/FormatSetter.php b/src/StackMiddleware/FormatSetter.php
deleted file mode 100644
index 89c8386..0000000
--- a/src/StackMiddleware/FormatSetter.php
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php
-
-namespace Drupal\jsonapi\StackMiddleware;
-
-use Drupal\jsonapi\Routing\Routes;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\HttpKernel\HttpKernelInterface;
-
-/**
- * Sets the 'api_json' format on all requests to JSON API-managed routes.
- *
- * @internal
- */
-class FormatSetter implements HttpKernelInterface {
-
-  /**
-   * The wrapped HTTP kernel.
-   *
-   * @var \Symfony\Component\HttpKernel\HttpKernelInterface
-   */
-  protected $httpKernel;
-
-  /**
-   * The JSON API base path.
-   *
-   * @var string
-   */
-  protected $jsonApiBasePath;
-
-  /**
-   * Constructs a FormatSetter object.
-   *
-   * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel
-   *   The decorated kernel.
-   * @param string $jsonapi_base_path
-   *   The JSON API base path.
-   */
-  public function __construct(HttpKernelInterface $http_kernel, $jsonapi_base_path) {
-    $this->httpKernel = $http_kernel;
-    $this->jsonApiBasePath = $jsonapi_base_path;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
-    if ($this->isJsonApiRequest($request)) {
-      $request->setRequestFormat('api_json');
-    }
-
-    return $this->httpKernel->handle($request, $type, $catch);
-  }
-
-  /**
-   * Checks whether the current request is a JSON API request.
-   *
-   * Inspects:
-   * - request parameters
-   * - request path (uses a heuristic, because e.g. language negotiation may use
-   *   path prefixes)
-   * - 'Accept' request header value.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The current request.
-   *
-   * @return bool
-   *   Whether the current request is a JSON API request.
-   */
-  protected function isJsonApiRequest(Request $request) {
-    $is_jsonapi_route = $request->attributes->get(Routes::JSON_API_ROUTE_FLAG_KEY);
-    // Check if the path indicates that the request intended to target a JSON
-    // API route (but may not have because of an incorrect parameter or minor
-    // typo).
-    $jsonapi_route_intended = strpos($request->getPathInfo(), "{$this->jsonApiBasePath}/") !== FALSE;
-    // Check if the 'Accept' header includes the JSON API MIME type.
-    $request_has_jsonapi_media_type = count(array_filter($request->getAcceptableContentTypes(), function ($accept) {
-      return strpos($accept, 'application/vnd.api+json') === 0;
-    }));
-    return $is_jsonapi_route || ($jsonapi_route_intended && $request_has_jsonapi_media_type);
-  }
-
-}
diff --git a/tests/src/Functional/InternalEntitiesTest.php b/tests/src/Functional/InternalEntitiesTest.php
index 26fa3b2..3c2a6b2 100644
--- a/tests/src/Functional/InternalEntitiesTest.php
+++ b/tests/src/Functional/InternalEntitiesTest.php
@@ -100,16 +100,14 @@ class InternalEntitiesTest extends BrowserTestBase {
     // This cannot be in a data provider because it needs values created by the
     // setUp method.
     $paths = [
-      'individual' => $this->getIndividual($this->internalEntity),
-      'collection' => $this->jsonapiGet("/jsonapi/{$this->internalEntity->getEntityTypeId()}/{$this->internalEntity->bundle()}"),
-      'related' => $this->getRelated($this->referencingEntity, 'field_internal'),
+      'individual' => "/jsonapi/entity_test_no_label/entity_test_no_label/{$this->internalEntity->uuid()}",
+      'collection' => "/jsonapi/entity_test_no_label/entity_test_no_label",
+      'related' => "/jsonapi/entity_test_no_label/entity_test_no_label/{$this->internalEntity->uuid()}/field_internal",
     ];
-    foreach ($paths as $type => $document) {
-      $this->assertSame(
-        404,
-        $document['errors'][0]['status'],
-        "The '{$type}' route should not be available for internal resource types.'"
-      );
+    $this->drupalLogin($this->testUser);
+    foreach ($paths as $type => $path) {
+      $this->drupalGet($path, ['Accept' => 'application/vnd.api+json']);
+      $this->assertSame(404, $this->getSession()->getStatusCode());
     }
   }
 
@@ -154,6 +152,7 @@ class InternalEntitiesTest extends BrowserTestBase {
     $entity_type_id = $entity->getEntityTypeId();
     $bundle = $entity->bundle();
     $path = "/jsonapi/{$entity_type_id}/{$bundle}/{$entity->uuid()}";
+    var_dump($path);
     return $this->jsonapiGet($path, $options);
   }
 
diff --git a/tests/src/Functional/JsonApiFunctionalTest.php b/tests/src/Functional/JsonApiFunctionalTest.php
index 83c2627..68ceba7 100644
--- a/tests/src/Functional/JsonApiFunctionalTest.php
+++ b/tests/src/Functional/JsonApiFunctionalTest.php
@@ -283,9 +283,8 @@ class JsonApiFunctionalTest extends JsonApiFunctionalTestBase {
     // 19. Test non-existing route without 'Accept' header.
     $this->drupalGet('/jsonapi/node/article/broccoli');
     $this->assertSession()->statusCodeEquals(404);
-    // Without the 'Accept' header we cannot know we want the 404 error
-    // formatted as JSON API.
-    $this->assertSession()->responseHeaderContains('Content-Type', 'text/html');
+    // Even without the 'Accept' header the 404 error is formatted as JSON API.
+    $this->assertSession()->responseHeaderEquals('Content-Type', 'application/vnd.api+json');
     // 20. Test non-existing route with 'Accept' header.
     $single_output = Json::decode($this->drupalGet('/jsonapi/node/article/broccoli', [], [
       'Accept' => 'application/vnd.api+json',
@@ -592,11 +591,6 @@ class JsonApiFunctionalTest extends JsonApiFunctionalTestBase {
     ]);
     $created_response = Json::decode($response->getBody()->__toString());
     $this->assertEquals(415, $response->getStatusCode());
-    $this->assertNotEmpty($created_response['errors']);
-    $this->assertEquals(
-      'Unsupported Media Type',
-      $created_response['errors'][0]['title']
-    );
 
     // 4. Article with a duplicate ID.
     $invalid_body = $body;
diff --git a/tests/src/Functional/MessageTest.php b/tests/src/Functional/MessageTest.php
index b6d951a..f923a8a 100644
--- a/tests/src/Functional/MessageTest.php
+++ b/tests/src/Functional/MessageTest.php
@@ -172,7 +172,8 @@ class MessageTest extends ResourceTestBase {
     // 405 because Message entities are not stored, so they cannot be retrieved,
     // yet the same URL can be used to POST them.
     $response = $this->request('GET', $collection_url, $request_options);
-    $this->assertResourceErrorResponse(405, 'No route found for "GET /jsonapi/contact_message/camelids": Method Not Allowed (Allow: POST)', $response, FALSE, ['4xx-response', 'http_response'], [''], FALSE, 'UNCACHEABLE');
+    $this->assertSame(405, $response->getStatusCode());
+    $this->assertSame(['POST'], $response->getHeader('Allow'));
   }
 
 }
diff --git a/tests/src/Functional/ResourceTestBase.php b/tests/src/Functional/ResourceTestBase.php
index 594e890..ff15fd6 100644
--- a/tests/src/Functional/ResourceTestBase.php
+++ b/tests/src/Functional/ResourceTestBase.php
@@ -1071,11 +1071,10 @@ abstract class ResourceTestBase extends BrowserTestBase {
     $message = 'The "' . static::$entityTypeId . '" parameter was not converted for the path "' . $path . '" (route name: "jsonapi.' . static::$resourceTypeName . '.individual")';
     $this->assertResourceErrorResponse(404, $message, $response, FALSE, ['4xx-response', 'http_response'], [''], FALSE, 'UNCACHEABLE');
 
-    // DX: when Accept request header is missing, still 404, but HTML response.
+    // DX: when Accept request header is missing, still 404, same response.
     unset($request_options[RequestOptions::HEADERS]['Accept']);
     $response = $this->request('GET', $url, $request_options);
-    $this->assertSame(404, $response->getStatusCode());
-    $this->assertSame(['text/html; charset=UTF-8'], $response->getHeader('Content-Type'));
+    $this->assertResourceErrorResponse(404, $message, $response, FALSE, ['4xx-response', 'http_response'], [''], FALSE, 'UNCACHEABLE');
   }
 
   /**
@@ -1413,7 +1412,7 @@ abstract class ResourceTestBase extends BrowserTestBase {
 
     // Test POST: missing content-type.
     $response = $this->request('POST', $url, $request_options);
-    $this->assertResourceErrorResponse(415, 'No "Content-Type" request header specified', $response);
+    $this->assertSame(415, $response->getStatusCode());
 
     // Set the JSON API media type header for all subsequent requests.
     $request_options[RequestOptions::HEADERS]['Content-Type'] = 'application/vnd.api+json';
@@ -1831,7 +1830,7 @@ abstract class ResourceTestBase extends BrowserTestBase {
 
     // DX: 415 when no Content-Type request header.
     $response = $this->request('POST', $url, $request_options);
-    $this->assertResourceErrorResponse(415, 'No "Content-Type" request header specified', $response);
+    $this->assertSame(415, $response->getStatusCode());
 
     $request_options[RequestOptions::HEADERS]['Content-Type'] = 'application/vnd.api+json';
 
@@ -2073,7 +2072,7 @@ abstract class ResourceTestBase extends BrowserTestBase {
 
     // DX: 415 when no Content-Type request header.
     $response = $this->request('PATCH', $url, $request_options);
-    $this->assertResourceErrorResponse(415, 'No "Content-Type" request header specified', $response);
+    $this->assertsame(415, $response->getStatusCode());
 
     $request_options[RequestOptions::HEADERS]['Content-Type'] = 'application/vnd.api+json';
 
@@ -2265,7 +2264,7 @@ abstract class ResourceTestBase extends BrowserTestBase {
 
     // DX: 415 when request body in existing but not allowed format.
     $response = $this->request('PATCH', $url, $request_options);
-    $this->assertResourceErrorResponse(415, 'No route found that matches "Content-Type: text/xml"', $response);
+    $this->assertSame(415, $response->getStatusCode());
 
     $request_options[RequestOptions::HEADERS]['Content-Type'] = 'application/vnd.api+json';
 
