/**
  * @covers ::processAttachments
  *
  * @dataProvider attachmentsProvider
  */
 public function testHtmlResponse(array $attachments)
 {
     $big_pipe_response = new BigPipeResponse('original');
     $big_pipe_response->setAttachments($attachments);
     // This mock is the main expectation of this test: verify that the decorated
     // service (that is this mock) never receives BigPipe placeholder
     // attachments, because it doesn't know (nor should it) how to handle them.
     $html_response_attachments_processor = $this->prophesize(AttachmentsResponseProcessorInterface::class);
     $html_response_attachments_processor->processAttachments(Argument::that(function ($response) {
         return $response instanceof HtmlResponse && empty(array_intersect(['big_pipe_placeholders', 'big_pipe_nojs_placeholders'], array_keys($response->getAttachments())));
     }))->will(function ($args) {
         /** @var \Symfony\Component\HttpFoundation\Response|\Drupal\Core\Render\AttachmentsInterface $response */
         $response = $args[0];
         // Simulate its actual behavior.
         $attachments = array_diff_key($response->getAttachments(), ['html_response_attachment_placeholders' => TRUE]);
         $response->setContent('processed');
         $response->setAttachments($attachments);
         return $response;
     })->shouldBeCalled();
     $big_pipe_response_attachments_processor = $this->createBigPipeResponseAttachmentsProcessor($html_response_attachments_processor);
     $processed_big_pipe_response = $big_pipe_response_attachments_processor->processAttachments($big_pipe_response);
     // The secondary expectation of this test: the original (passed in) response
     // object remains unchanged, the processed (returned) response object has
     // the expected values.
     $this->assertSame($attachments, $big_pipe_response->getAttachments(), 'Attachments of original response object MUST NOT be changed.');
     $this->assertEquals('original', $big_pipe_response->getContent(), 'Content of original response object MUST NOT be changed.');
     $this->assertEquals(array_diff_key($attachments, ['html_response_attachment_placeholders' => TRUE]), $processed_big_pipe_response->getAttachments(), 'Attachments of returned (processed) response object MUST be changed.');
     $this->assertEquals('processed', $processed_big_pipe_response->getContent(), 'Content of returned (processed) response object MUST be changed.');
 }
 /**
  * Transforms a HtmlResponse to a BigPipeResponse.
  *
  * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
  *   The event to process.
  */
 public function onRespond(FilterResponseEvent $event)
 {
     $response = $event->getResponse();
     if (!$response instanceof HtmlResponse) {
         return;
     }
     $attachments = $response->getAttachments();
     // If there are no no-JS BigPipe placeholders, unwrap the scripts_bottom
     // markup.
     // @see onRespondEarly()
     // @see \Drupal\big_pipe\Render\BigPipe::sendPreBody()
     if (empty($attachments['big_pipe_nojs_placeholders'])) {
         $content = $response->getContent();
         $content = str_replace('<drupal-big-pipe-scripts-bottom-marker>', '', $content);
         $response->setContent($content);
     }
     // If there are neither BigPipe placeholders nor no-JS BigPipe placeholders,
     // there isn't anything dynamic in this response, and we can return early:
     // there is no point in sending this response using BigPipe.
     if (empty($attachments['big_pipe_placeholders']) && empty($attachments['big_pipe_nojs_placeholders'])) {
         return;
     }
     $big_pipe_response = new BigPipeResponse();
     $big_pipe_response->setBigPipeService($this->bigPipe);
     // Clone the HtmlResponse's data into the new BigPipeResponse.
     $big_pipe_response->headers = clone $response->headers;
     $big_pipe_response->setStatusCode($response->getStatusCode())->setContent($response->getContent())->setAttachments($attachments)->addCacheableDependency($response->getCacheableMetadata());
     // A BigPipe response can never be cached, because it is intended for a
     // single user.
     // @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1
     $big_pipe_response->setPrivate();
     // Inform surrogates how they should handle BigPipe responses:
     // - "no-store" specifies that the response should not be stored in cache;
     //   it is only to be used for the original request
     // - "content" identifies what processing surrogates should perform on the
     //   response before forwarding it. We send, "BigPipe/1.0", which surrogates
     //   should not process at all, and in fact, they should not even buffer it
     //   at all.
     // @see http://www.w3.org/TR/edge-arch/
     $big_pipe_response->headers->set('Surrogate-Control', 'no-store, content="BigPipe/1.0"');
     // Add header to support streaming on NGINX + php-fpm (nginx >= 1.5.6).
     $big_pipe_response->headers->set('X-Accel-Buffering', 'no');
     $event->setResponse($big_pipe_response);
 }