| File: HeaderRegistry.cs | Web Access |
| Project: src\src\Libraries\Microsoft.AspNetCore.HeaderParsing\Microsoft.AspNetCore.HeaderParsing.csproj (Microsoft.AspNetCore.HeaderParsing) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; using System.Threading; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Microsoft.Shared.Diagnostics; namespace Microsoft.AspNetCore.HeaderParsing; internal sealed class HeaderRegistry : IHeaderRegistry { private readonly HeaderParsingOptions _options; private readonly IServiceProvider _provider; private readonly ConcurrentDictionary<HeaderKeyIdentity, object> _headerKeys = new(); private int _current = -1; public HeaderRegistry(IServiceProvider provider, IOptions<HeaderParsingOptions> options) { _provider = provider; _options = options.Value; } public HeaderKey<T> Register<T>(HeaderSetup<T> setup) where T : notnull { var parser = setup.ParserInstance ?? (HeaderParser<T>)_provider.GetRequiredService(setup.ParserType!); var id = new HeaderKeyIdentity(setup.HeaderName, parser, setup.Cacheable); return (HeaderKey<T>)_headerKeys.GetOrAdd(id, CreateKey<T>, parser); } private HeaderKey<T> CreateKey<T>(HeaderKeyIdentity id, HeaderParser<T> parser) where T : notnull { int maxCachedValues = 0; if (id.Cacheable) { if (!_options.MaxCachedValuesPerHeader.TryGetValue(id.HeaderName, out maxCachedValues)) { maxCachedValues = _options.DefaultMaxCachedValuesPerHeader; } } var pos = Interlocked.Increment(ref _current); if (_options.DefaultValues.TryGetValue(id.HeaderName, out var defValue)) { if (!parser.TryParse(defValue, out var parsedValue, out var error)) { Throw.InvalidOperationException($"Can't parse default value '{defValue}' for header '{id.HeaderName}': {error}."); } return new HeaderKey<T>(id.HeaderName, parser, pos, maxCachedValues, parsedValue); } return new HeaderKey<T>(id.HeaderName, parser, pos, maxCachedValues); } [ExcludeFromCodeCoverage] private readonly record struct HeaderKeyIdentity( string HeaderName, object Parser, bool Cacheable); }