diff --git a/core/modules/rest/src/Plugin/views/display/RestExport.php b/core/modules/rest/src/Plugin/views/display/RestExport.php
index fb58513..77899fc 100644
--- a/core/modules/rest/src/Plugin/views/display/RestExport.php
+++ b/core/modules/rest/src/Plugin/views/display/RestExport.php
@@ -2,8 +2,11 @@
 
 namespace Drupal\rest\Plugin\views\display;
 
+use Drupal\Core\Cache\Cache;
+use Drupal\Core\Cache\CacheableDependencyInterface;
 use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Cache\CacheableResponse;
+use Drupal\Core\Cache\CacheableJsonResponse;
 use Drupal\Core\Render\RenderContext;
 use Drupal\Core\Render\RendererInterface;
 use Drupal\Core\Routing\RouteProviderInterface;
@@ -29,7 +32,7 @@
  *   returns_response = TRUE
  * )
  */
-class RestExport extends PathPluginBase implements ResponseDisplayPluginInterface {
+class RestExport extends PathPluginBase implements ResponseDisplayPluginInterface, CacheableDependencyInterface  {
 
   /**
    * {@inheritdoc}
@@ -282,7 +285,13 @@ public static function buildResponse($view_id, $display_id, array $args = []) {
 
     $output = $renderer->renderRoot($build);
 
-    $response = new CacheableResponse($output, 200);
+    if (isset($build['#jsonp_callback'])) {
+      $response = new CacheableJsonResponse($output, 200);
+      $response->setCallback($build['#jsonp_callback']);
+    }
+    else {
+      $response = new CacheableResponse($output, 200);
+    }
     $cache_metadata = CacheableMetadata::createFromRenderArray($build);
     $response->addCacheableDependency($cache_metadata);
 
@@ -309,7 +318,16 @@ public function render() {
       return $this->view->style_plugin->render();
     });
 
-    $this->view->element['#content_type'] = $this->getMimeType();
+    // Allow for JSONP response.
+    $callback = $this->view->getRequest()->get('jsonp') ?: $this->view->getRequest()->get('callback');
+    if ($callback) {
+      $this->view->element['#content_type'] = 'application/javascript';
+      $this->view->element['#jsonp_callback'] = $callback;
+    }
+    else {
+      $this->view->element['#content_type'] = $this->getMimeType();
+    }
+
     $this->view->element['#cache_properties'][] = '#content_type';
 
     // Encode and wrap the output in a pre tag if this is for a live preview.
@@ -348,4 +366,25 @@ public function preview() {
     return $this->view->render();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheMaxAge() {
+    return Cache::PERMANENT;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheContexts() {
+    return ['url.query_args:callback', 'url.query_args:jsonp'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheTags() {
+    return [];
+  }
+
 }
