File: Internal\Http\DateHeaderValueManager.cs
Web Access
Project: src\src\Servers\Kestrel\Core\src\Microsoft.AspNetCore.Server.Kestrel.Core.csproj (Microsoft.AspNetCore.Server.Kestrel.Core)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Text;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.Net.Http.Headers;
 
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
 
/// <summary>
/// Manages the generation of the date header value.
/// </summary>
internal sealed class DateHeaderValueManager : IHeartbeatHandler
{
    // This uses C# compiler's ability to refer to static data directly. For more information see https://vcsjones.dev/2019/02/01/csharp-readonly-span-bytes-static
    private static ReadOnlySpan<byte> DatePreambleBytes => "\r\nDate: "u8;
 
    public TimeProvider _timeProvider;
 
    private DateHeaderValues? _dateValues;
 
    public DateHeaderValueManager(TimeProvider timeProvider)
    {
        _timeProvider = timeProvider;
    }
 
    /// <summary>
    /// Returns a value representing the current server date/time for use in the HTTP "Date" response header
    /// in accordance with http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.18
    /// </summary>
    /// <returns>The value in string and byte[] format.</returns>
    public DateHeaderValues GetDateHeaderValues() => _dateValues!;
 
    // Called by the Timer (background) thread
    public void OnHeartbeat()
    {
        SetDateValues();
    }
 
    /// <summary>
    /// Sets date values from a provided ticks value
    /// </summary>
    private void SetDateValues()
    {
        var value = _timeProvider.GetUtcNow();
        var dateValue = HeaderUtilities.FormatDate(value);
        var dateBytes = new byte[DatePreambleBytes.Length + dateValue.Length];
        DatePreambleBytes.CopyTo(dateBytes);
        Encoding.ASCII.GetBytes(dateValue, dateBytes.AsSpan(DatePreambleBytes.Length));
 
        var dateValues = new DateHeaderValues(dateBytes, dateValue);
        Volatile.Write(ref _dateValues, dateValues);
    }
 
    public sealed class DateHeaderValues
    {
        public readonly byte[] Bytes;
        public readonly string String;
 
        public DateHeaderValues(byte[] bytes, string s)
        {
            Bytes = bytes;
            String = s;
        }
    }
}