diff --git a/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php b/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php
index e3864610f4..f246cce462 100644
--- a/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php
+++ b/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php
@@ -46,7 +46,9 @@ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch =
     }
 
     // Determine the request format using the negotiator.
-    $request->setRequestFormat($this->getContentType($request));
+    if ($requested_format = $this->getContentType($request)) {
+      $request->setRequestFormat($requested_format);
+    }
     return $this->app->handle($request, $type, $catch);
   }
 
@@ -88,8 +90,8 @@ protected function getContentType(Request $request) {
       return $request->query->get('_format');
     }
 
-    // Do HTML last so that it always wins.
-    return 'html';
+    // No format was specified in the request.
+    return NULL;
   }
 
 }
diff --git a/core/modules/system/tests/modules/default_format_test/default_format_test.info.yml b/core/modules/system/tests/modules/default_format_test/default_format_test.info.yml
new file mode 100644
index 0000000000..0a02a0688a
--- /dev/null
+++ b/core/modules/system/tests/modules/default_format_test/default_format_test.info.yml
@@ -0,0 +1,6 @@
+name: 'Default format test'
+type: module
+description: 'Support module for testing default route format.'
+package: Testing
+version: VERSION
+core: 8.x
diff --git a/core/modules/system/tests/modules/default_format_test/default_format_test.routing.yml b/core/modules/system/tests/modules/default_format_test/default_format_test.routing.yml
new file mode 100644
index 0000000000..d29657cfb7
--- /dev/null
+++ b/core/modules/system/tests/modules/default_format_test/default_format_test.routing.yml
@@ -0,0 +1,17 @@
+default_format_test.machine:
+  path: '/default_format_test/machine'
+  defaults:
+    # Same controller + method!
+    _controller: '\Drupal\default_format_test\DefaultFormatTestController::content'
+  requirements:
+    _access: 'TRUE'
+    _format: 'json'
+
+default_format_test.human:
+  path: '/default_format_test/human'
+  defaults:
+    # Same controller + method!
+    _controller: '\Drupal\default_format_test\DefaultFormatTestController::content'
+  requirements:
+    _access: 'TRUE'
+    _format: 'html'
diff --git a/core/modules/system/tests/modules/default_format_test/src/DefaultFormatTestController.php b/core/modules/system/tests/modules/default_format_test/src/DefaultFormatTestController.php
new file mode 100644
index 0000000000..6e52eea342
--- /dev/null
+++ b/core/modules/system/tests/modules/default_format_test/src/DefaultFormatTestController.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace Drupal\default_format_test;
+
+use Drupal\Core\Cache\CacheableResponse;
+use Symfony\Component\HttpFoundation\Request;
+
+class DefaultFormatTestController {
+
+  public function content(Request $request) {
+    $format = $request->getRequestFormat();
+    return new CacheableResponse('format:' . $format, 200, ['Content-Type' => $request->getMimeType($format)]);
+  }
+
+}
diff --git a/core/tests/Drupal/FunctionalTests/Routing/DefaultFormatTest.php b/core/tests/Drupal/FunctionalTests/Routing/DefaultFormatTest.php
new file mode 100644
index 0000000000..fba590e06d
--- /dev/null
+++ b/core/tests/Drupal/FunctionalTests/Routing/DefaultFormatTest.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Drupal\FunctionalTests\Routing;
+
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * @group routing
+ */
+class DefaultFormatTest extends BrowserTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['system', 'default_format_test'];
+
+  public function testFoo() {
+    $this->drupalGet('/default_format_test/human');
+    $this->assertSame('format:html', $this->getSession()->getPage()->getContent());
+    $this->assertSame('MISS', $this->drupalGetHeader('X-Drupal-Cache'));
+
+    $this->drupalGet('/default_format_test/machine');
+    $this->assertSame('format:html', $this->getSession()->getPage()->getContent());
+    $this->assertSame('MISS', $this->drupalGetHeader('X-Drupal-Cache'));
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Core/StackMiddleware/NegotiationMiddlewareTest.php b/core/tests/Drupal/Tests/Core/StackMiddleware/NegotiationMiddlewareTest.php
index 0f5142c945..5ace79177f 100644
--- a/core/tests/Drupal/Tests/Core/StackMiddleware/NegotiationMiddlewareTest.php
+++ b/core/tests/Drupal/Tests/Core/StackMiddleware/NegotiationMiddlewareTest.php
@@ -68,10 +68,10 @@ public function testFormatViaQueryParameter() {
    *
    * @covers ::getContentType
    */
-  public function testUnknowContentTypeReturnsHtmlByDefault() {
+  public function testUnknowContentTypeReturnsNull() {
     $request = new Request();
 
-    $this->assertSame('html', $this->contentNegotiation->getContentType($request));
+    $this->assertNull($this->contentNegotiation->getContentType($request));
   }
 
   /**
@@ -83,7 +83,7 @@ public function testUnknowContentTypeButAjaxRequest() {
     $request = new Request();
     $request->headers->set('X-Requested-With', 'XMLHttpRequest');
 
-    $this->assertSame('html', $this->contentNegotiation->getContentType($request));
+    $this->assertNull($this->contentNegotiation->getContentType($request));
   }
 
   /**
@@ -98,7 +98,7 @@ public function testHandle() {
     $request->setFormat()->shouldNotBeCalled();
 
     // Request format will be set with default format.
-    $request->setRequestFormat('html')->shouldBeCalled();
+    $request->setRequestFormat()->shouldNotBeCalled();
 
     // Some getContentType calls we don't really care about but have to mock.
     $request_data = $this->prophesize(ParameterBag::class);
@@ -127,7 +127,7 @@ public function testSetFormat() {
     $request->setFormat('david', 'geeky/david')->shouldBeCalled();
 
     // Some calls we don't care about.
-    $request->setRequestFormat('html')->shouldBeCalled();
+    $request->setRequestFormat()->shouldNotBeCalled();
     $request_data = $this->prophesize(ParameterBag::class);
     $request_data->get('ajax_iframe_upload', FALSE)->shouldBeCalled();
     $request_mock = $request->reveal();
