Description
Building a resource uri with the default configuration will crash on CLI:
No base URI could be provided.
This probably means a call was made outside of an HTTP request and a base
URI was neither configured nor specified as $fallbackRequest.
The entry point ResourceManager::getPublicPackageResourceUri
calls TargetInterface::getPublicStaticResourceUri
which will use the configured target like localWebDirectoryStaticResourcesTarget
which in case of the FileSystemTarget and FileSystemSymlinkTarget
will call the BaseUriProvider::getConfiguredBaseUriOrFallbackToCurrentRequest
which uses $bootstrap->getActiveRequestHandler->getHttpRequest
which is not possible on CLI.
Possible workarounds include:
- statically set
localWebDirectoryStaticResourcesTarget.targetOptions.baseUri
tohttp://localhost:8081/_Resources/Static/Packages/
- statically set
Neos.Flow.http.baseUri
tohttp://localhost:8081
- hack the BaseUriProvider (see Get rid of configured baseUri #2157 (comment)) for dynamic multi site support
- hack by extending the targets to dynamically override
getResourcesBaseUri
https://github.com/Flowpack/Flowpack.DecoupledContentStore/blob/6adb8e04246f5fc9b8471b656db7ddf131474745/Classes/Transfer/Resource/Target/MultisiteFileSystemSymlinkTarget.php#L16-L38 - use
$this->bootstrap->setActiveRequestHandler($requestHandler);
and provide a customHttpRequestHandlerInterface
which provides a mockedgetHttpRequest()
(like during testing)
To actually fix this issue we should pass the current base uri to the target:
interface TargetInterface
{
public function getPublicStaticResourceUri(string $relativePathAndFilename, UriInterface $baseUri): string;
public function getPublicPersistentResourceUri(PersistentResource $resource, UriInterface $baseUri): string;
// ...
}
The methods are currently only used by the resource manager Neos & Flow.
And there we could allow a backwards compatible nullable parameter which will default to the current request:
class ResourceManager
{
public function getPublicPackageResourceUri(string $packageKey, string $relativePathAndFilename, ?UriInterface $baseUri = null): string
{
$baseUri ??= $this->generateBaseUriFromHttpRequest();
// ...
}
public function getPublicPersistentResourceUri(PersistentResource $resource, ?UriInterface $baseUri = null)
{
$baseUri ??= $this->generateBaseUriFromHttpRequest();
// ...
}
private function generateBaseUriFromHttpRequest(): ?UriInterface
{
// copied from the base uri provider without `Neos.Flow.http.baseUri` support
$activeRequestHandler = $this->bootstrap->getActiveRequestHandler();
if (!$activeRequestHandler instanceof HttpRequestHandlerInterface) {
return new Uri();
}
$request = $activeRequestHandler->getHttpRequest();
return RequestInformationHelper::generateBaseUri($request);
}
}
(i left out the demonstration for ResourceManager::getPublicPersistentResourceUriByHash
as its unused)
Meaning the resource manager can be used with fixed base uris
$this->resourceManager->getPublicPersistentResourceUri($resource, new Uri('http://localhost'));
or when leaving this parameter out, the previous default behaviour is used:
$this->resourceManager->getPublicPersistentResourceUri($resource);
a little more breaking would be do always enforce to specify the baseUri which would definitely be correct.
In Fusion we could start inside our prototypes to call getPublicPersistentResourceUri
with the base uri of the current
request and thus make the life a little easier ;)
- related bug cause BUG: NodeTypeManager can crash in cli context neos-development-collection#4888
- related Get rid of configured baseUri #2157
Alternative fixes
- Add a context switcher like
BaseUriProvider::applyBaseUriToClosure($newBaseUri, fn () => $resourcemanger->...(...))
- Add an environment variable like
FLOW_BASE_URI
see FEATURE: Make base URI configuration obsolete #3002- (like option 1 but less hacky to the eye, as it could be specified from outside flow ^^)
- Use empty base uri (host relative) and dont crash BUGFIX: Prevent
getPublicStaticResourceUri
from crashing in cli con… #3314