Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/13.1.1 hashed identifiers php 8.3 #6

Open
wants to merge 58 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
f08a8d1
Merge pull request #1 from lochmueller/master
weakbit Apr 7, 2021
42dcccb
[BUGFIX] only use the url if it is set
weakbit Apr 7, 2021
bb9a48f
[BUGFIX] flush to boostqueue will now work with hashed identifiers
weakbit Apr 8, 2021
92a7bd3
[TASK] removed debug output
weakbit Apr 15, 2021
48fe5f3
[BUGFIX] do not allow url to be null
weakbit Apr 15, 2021
34df38d
[FEATURE] always use hashed identifiers
weakbit Apr 22, 2021
1042901
[BUGFIX] in caching always use uri
weakbit Apr 22, 2021
4ad9d29
[BUGFIX] with boost queue fixes install tool clear cache for typo3v10
weakbit Apr 22, 2021
92dbefe
[FEATURE] provide possibility to let the stack know about the host we…
weakbit Jan 19, 2022
dfc71e8
[FEATURE] BREAKING adds multithread support for boostqueue
weakbit Jan 26, 2022
1d90c6a
[TASK] dispatch in outer loop for uptime monitoring
weakbit Jan 26, 2022
c472e2e
Merge pull request #2 from weakbit/bugfix/12.1.0-hashed-identifiers-m…
weakbit Jan 27, 2022
c36a80b
[FEATURE] BREAKING (for privileged server only yet) prevent from runn…
weakbit Jan 27, 2022
bbc956b
[FEATURE] reset pickups on start of our command
weakbit Jan 27, 2022
215236c
[FEATURE] readds the limit
weakbit Jan 31, 2022
67847df
[REGRESSION] removes fallback middleware - really use proper webserve…
weakbit Jan 31, 2022
3781707
[FEATURE] possibility to add basic auth for boosting
weakbit Jan 31, 2022
e9fc184
[BUGFIX] authentication has to be set in client
weakbit Jan 31, 2022
5ee0ceb
[BUGFIX]
weakbit Jan 31, 2022
705380a
[FEATURE] command to remove errorous entries
weakbit Jan 31, 2022
1916402
[TASK] change item limit for ram issues
weakbit Feb 1, 2022
610e54e
[FEATURE] speedup clear page cache with boost mode
weakbit Feb 2, 2022
8e71a27
[BUGFIX] chunk bulkInserts to avoid having too many placeholders in S…
weakbit Feb 2, 2022
82a0d28
[BUGFIX] if there is no cache entry do not increase them
weakbit Feb 2, 2022
92c2809
[BUGFIX] remove files from FS if the return code is not 200, introduc…
weakbit Feb 3, 2022
04ed745
remove hidden and deleted pages directly from cache
Kanti Feb 9, 2022
a46cf65
Merge pull request #3 from andersundsehr/bugfix/12.1.0-hashed-identif…
weakbit Feb 9, 2022
80e7367
[FEATURE] remove pages by their link builder url if the cache_staticf…
weakbit Feb 24, 2022
ef38445
Merge pull request #4 from weakbit/bugfix/remove-by-linkhandler-url
weakbit Feb 24, 2022
bd40a48
remove hidden and deleted pages directly from cache for translations …
Kanti Feb 25, 2022
90fa487
🐛 fix dubble absolute path in UriUtility
Kanti Feb 28, 2022
c3a0d98
Merge pull request #5 from andersundsehr/bugfix/remove-hidden-and-del…
weakbit Feb 28, 2022
2ceebda
🐛 make UriUtility more robust
Kanti Feb 28, 2022
346e47f
✨ remove default lang if hideIfDefaultLanguage is enabled
Kanti Feb 28, 2022
9b2544d
Merge pull request #6 from andersundsehr/bugfix/remove-hidden-and-del…
weakbit Feb 28, 2022
6832825
🐛 fix increaseCachePriorityByIdentifiers on some DB plattforms
Kanti Mar 3, 2022
7e4aaef
🐛 allow empty path for root level urls
Kanti Mar 4, 2022
dadcffe
[FEATURE] reenables garbage collection with the boostqueue preventing…
weakbit Mar 7, 2022
aae4fdc
Merge pull request #1 from andersundsehr/bugfix/12.1.0-hashed-identif…
weakbit Mar 8, 2022
016c039
[FEATURE] remove static files on return code > 299 and < 500 code cle…
weakbit Mar 8, 2022
b3c04b7
Merge pull request #2 from andersundsehr/feature/remove-non200non500-…
weakbit Mar 8, 2022
429deb1
[BUGFIX] if cache tags missing and link to a page with language could…
weakbit Mar 23, 2022
c06d082
[BUGFIX] fasten clearing cache if the tag tables do not contain their…
weakbit Apr 12, 2022
20dd904
[MERGE] bugfix/12.1.0-hashed-identifiers -> bugfix/12.1.0-hashed-iden…
weakbit Apr 12, 2022
1d3dcf8
[BUGFIX] check has to be done with hashed identifiers which support v…
weakbit Apr 12, 2022
bb846a2
Merge pull request #3 from andersundsehr/bugfix/12.1.0-hashed-identif…
weakbit Apr 12, 2022
43d7ac5
[BUGFIX] using hashed identifiers blows up cache_staticfilecache on s…
weakbit Dec 2, 2022
43ff5df
WIP merging bugfix/12.1.0-hashed-identifiers -> 12.5.0
weakbit Feb 21, 2023
825119a
Do not show a full process as it may stop before
weakbit Mar 23, 2023
a9cc6b1
Implement fixes and features from long URIs, and parallel boostqueue …
weakbit Aug 29, 2023
44b018c
Phpstan cleanup (v11 only)
weakbit Aug 31, 2023
aaf71f1
Split cache_url to identifier and url
weakbit Aug 31, 2023
af1932b
If the item is in queue already set its error to null on cache flush
weakbit Sep 21, 2023
03e84cc
Adds a retry possibility for previously failed boost queue items
weakbit Sep 22, 2023
95f6dda
fixup
weakbit Sep 22, 2023
d8cfabc
🐛 fix clear cache in install tool
Kanti Dec 8, 2023
e6cd322
chunk identifiers to prevent statement with too many placeholders
forxec Mar 19, 2024
52567dc
Merge branch 'andersundsehr:master' into bugfix/13.1.1-hashed-identif…
rtfirst Oct 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions Classes/Cache/IdentifierBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class IdentifierBuilder extends StaticFileCacheObject
*/
public function getFilepath(string $requestUri): string
{
if (!$this->isValidEntryIdentifier($requestUri)) {
if (!$this->isValidEntryUri($requestUri)) {
throw new \Exception('Invalid RequestUri as cache identifier: '.$requestUri, 2346782);
}
$urlParts = parse_url($requestUri);
Expand Down Expand Up @@ -51,16 +51,33 @@ public function getFilepath(string $requestUri): string
return $resultPath;
}

public function getUrl(string $filePath, int $stripPort): string
{
$p = strpos($filePath, '_');
$p2 = strpos($filePath, '_', $p + 1);
$first = substr($filePath, 0, $p) . '://' . substr($filePath, $p + 1, $p2 - $p - 1);
if ($stripPort && strpos($filePath, '_' . $stripPort)) {
return $first . substr($filePath, $p2 + 1 + strlen((string)$stripPort));
}

return $first . ':' . substr($filePath, $p2 + 1);
}

/**
* Check if the $requestUri is a valid base for cache identifier.
*/
public function isValidEntryIdentifier(string $requestUri): bool
public function isValidEntryIdentifier(string $identifier): bool
{
return preg_replace('/[a-z0-9]{64}/', '', $identifier) === '';
}

public function isValidEntryUri(string $requestUri): bool
{
if (false === GeneralUtility::isValidUrl($requestUri)) {
return false;
}
$urlParts = parse_url($requestUri);
$required = ['host', 'path', 'scheme'];
$required = ['host', 'scheme'];
foreach ($required as $item) {
if (!isset($urlParts[$item]) || mb_strlen($urlParts[$item]) <= 0) {
return false;
Expand All @@ -69,4 +86,9 @@ public function isValidEntryIdentifier(string $requestUri): bool

return true;
}

public function hash(string $requestUri): string
{
return hash('sha256', $requestUri);
}
}
98 changes: 62 additions & 36 deletions Classes/Cache/StaticFileBackend.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use TYPO3\CMS\Core\Cache\Exception\InvalidDataException;
use TYPO3\CMS\Core\Context\Context;
use Psr\EventDispatcher\EventDispatcherInterface;
use Exception;
use Psr\Http\Message\ResponseInterface;
use SFC\Staticfilecache\Domain\Repository\CacheRepository;
use SFC\Staticfilecache\Domain\Repository\QueueRepository;
Expand All @@ -17,7 +18,11 @@
use SFC\Staticfilecache\Service\GeneratorService;
use SFC\Staticfilecache\Service\QueueService;
use SFC\Staticfilecache\Service\RemoveService;
use SFC\Staticfilecache\Utility\UriUtility;
use Symfony\Component\Console\Output\NullOutput;
use TYPO3\CMS\Core\Cache\Backend\TransientBackendInterface;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
Expand All @@ -31,6 +36,14 @@
*/
class StaticFileBackend extends StaticDatabaseBackend implements TransientBackendInterface
{
protected IdentifierBuilder $identifierBuilder;

public function __construct($context, array $options = [])
{
parent::__construct($context, $options);
$this->identifierBuilder = GeneralUtility::makeInstance(IdentifierBuilder::class);
}

/**
* Saves data in the cache.
*
Expand Down Expand Up @@ -62,9 +75,7 @@ public function set($entryIdentifier, $data, array $tags = [], $lifetime = null)
}

$this->logger->debug('SFC Set', [$entryIdentifier, $tags, $lifetime]);

$identifierBuilder = GeneralUtility::makeInstance(IdentifierBuilder::class);
$fileName = $identifierBuilder->getFilepath($entryIdentifier);
$fileName = $this->identifierBuilder->getFilepath($entryIdentifier);

try {
// Create dir
Expand All @@ -73,21 +84,18 @@ public function set($entryIdentifier, $data, array $tags = [], $lifetime = null)
GeneralUtility::mkdir_deep($cacheDir);
}

if ($this->isHashedIdentifier()) {
$databaseData['url'] = $entryIdentifier;
$entryIdentifierForDatabase = $this->hash($entryIdentifier);
} else {
$entryIdentifierForDatabase = $entryIdentifier;
}
$databaseData['url'] = $entryIdentifier;
$entryIdentifierForDatabase = $this->identifierBuilder->hash($entryIdentifier);

// call set in front of the generation, because the set method
// of the DB backend also call remove (this remove do not remove the folder already created above)
$this->removeFromDatabase($entryIdentifierForDatabase);
parent::set($entryIdentifierForDatabase, serialize($databaseData), $tags, $realLifetime);

$this->removeStaticFiles($entryIdentifier);

GeneralUtility::makeInstance(GeneratorService::class)->generate($entryIdentifier, $fileName, $data, $realLifetime);
} catch (\Exception $exception) {
} catch (Exception $exception) {
$this->logger->error('Error in cache create process', ['exception' => $exception]);
}
}
Expand All @@ -104,12 +112,12 @@ public function get($entryIdentifier)
if (!$this->has($entryIdentifier)) {
return false;
}
$result = parent::get($entryIdentifier);
$result = parent::get($this->identifierBuilder->hash($entryIdentifier));
if (!\is_string($result)) {
return false;
}

return unserialize($result);
return unserialize($result, ['allowed_classes' => false]);
}

/**
Expand All @@ -121,7 +129,16 @@ public function get($entryIdentifier)
*/
public function has($entryIdentifier)
{
return is_file($this->getFilepath($entryIdentifier)) || parent::has($entryIdentifier);
if (!$entryIdentifier) {
return false;
}

if (GeneralUtility::isValidUrl($entryIdentifier)) {
$entryIdentifierForDatabase = $this->identifierBuilder->hash($entryIdentifier);
} else {
$entryIdentifierForDatabase = $entryIdentifier;
}
return is_file($this->getFilepath($entryIdentifier)) && parent::has($entryIdentifierForDatabase);
}

/**
Expand All @@ -143,7 +160,7 @@ public function remove($entryIdentifier)

if ($this->isBoostMode()) {
$this->getQueue()
->addIdentifier($entryIdentifier)
->addIdentifiers([$entryIdentifier])
;

return true;
Expand Down Expand Up @@ -242,6 +259,7 @@ public function flushByTag($tag): void
if ($this->isBoostMode()) {
$this->getQueue()->addIdentifiers($identifiers);


return;
}

Expand All @@ -253,27 +271,21 @@ public function flushByTag($tag): void

/**
* Does garbage collection.
*
* Note: Do not check boostmode. If we check boost mode, we get the problem, that the core garbage collection drop
* the DB related part of StaticFileCache but not the files, because the "garbage collection" works directly on
* the caching backends and not on the caches itself. By ignoring the boost mode in this function we take care,
* that the StaticFileCache drop the file AND the db representation. Please take care, that you select both backends
* in the garbage collection task in the Scheduler.
*/
public function collectGarbage(): void
{
$expiredIdentifiers = GeneralUtility::makeInstance(CacheRepository::class)->findExpiredIdentifiers();
if ($this->isBoostMode()) {
$this->getQueue()->addIdentifiers($expiredIdentifiers);
parent::collectGarbage();
return;
}
parent::collectGarbage();
foreach ($expiredIdentifiers as $identifier) {
$this->removeStaticFiles($identifier);
}
}

protected function hash(string $entryIdentifier): string
{
return hash('sha256', $entryIdentifier);
}

/**
* Get prority.
*
Expand All @@ -300,16 +312,20 @@ protected function getPriority(string $uri)
*/
protected function getFilepath(string $entryIdentifier): string
{
$url = $entryIdentifier;
if ($this->isHashedIdentifier()) {
if (GeneralUtility::isValidUrl($entryIdentifier)) {
$url = $entryIdentifier;
} else {
$data = parent::get($entryIdentifier);
if (!$data) {
return '';
}
$entry = unserialize($data);
if (!empty($entry['url'])) {
$url = $entry['url'];

$entry = unserialize($data, ['allowed_classes' => false]);
if (empty($entry['url'])) {
return '';
}

$url = $entry['url'];
}
$identifierBuilder = GeneralUtility::makeInstance(IdentifierBuilder::class);

Expand Down Expand Up @@ -357,7 +373,7 @@ protected function getQueue(): QueueService
// Build Queue Service manually, because here is no DI
$queueService = GeneralUtility::makeInstance(
QueueService::class,
GeneralUtility::makeInstance(QueueRepository::class),
GeneralUtility::makeInstance(QueueRepository::class, GeneralUtility::makeInstance(ConfigurationService::class)),
GeneralUtility::makeInstance(ConfigurationService::class),
GeneralUtility::makeInstance(ClientService::class, GeneralUtility::makeInstance(EventDispatcherInterface::class)),
GeneralUtility::makeInstance(CacheService::class)
Expand All @@ -380,11 +396,21 @@ protected function isBoostMode(): bool
return (bool) $this->configuration->get('boostMode');
}

/**
* Check if the "hashUriInCache" feature is enabled.
*/
protected function isHashedIdentifier(): bool
protected function removeFromDatabase(string $entryIdentifierForDatabase)
{
return (bool) $this->configuration->isBool('hashUriInCache');
GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable($this->cacheTable)
->delete(
$this->cacheTable,
[
'identifier' => $entryIdentifierForDatabase,
]
);

GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable($this->tagsTable)
->delete($this->tagsTable, [
'identifier' => $entryIdentifierForDatabase,
]);
}
}
31 changes: 27 additions & 4 deletions Classes/Cache/UriFrontend.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,44 @@ class UriFrontend extends VariableFrontend
/**
* Check if the identifier is a valid URI incl. host and path.
*
* @param string $identifier
* @param string $requestUri
*
* @return bool
*/
public function isValidEntryIdentifier($identifier)
public function isValidEntryIdentifier($requestUri)
{
try {
$identifierBuilder = GeneralUtility::makeInstance(IdentifierBuilder::class);

return $identifierBuilder->isValidEntryIdentifier($identifier);
return $identifierBuilder->isValidEntryUri($requestUri);
} catch (\Exception $exception) {
return false;
}
}

/**
* Finds and returns a variable value from the cache.
*
* @param string $entryIdentifier Identifier of the cache entry to fetch
*
* @return mixed The value
* @throws \InvalidArgumentException if the identifier is not valid
*/
public function get($entryIdentifier)
{
$identifierBuilder = GeneralUtility::makeInstance(IdentifierBuilder::class);
if (!$identifierBuilder->isValidEntryUri($entryIdentifier)) {
throw new \InvalidArgumentException(
$entryIdentifier . '" is not a valid cache entry identifier.',
1233058294
);
}
$rawResult = $this->backend->get($entryIdentifier);
if ($rawResult === false) {
return false;
}
return $this->backend instanceof TransientBackendInterface ? $rawResult : unserialize($rawResult, ['allowed_classes' => false]);
}

/**
* Finds and returns all cache entries which are tagged by the specified tag.
*
Expand Down
Loading