perf(auth): allocation-free token parsing; single partition-key build per RPC
This commit is contained in:
@@ -213,7 +213,10 @@ public sealed class CachingApiKeyVerifier : IApiKeyVerifier, IApiKeyCacheInvalid
|
||||
// DashboardApiKeyManagementService.ValidateKeyId each restrict a key id to
|
||||
// char.IsAsciiLetterOrDigit || '.' || '-'. Key ids are never library-generated, so no path can
|
||||
// mint one containing '_'.
|
||||
private static string? TryParseKeyId(string? authorizationHeader)
|
||||
//
|
||||
// Internal rather than private so the parse rules can be pinned directly by test: the guard's
|
||||
// correctness depends on this returning the full key id.
|
||||
internal static string? TryParseKeyId(string? authorizationHeader)
|
||||
{
|
||||
if (string.IsNullOrEmpty(authorizationHeader))
|
||||
{
|
||||
@@ -226,15 +229,29 @@ public sealed class CachingApiKeyVerifier : IApiKeyVerifier, IApiKeyCacheInvalid
|
||||
? header[bearer.Length..].Trim()
|
||||
: header;
|
||||
|
||||
string[] parts = token.ToString().Split('_');
|
||||
if (parts.Length < 3
|
||||
|| !string.Equals(parts[0], TokenPrefix, StringComparison.Ordinal)
|
||||
|| parts[1].Length == 0)
|
||||
// Scanned rather than split, for the same reason as the interceptor's copy: Split would
|
||||
// allocate a token copy, an array and a string per segment on every cache miss to produce
|
||||
// one key id. Two IndexOf scans allocate only that key id.
|
||||
//
|
||||
// The '_' checked immediately after the prefix is what makes "mxgw" the whole first segment
|
||||
// (so "mxgwabc_..." is still rejected), and the second separator must exist because the
|
||||
// split form required three segments — a token with no secret delimiter is not a key token.
|
||||
if (!token.StartsWith(TokenPrefix, StringComparison.Ordinal)
|
||||
|| token.Length <= TokenPrefix.Length
|
||||
|| token[TokenPrefix.Length] != '_')
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return parts[1];
|
||||
ReadOnlySpan<char> afterPrefix = token[(TokenPrefix.Length + 1)..];
|
||||
int separator = afterPrefix.IndexOf('_');
|
||||
if (separator <= 0)
|
||||
{
|
||||
// -1 is a token with no second separator; 0 is an empty key id.
|
||||
return null;
|
||||
}
|
||||
|
||||
return new string(afterPrefix[..separator]);
|
||||
}
|
||||
|
||||
private void IndexCacheKey(string keyId, string cacheKey)
|
||||
|
||||
Reference in New Issue
Block a user