annotate core/modules/big_pipe/src/Render/BigPipeResponse.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 4c8ae668cc8c
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\big_pipe\Render;
Chris@0 4
Chris@0 5 use Drupal\Core\Render\HtmlResponse;
Chris@0 6
Chris@0 7 /**
Chris@0 8 * A response that is sent in chunks by the BigPipe service.
Chris@0 9 *
Chris@0 10 * Note we cannot use \Symfony\Component\HttpFoundation\StreamedResponse because
Chris@0 11 * it makes the content inaccessible (hidden behind a callback), which means no
Chris@0 12 * middlewares are able to modify the content anymore.
Chris@0 13 *
Chris@0 14 * @see \Drupal\big_pipe\Render\BigPipe
Chris@0 15 *
Chris@0 16 * @internal
Chris@0 17 * This is a temporary solution until a generic response emitter interface is
Chris@0 18 * created in https://www.drupal.org/node/2577631. Only code internal to
Chris@0 19 * BigPipe should instantiate or type hint to this class.
Chris@0 20 */
Chris@0 21 class BigPipeResponse extends HtmlResponse {
Chris@0 22
Chris@0 23 /**
Chris@0 24 * The BigPipe service.
Chris@0 25 *
Chris@0 26 * @var \Drupal\big_pipe\Render\BigPipe
Chris@0 27 */
Chris@0 28 protected $bigPipe;
Chris@0 29
Chris@0 30 /**
Chris@0 31 * The original HTML response.
Chris@0 32 *
Chris@0 33 * Still contains placeholders. Its cacheability metadata and attachments are
Chris@0 34 * for everything except the placeholders (since those are not yet rendered).
Chris@0 35 *
Chris@0 36 * @see \Drupal\Core\Render\StreamedResponseInterface
Chris@0 37 * @see ::getStreamedResponse()
Chris@0 38 *
Chris@0 39 * @var \Drupal\Core\Render\HtmlResponse
Chris@0 40 */
Chris@0 41 protected $originalHtmlResponse;
Chris@0 42
Chris@0 43 /**
Chris@0 44 * Constructs a new BigPipeResponse.
Chris@0 45 *
Chris@0 46 * @param \Drupal\Core\Render\HtmlResponse $response
Chris@0 47 * The original HTML response.
Chris@0 48 */
Chris@0 49 public function __construct(HtmlResponse $response) {
Chris@0 50 parent::__construct('', $response->getStatusCode(), []);
Chris@0 51
Chris@0 52 $this->originalHtmlResponse = $response;
Chris@0 53
Chris@0 54 $this->populateBasedOnOriginalHtmlResponse();
Chris@0 55 }
Chris@0 56
Chris@0 57 /**
Chris@0 58 * Returns the original HTML response.
Chris@0 59 *
Chris@0 60 * @return \Drupal\Core\Render\HtmlResponse
Chris@0 61 * The original HTML response.
Chris@0 62 */
Chris@0 63 public function getOriginalHtmlResponse() {
Chris@0 64 return $this->originalHtmlResponse;
Chris@0 65 }
Chris@0 66
Chris@0 67 /**
Chris@0 68 * Populates this BigPipeResponse object based on the original HTML response.
Chris@0 69 */
Chris@0 70 protected function populateBasedOnOriginalHtmlResponse() {
Chris@0 71 // Clone the HtmlResponse's data into the new BigPipeResponse.
Chris@0 72 $this->headers = clone $this->originalHtmlResponse->headers;
Chris@0 73 $this
Chris@0 74 ->setStatusCode($this->originalHtmlResponse->getStatusCode())
Chris@0 75 ->setContent($this->originalHtmlResponse->getContent())
Chris@0 76 ->setAttachments($this->originalHtmlResponse->getAttachments())
Chris@0 77 ->addCacheableDependency($this->originalHtmlResponse->getCacheableMetadata());
Chris@0 78
Chris@0 79 // A BigPipe response can never be cached, because it is intended for a
Chris@0 80 // single user.
Chris@0 81 // @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1
Chris@0 82 $this->setPrivate();
Chris@0 83
Chris@0 84 // Inform surrogates how they should handle BigPipe responses:
Chris@0 85 // - "no-store" specifies that the response should not be stored in cache;
Chris@0 86 // it is only to be used for the original request
Chris@0 87 // - "content" identifies what processing surrogates should perform on the
Chris@0 88 // response before forwarding it. We send, "BigPipe/1.0", which surrogates
Chris@0 89 // should not process at all, and in fact, they should not even buffer it
Chris@0 90 // at all.
Chris@0 91 // @see http://www.w3.org/TR/edge-arch/
Chris@0 92 $this->headers->set('Surrogate-Control', 'no-store, content="BigPipe/1.0"');
Chris@0 93
Chris@0 94 // Add header to support streaming on NGINX + php-fpm (nginx >= 1.5.6).
Chris@0 95 $this->headers->set('X-Accel-Buffering', 'no');
Chris@0 96 }
Chris@0 97
Chris@0 98 /**
Chris@0 99 * Sets the BigPipe service to use.
Chris@0 100 *
Chris@0 101 * @param \Drupal\big_pipe\Render\BigPipe $big_pipe
Chris@0 102 * The BigPipe service.
Chris@0 103 */
Chris@0 104 public function setBigPipeService(BigPipe $big_pipe) {
Chris@0 105 $this->bigPipe = $big_pipe;
Chris@0 106 }
Chris@0 107
Chris@0 108 /**
Chris@0 109 * {@inheritdoc}
Chris@0 110 */
Chris@0 111 public function sendContent() {
Chris@0 112 $this->bigPipe->sendContent($this);
Chris@0 113
Chris@0 114 // All BigPipe placeholders are processed, so update this response's
Chris@0 115 // attachments.
Chris@0 116 unset($this->attachments['big_pipe_placeholders']);
Chris@0 117 unset($this->attachments['big_pipe_nojs_placeholders']);
Chris@0 118
Chris@0 119 return $this;
Chris@0 120 }
Chris@0 121
Chris@0 122 }