// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Text;
using System.Threading;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{
///
/// Manages the generation of the date header value.
///
public class DateHeaderValueManager : IHeartbeatHandler
{
private static readonly byte[] _datePreambleBytes = Encoding.ASCII.GetBytes("\r\nDate: ");
private DateHeaderValues _dateValues;
///
/// Initializes a new instance of the class.
///
public DateHeaderValueManager()
: this(systemClock: new SystemClock())
{
}
// Internal for testing
internal DateHeaderValueManager(ISystemClock systemClock)
{
SetDateValues(systemClock.UtcNow);
}
///
/// 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
///
/// The value in string and byte[] format.
public DateHeaderValues GetDateHeaderValues() => _dateValues;
// Called by the Timer (background) thread
public void OnHeartbeat(DateTimeOffset now)
{
SetDateValues(now);
}
///
/// Sets date values from a provided ticks value
///
/// A DateTimeOffset value
private void SetDateValues(DateTimeOffset value)
{
var dateValue = HeaderUtilities.FormatDate(value);
var dateBytes = new byte[_datePreambleBytes.Length + dateValue.Length];
Buffer.BlockCopy(_datePreambleBytes, 0, dateBytes, 0, _datePreambleBytes.Length);
Encoding.ASCII.GetBytes(dateValue, 0, dateValue.Length, dateBytes, _datePreambleBytes.Length);
var dateValues = new DateHeaderValues()
{
Bytes = dateBytes,
String = dateValue
};
Volatile.Write(ref _dateValues, dateValues);
}
public class DateHeaderValues
{
public byte[] Bytes;
public string String;
}
}
}