diff options
| author | Dan Engelbrecht <[email protected]> | 2025-10-03 15:57:42 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2025-10-03 15:57:42 +0200 |
| commit | 42a2c2582b10a598ce5ef50f7feb4bab394b8fc1 (patch) | |
| tree | 267816281dcdbeda9900a38e6863265ecc257f15 /src/zenstore/cache/cache.cpp | |
| parent | 5.7.5-pre0 (diff) | |
| download | zen-42a2c2582b10a598ce5ef50f7feb4bab394b8fc1.tar.xz zen-42a2c2582b10a598ce5ef50f7feb4bab394b8fc1.zip | |
cacherequests helpers test only (#551)
* don't use cacherequests utils in cache_cmd.cpp
* make zenutil/cacherequests code into test code helpers only
Diffstat (limited to 'src/zenstore/cache/cache.cpp')
| -rw-r--r-- | src/zenstore/cache/cache.cpp | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/src/zenstore/cache/cache.cpp b/src/zenstore/cache/cache.cpp new file mode 100644 index 000000000..0436bfd7b --- /dev/null +++ b/src/zenstore/cache/cache.cpp @@ -0,0 +1,235 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include <zenstore/cache/cache.h> + +#include <zencore/logging.h> + +namespace zen { + +namespace { + constinit AsciiSet ValidNamespaceNameCharactersSet{"abcdefghijklmnopqrstuvwxyz0123456789-_.ABCDEFGHIJKLMNOPQRSTUVWXYZ"}; + constinit AsciiSet ValidBucketNameCharactersSet{"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"}; +} // namespace + +std::optional<std::string> +GetValidNamespaceName(std::string_view Name) +{ + if (Name.empty()) + { + ZEN_WARN("Namespace is invalid, empty namespace is not allowed"); + return {}; + } + + if (Name.length() > 64) + { + ZEN_WARN("Namespace '{}' is invalid, length exceeds 64 characters", Name); + return {}; + } + + if (!AsciiSet::HasOnly(Name, ValidNamespaceNameCharactersSet)) + { + ZEN_WARN("Namespace '{}' is invalid, invalid characters detected", Name); + return {}; + } + + return ToLower(Name); +} + +std::optional<std::string> +GetValidBucketName(std::string_view Name) +{ + if (Name.empty()) + { + ZEN_WARN("Bucket name is invalid, empty bucket name is not allowed"); + return {}; + } + + if (!AsciiSet::HasOnly(Name, ValidBucketNameCharactersSet)) + { + ZEN_WARN("Bucket name '{}' is invalid, invalid characters detected", Name); + return {}; + } + + return ToLower(Name); +} + +std::optional<IoHash> +GetValidIoHash(std::string_view Hash) +{ + if (Hash.length() != IoHash::StringLength) + { + return {}; + } + + IoHash KeyHash; + if (!ParseHexBytes(Hash.data(), Hash.size(), KeyHash.Hash)) + { + return {}; + } + return KeyHash; +} + +bool +HttpCacheRequestParseRelativeUri(std::string_view Key, std::string_view DefaultNamespace, HttpCacheRequestData& Data) +{ + std::vector<std::string_view> Tokens; + uint32_t TokenCount = ForEachStrTok(Key, '/', [&](const std::string_view& Token) { + Tokens.push_back(Token); + return true; + }); + + switch (TokenCount) + { + case 0: + return true; + case 1: + Data.Namespace = GetValidNamespaceName(Tokens[0]); + return Data.Namespace.has_value(); + case 2: + { + std::optional<IoHash> PossibleHashKey = GetValidIoHash(Tokens[1]); + if (PossibleHashKey.has_value()) + { + // Legacy bucket/key request + Data.Bucket = GetValidBucketName(Tokens[0]); + if (!Data.Bucket.has_value()) + { + return false; + } + Data.HashKey = PossibleHashKey; + Data.Namespace = DefaultNamespace; + return true; + } + Data.Namespace = GetValidNamespaceName(Tokens[0]); + if (!Data.Namespace.has_value()) + { + return false; + } + Data.Bucket = GetValidBucketName(Tokens[1]); + if (!Data.Bucket.has_value()) + { + return false; + } + return true; + } + case 3: + { + std::optional<IoHash> PossibleHashKey = GetValidIoHash(Tokens[1]); + if (PossibleHashKey.has_value()) + { + // Legacy bucket/key/valueid request + Data.Bucket = GetValidBucketName(Tokens[0]); + if (!Data.Bucket.has_value()) + { + return false; + } + Data.HashKey = PossibleHashKey; + Data.ValueContentId = GetValidIoHash(Tokens[2]); + if (!Data.ValueContentId.has_value()) + { + return false; + } + Data.Namespace = DefaultNamespace; + return true; + } + Data.Namespace = GetValidNamespaceName(Tokens[0]); + if (!Data.Namespace.has_value()) + { + return false; + } + Data.Bucket = GetValidBucketName(Tokens[1]); + if (!Data.Bucket.has_value()) + { + return false; + } + Data.HashKey = GetValidIoHash(Tokens[2]); + if (!Data.HashKey) + { + return false; + } + return true; + } + case 4: + { + Data.Namespace = GetValidNamespaceName(Tokens[0]); + if (!Data.Namespace.has_value()) + { + return false; + } + + Data.Bucket = GetValidBucketName(Tokens[1]); + if (!Data.Bucket.has_value()) + { + return false; + } + + Data.HashKey = GetValidIoHash(Tokens[2]); + if (!Data.HashKey.has_value()) + { + return false; + } + + Data.ValueContentId = GetValidIoHash(Tokens[3]); + if (!Data.ValueContentId.has_value()) + { + return false; + } + return true; + } + default: + return false; + } +} + +std::optional<std::string> +GetCacheRequestNamespace(const CbObjectView& Params) +{ + CbFieldView NamespaceField = Params["Namespace"]; + if (!NamespaceField) + { + return std::string("!default!"); // ZenCacheStore::DefaultNamespace); + } + + if (NamespaceField.HasError()) + { + return {}; + } + if (!NamespaceField.IsString()) + { + return {}; + } + return GetValidNamespaceName(NamespaceField.AsString()); +} + +bool +GetCacheRequestCacheKey(const CbObjectView& KeyView, CacheKey& Key) +{ + CbFieldView BucketField = KeyView["Bucket"]; + if (BucketField.HasError()) + { + return false; + } + if (!BucketField.IsString()) + { + return false; + } + std::optional<std::string> Bucket = GetValidBucketName(BucketField.AsString()); + if (!Bucket.has_value()) + { + return false; + } + CbFieldView HashField = KeyView["Hash"]; + if (HashField.HasError()) + { + return false; + } + if (!HashField.IsHash()) + { + return false; + } + Key.Bucket = *Bucket; + Key.Hash = HashField.AsHash(); + return true; +} + +} // namespace zen |