Build modified streamline images

The official image from streamline does not currently work for the arm64
platform. As a temporary measure, the source code and docker build scripts
have been lifted from the official images and are used to build locally.

Some additional modifications are made to reduce overall image size, these
are documented in docker/README.md
This commit is contained in:
2024-03-10 16:17:50 -07:00
parent 2ffc3c408a
commit a424394109
13506 changed files with 1860172 additions and 6 deletions
@@ -0,0 +1,106 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Fragment;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\UriSigner;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface;
/**
* Implements Surrogate rendering strategy.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRenderer
{
private ?SurrogateInterface $surrogate;
private FragmentRendererInterface $inlineStrategy;
private ?UriSigner $signer;
/**
* The "fallback" strategy when surrogate is not available should always be an
* instance of InlineFragmentRenderer.
*
* @param FragmentRendererInterface $inlineStrategy The inline strategy to use when the surrogate is not supported
*/
public function __construct(?SurrogateInterface $surrogate, FragmentRendererInterface $inlineStrategy, ?UriSigner $signer = null)
{
$this->surrogate = $surrogate;
$this->inlineStrategy = $inlineStrategy;
$this->signer = $signer;
}
/**
* Note that if the current Request has no surrogate capability, this method
* falls back to use the inline rendering strategy.
*
* Additional available options:
*
* * alt: an alternative URI to render in case of an error
* * comment: a comment to add when returning the surrogate tag
* * absolute_uri: whether to generate an absolute URI or not. Default is false
*
* Note, that not all surrogate strategies support all options. For now
* 'alt' and 'comment' are only supported by ESI.
*
* @see Symfony\Component\HttpKernel\HttpCache\SurrogateInterface
*/
public function render(string|ControllerReference $uri, Request $request, array $options = []): Response
{
if (!$this->surrogate || !$this->surrogate->hasSurrogateCapability($request)) {
$request->attributes->set('_check_controller_is_allowed', -1); // @deprecated, switch to true in Symfony 7
if ($uri instanceof ControllerReference && $this->containsNonScalars($uri->attributes)) {
throw new \InvalidArgumentException('Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is not supported. Use a different rendering strategy or pass scalar values.');
}
return $this->inlineStrategy->render($uri, $request, $options);
}
$absolute = $options['absolute_uri'] ?? false;
if ($uri instanceof ControllerReference) {
$uri = $this->generateSignedFragmentUri($uri, $request, $absolute);
}
$alt = $options['alt'] ?? null;
if ($alt instanceof ControllerReference) {
$alt = $this->generateSignedFragmentUri($alt, $request, $absolute);
}
$tag = $this->surrogate->renderIncludeTag($uri, $alt, $options['ignore_errors'] ?? false, $options['comment'] ?? '');
return new Response($tag);
}
private function generateSignedFragmentUri(ControllerReference $uri, Request $request, bool $absolute): string
{
return (new FragmentUriGenerator($this->fragmentPath, $this->signer))->generate($uri, $request, $absolute);
}
private function containsNonScalars(array $values): bool
{
foreach ($values as $value) {
if (\is_scalar($value) || null === $value) {
continue;
}
if (!\is_array($value) || $this->containsNonScalars($value)) {
return true;
}
}
return false;
}
}
@@ -0,0 +1,25 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Fragment;
/**
* Implements the ESI rendering strategy.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class EsiFragmentRenderer extends AbstractSurrogateFragmentRenderer
{
public function getName(): string
{
return 'esi';
}
}
@@ -0,0 +1,111 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Fragment;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\Exception\HttpException;
/**
* Renders a URI that represents a resource fragment.
*
* This class handles the rendering of resource fragments that are included into
* a main resource. The handling of the rendering is managed by specialized renderers.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @see FragmentRendererInterface
*/
class FragmentHandler
{
private bool $debug;
private array $renderers = [];
private RequestStack $requestStack;
/**
* @param FragmentRendererInterface[] $renderers An array of FragmentRendererInterface instances
* @param bool $debug Whether the debug mode is enabled or not
*/
public function __construct(RequestStack $requestStack, array $renderers = [], bool $debug = false)
{
$this->requestStack = $requestStack;
foreach ($renderers as $renderer) {
$this->addRenderer($renderer);
}
$this->debug = $debug;
}
/**
* Adds a renderer.
*
* @return void
*/
public function addRenderer(FragmentRendererInterface $renderer)
{
$this->renderers[$renderer->getName()] = $renderer;
}
/**
* Renders a URI and returns the Response content.
*
* Available options:
*
* * ignore_errors: true to return an empty string in case of an error
*
* @throws \InvalidArgumentException when the renderer does not exist
* @throws \LogicException when no main request is being handled
*/
public function render(string|ControllerReference $uri, string $renderer = 'inline', array $options = []): ?string
{
if (!isset($options['ignore_errors'])) {
$options['ignore_errors'] = !$this->debug;
}
if (!isset($this->renderers[$renderer])) {
throw new \InvalidArgumentException(sprintf('The "%s" renderer does not exist.', $renderer));
}
if (!$request = $this->requestStack->getCurrentRequest()) {
throw new \LogicException('Rendering a fragment can only be done when handling a Request.');
}
return $this->deliver($this->renderers[$renderer]->render($uri, $request, $options));
}
/**
* Delivers the Response as a string.
*
* When the Response is a StreamedResponse, the content is streamed immediately
* instead of being returned.
*
* @return string|null The Response content or null when the Response is streamed
*
* @throws \RuntimeException when the Response is not successful
*/
protected function deliver(Response $response): ?string
{
if (!$response->isSuccessful()) {
$responseStatusCode = $response->getStatusCode();
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %d).', $this->requestStack->getCurrentRequest()->getUri(), $responseStatusCode), 0, new HttpException($responseStatusCode));
}
if (!$response instanceof StreamedResponse) {
return $response->getContent();
}
$response->sendContent();
return null;
}
}
@@ -0,0 +1,34 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Fragment;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
/**
* Interface implemented by all rendering strategies.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface FragmentRendererInterface
{
/**
* Renders a URI and returns the Response content.
*/
public function render(string|ControllerReference $uri, Request $request, array $options = []): Response;
/**
* Gets the name of the strategy.
*/
public function getName(): string;
}
@@ -0,0 +1,90 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Fragment;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\UriSigner;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
/**
* Generates a fragment URI.
*
* @author Kévin Dunglas <kevin@dunglas.fr>
* @author Fabien Potencier <fabien@symfony.com>
*/
final class FragmentUriGenerator implements FragmentUriGeneratorInterface
{
private string $fragmentPath;
private ?UriSigner $signer;
private ?RequestStack $requestStack;
public function __construct(string $fragmentPath, ?UriSigner $signer = null, ?RequestStack $requestStack = null)
{
$this->fragmentPath = $fragmentPath;
$this->signer = $signer;
$this->requestStack = $requestStack;
}
public function generate(ControllerReference $controller, ?Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string
{
if (null === $request && (null === $this->requestStack || null === $request = $this->requestStack->getCurrentRequest())) {
throw new \LogicException('Generating a fragment URL can only be done when handling a Request.');
}
if ($sign && null === $this->signer) {
throw new \LogicException('You must use a URI when using the ESI rendering strategy or set a URL signer.');
}
if ($strict) {
$this->checkNonScalar($controller->attributes);
}
// We need to forward the current _format and _locale values as we don't have
// a proper routing pattern to do the job for us.
// This makes things inconsistent if you switch from rendering a controller
// to rendering a route if the route pattern does not contain the special
// _format and _locale placeholders.
if (!isset($controller->attributes['_format'])) {
$controller->attributes['_format'] = $request->getRequestFormat();
}
if (!isset($controller->attributes['_locale'])) {
$controller->attributes['_locale'] = $request->getLocale();
}
$controller->attributes['_controller'] = $controller->controller;
$controller->query['_path'] = http_build_query($controller->attributes, '', '&');
$path = $this->fragmentPath.'?'.http_build_query($controller->query, '', '&');
// we need to sign the absolute URI, but want to return the path only.
$fragmentUri = $sign || $absolute ? $request->getUriForPath($path) : $request->getBaseUrl().$path;
if (!$sign) {
return $fragmentUri;
}
$fragmentUri = $this->signer->sign($fragmentUri);
return $absolute ? $fragmentUri : substr($fragmentUri, \strlen($request->getSchemeAndHttpHost()));
}
private function checkNonScalar(array $values): void
{
foreach ($values as $key => $value) {
if (\is_array($value)) {
$this->checkNonScalar($value);
} elseif (!\is_scalar($value) && null !== $value) {
throw new \LogicException(sprintf('Controller attributes cannot contain non-scalar/non-null values (value for key "%s" is not a scalar or null).', $key));
}
}
}
}
@@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Fragment;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
/**
* Interface implemented by rendering strategies able to generate a URL for a fragment.
*
* @author Kévin Dunglas <kevin@dunglas.fr>
*/
interface FragmentUriGeneratorInterface
{
/**
* Generates a fragment URI for a given controller.
*
* @param bool $absolute Whether to generate an absolute URL or not
* @param bool $strict Whether to allow non-scalar attributes or not
* @param bool $sign Whether to sign the URL or not
*/
public function generate(ControllerReference $controller, ?Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string;
}
@@ -0,0 +1,97 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Fragment;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\UriSigner;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Twig\Environment;
/**
* Implements the Hinclude rendering strategy.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class HIncludeFragmentRenderer extends RoutableFragmentRenderer
{
private ?string $globalDefaultTemplate;
private ?UriSigner $signer;
private ?Environment $twig;
private string $charset;
/**
* @param string|null $globalDefaultTemplate The global default content (it can be a template name or the content)
*/
public function __construct(?Environment $twig = null, ?UriSigner $signer = null, ?string $globalDefaultTemplate = null, string $charset = 'utf-8')
{
$this->twig = $twig;
$this->globalDefaultTemplate = $globalDefaultTemplate;
$this->signer = $signer;
$this->charset = $charset;
}
/**
* Checks if a templating engine has been set.
*/
public function hasTemplating(): bool
{
return null !== $this->twig;
}
/**
* Additional available options:
*
* * default: The default content (it can be a template name or the content)
* * id: An optional hx:include tag id attribute
* * attributes: An optional array of hx:include tag attributes
*/
public function render(string|ControllerReference $uri, Request $request, array $options = []): Response
{
if ($uri instanceof ControllerReference) {
$uri = (new FragmentUriGenerator($this->fragmentPath, $this->signer))->generate($uri, $request);
}
// We need to replace ampersands in the URI with the encoded form in order to return valid html/xml content.
$uri = str_replace('&', '&amp;', $uri);
$template = $options['default'] ?? $this->globalDefaultTemplate;
if (null !== $this->twig && $template && $this->twig->getLoader()->exists($template)) {
$content = $this->twig->render($template);
} else {
$content = $template;
}
$attributes = isset($options['attributes']) && \is_array($options['attributes']) ? $options['attributes'] : [];
if (isset($options['id']) && $options['id']) {
$attributes['id'] = $options['id'];
}
$renderedAttributes = '';
if (\count($attributes) > 0) {
$flags = \ENT_QUOTES | \ENT_SUBSTITUTE;
foreach ($attributes as $attribute => $value) {
$renderedAttributes .= sprintf(
' %s="%s"',
htmlspecialchars($attribute, $flags, $this->charset, false),
htmlspecialchars($value, $flags, $this->charset, false)
);
}
}
return new Response(sprintf('<hx:include src="%s"%s>%s</hx:include>', $uri, $renderedAttributes, $content));
}
public function getName(): string
{
return 'hinclude';
}
}
@@ -0,0 +1,147 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Fragment;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\HttpCache\SubRequestHandler;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
* Implements the inline rendering strategy where the Request is rendered by the current HTTP kernel.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class InlineFragmentRenderer extends RoutableFragmentRenderer
{
private HttpKernelInterface $kernel;
private ?EventDispatcherInterface $dispatcher;
public function __construct(HttpKernelInterface $kernel, ?EventDispatcherInterface $dispatcher = null)
{
$this->kernel = $kernel;
$this->dispatcher = $dispatcher;
}
/**
* Additional available options:
*
* * alt: an alternative URI to render in case of an error
*/
public function render(string|ControllerReference $uri, Request $request, array $options = []): Response
{
$reference = null;
if ($uri instanceof ControllerReference) {
$reference = $uri;
// Remove attributes from the generated URI because if not, the Symfony
// routing system will use them to populate the Request attributes. We don't
// want that as we want to preserve objects (so we manually set Request attributes
// below instead)
$attributes = $reference->attributes;
$reference->attributes = [];
// The request format and locale might have been overridden by the user
foreach (['_format', '_locale'] as $key) {
if (isset($attributes[$key])) {
$reference->attributes[$key] = $attributes[$key];
}
}
$uri = $this->generateFragmentUri($uri, $request, false, false);
$reference->attributes = array_merge($attributes, $reference->attributes);
}
$subRequest = $this->createSubRequest($uri, $request);
// override Request attributes as they can be objects (which are not supported by the generated URI)
if (null !== $reference) {
$subRequest->attributes->add($reference->attributes);
}
$level = ob_get_level();
try {
return SubRequestHandler::handle($this->kernel, $subRequest, HttpKernelInterface::SUB_REQUEST, false);
} catch (\Exception $e) {
// we dispatch the exception event to trigger the logging
// the response that comes back is ignored
if (isset($options['ignore_errors']) && $options['ignore_errors'] && $this->dispatcher) {
$event = new ExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e);
$this->dispatcher->dispatch($event, KernelEvents::EXCEPTION);
}
// let's clean up the output buffers that were created by the sub-request
Response::closeOutputBuffers($level, false);
if (isset($options['alt'])) {
$alt = $options['alt'];
unset($options['alt']);
return $this->render($alt, $request, $options);
}
if (!isset($options['ignore_errors']) || !$options['ignore_errors']) {
throw $e;
}
return new Response();
}
}
/**
* @return Request
*/
protected function createSubRequest(string $uri, Request $request)
{
$cookies = $request->cookies->all();
$server = $request->server->all();
unset($server['HTTP_IF_MODIFIED_SINCE']);
unset($server['HTTP_IF_NONE_MATCH']);
$subRequest = Request::create($uri, 'get', [], $cookies, [], $server);
if ($request->headers->has('Surrogate-Capability')) {
$subRequest->headers->set('Surrogate-Capability', $request->headers->get('Surrogate-Capability'));
}
static $setSession;
$setSession ??= \Closure::bind(static function ($subRequest, $request) { $subRequest->session = $request->session; }, null, Request::class);
$setSession($subRequest, $request);
if ($request->get('_format')) {
$subRequest->attributes->set('_format', $request->get('_format'));
}
if ($request->getDefaultLocale() !== $request->getLocale()) {
$subRequest->setLocale($request->getLocale());
}
if ($request->attributes->has('_stateless')) {
$subRequest->attributes->set('_stateless', $request->attributes->get('_stateless'));
}
if ($request->attributes->has('_check_controller_is_allowed')) {
$subRequest->attributes->set('_check_controller_is_allowed', $request->attributes->get('_check_controller_is_allowed'));
}
return $subRequest;
}
public function getName(): string
{
return 'inline';
}
}
@@ -0,0 +1,52 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Fragment;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\EventListener\FragmentListener;
/**
* Adds the possibility to generate a fragment URI for a given Controller.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
abstract class RoutableFragmentRenderer implements FragmentRendererInterface
{
/**
* @internal
*/
protected string $fragmentPath = '/_fragment';
/**
* Sets the fragment path that triggers the fragment listener.
*
* @see FragmentListener
*
* @return void
*/
public function setFragmentPath(string $path)
{
$this->fragmentPath = $path;
}
/**
* Generates a fragment URI for a given controller.
*
* @param bool $absolute Whether to generate an absolute URL or not
* @param bool $strict Whether to allow non-scalar attributes or not
*/
protected function generateFragmentUri(ControllerReference $reference, Request $request, bool $absolute = false, bool $strict = true): string
{
return (new FragmentUriGenerator($this->fragmentPath))->generate($reference, $request, $absolute, $strict, false);
}
}
@@ -0,0 +1,25 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpKernel\Fragment;
/**
* Implements the SSI rendering strategy.
*
* @author Sebastian Krebs <krebs.seb@gmail.com>
*/
class SsiFragmentRenderer extends AbstractSurrogateFragmentRenderer
{
public function getName(): string
{
return 'ssi';
}
}