Only call PrepareDateValues if not already called for tick
This commit is contained in:
parent
388841c1d8
commit
a3b0f809de
|
|
@ -13,15 +13,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
|||
/// </summary>
|
||||
public class DateHeaderValueManager : IDisposable
|
||||
{
|
||||
private static readonly byte[] _datePreambleBytes = Encoding.ASCII.GetBytes("\r\nDate: ");
|
||||
|
||||
private readonly ISystemClock _systemClock;
|
||||
private readonly TimeSpan _timeWithoutRequestsUntilIdle;
|
||||
private readonly TimeSpan _timerInterval;
|
||||
private readonly object _timerLocker = new object();
|
||||
|
||||
private DateHeaderValues _dateValues;
|
||||
|
||||
private volatile string _dateValue;
|
||||
private volatile bool _activeDateBytes;
|
||||
private readonly byte[] _dateBytes0 = Encoding.ASCII.GetBytes("\r\nDate: DDD, dd mmm yyyy hh:mm:ss GMT");
|
||||
private readonly byte[] _dateBytes1 = Encoding.ASCII.GetBytes("\r\nDate: DDD, dd mmm yyyy hh:mm:ss GMT");
|
||||
private object _timerLocker = new object();
|
||||
private volatile bool _isDisposed = false;
|
||||
private volatile bool _hadRequestsSinceLastTimerTick = false;
|
||||
private Timer _dateValueTimer;
|
||||
|
|
@ -55,19 +55,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
|||
/// 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.</returns>
|
||||
public virtual string GetDateHeaderValue()
|
||||
/// <returns>The value in string and byte[] format.</returns>
|
||||
public DateHeaderValues GetDateHeaderValues()
|
||||
{
|
||||
_hadRequestsSinceLastTimerTick = true;
|
||||
PrepareDateValues();
|
||||
return _dateValue;
|
||||
}
|
||||
if (!_hadRequestsSinceLastTimerTick)
|
||||
{
|
||||
PrepareDateValues();
|
||||
}
|
||||
|
||||
public byte[] GetDateHeaderValueBytes()
|
||||
{
|
||||
_hadRequestsSinceLastTimerTick = true;
|
||||
PrepareDateValues();
|
||||
return _activeDateBytes ? _dateBytes0 : _dateBytes1;
|
||||
return _dateValues;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -78,6 +74,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
|||
if (!_isDisposed)
|
||||
{
|
||||
_isDisposed = true;
|
||||
_hadRequestsSinceLastTimerTick = false;
|
||||
|
||||
lock (_timerLocker)
|
||||
{
|
||||
|
|
@ -125,6 +122,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
|||
{
|
||||
_timerIsRunning = false;
|
||||
_dateValueTimer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
_hadRequestsSinceLastTimerTick = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -158,16 +156,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
|||
/// </summary>
|
||||
private void PrepareDateValues()
|
||||
{
|
||||
if (_isDisposed)
|
||||
_hadRequestsSinceLastTimerTick = !_isDisposed;
|
||||
if (!_timerIsRunning)
|
||||
{
|
||||
SetDateValues(_systemClock.UtcNow);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_timerIsRunning)
|
||||
{
|
||||
StartTimer();
|
||||
}
|
||||
StartTimer();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -178,9 +170,23 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
|||
private void SetDateValues(DateTimeOffset value)
|
||||
{
|
||||
// See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.18 for required format of Date header
|
||||
_dateValue = value.ToString(Constants.RFC1123DateFormat);
|
||||
Encoding.ASCII.GetBytes(_dateValue, 0, _dateValue.Length, !_activeDateBytes ? _dateBytes0 : _dateBytes1, "\r\nDate: ".Length);
|
||||
_activeDateBytes = !_activeDateBytes;
|
||||
var dateValue = value.ToString(Constants.RFC1123DateFormat);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -589,12 +589,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
|
|||
|
||||
var responseHeaders = _frameHeaders.ResponseHeaders;
|
||||
responseHeaders.Reset();
|
||||
responseHeaders.SetRawDate(
|
||||
DateHeaderValueManager.GetDateHeaderValue(),
|
||||
DateHeaderValueManager.GetDateHeaderValueBytes());
|
||||
responseHeaders.SetRawServer(
|
||||
"Kestrel",
|
||||
Headers.BytesServer);
|
||||
var dateHeaderValues = DateHeaderValueManager.GetDateHeaderValues();
|
||||
responseHeaders.SetRawDate(dateHeaderValues.String, dateHeaderValues.Bytes);
|
||||
responseHeaders.SetRawServer("Kestrel", Headers.BytesServer);
|
||||
responseHeaders.SetRawContentLength("0", _bytesContentLengthZero);
|
||||
|
||||
ResponseHeaders = responseHeaders;
|
||||
|
|
|
|||
|
|
@ -78,9 +78,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Infrastructure
|
|||
|
||||
public void Initialize(DateHeaderValueManager dateValueManager)
|
||||
{
|
||||
ResponseHeaders.SetRawDate(
|
||||
dateValueManager.GetDateHeaderValue(),
|
||||
dateValueManager.GetDateHeaderValueBytes());
|
||||
var dateHeaderValues = dateValueManager.GetDateHeaderValues();
|
||||
ResponseHeaders.SetRawDate(dateHeaderValues.String, dateHeaderValues.Bytes);
|
||||
ResponseHeaders.SetRawServer("Kestrel", BytesServer);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
|
||||
try
|
||||
{
|
||||
result = dateHeaderValueManager.GetDateHeaderValue();
|
||||
result = dateHeaderValueManager.GetDateHeaderValues().String;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -54,9 +54,9 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
|
||||
try
|
||||
{
|
||||
result1 = dateHeaderValueManager.GetDateHeaderValue();
|
||||
result1 = dateHeaderValueManager.GetDateHeaderValues().String;
|
||||
systemClock.UtcNow = future;
|
||||
result2 = dateHeaderValueManager.GetDateHeaderValue();
|
||||
result2 = dateHeaderValueManager.GetDateHeaderValues().String;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -85,11 +85,11 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
|
||||
try
|
||||
{
|
||||
result1 = dateHeaderValueManager.GetDateHeaderValue();
|
||||
result1 = dateHeaderValueManager.GetDateHeaderValues().String;
|
||||
systemClock.UtcNow = future;
|
||||
// Wait for longer than the idle timeout to ensure the timer is stopped
|
||||
await Task.Delay(TimeSpan.FromSeconds(1));
|
||||
result2 = dateHeaderValueManager.GetDateHeaderValue();
|
||||
result2 = dateHeaderValueManager.GetDateHeaderValues().String;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -114,10 +114,10 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
var timerInterval = TimeSpan.FromSeconds(10);
|
||||
var dateHeaderValueManager = new DateHeaderValueManager(systemClock, timeWithoutRequestsUntilIdle, timerInterval);
|
||||
|
||||
var result1 = dateHeaderValueManager.GetDateHeaderValue();
|
||||
var result1 = dateHeaderValueManager.GetDateHeaderValues().String;
|
||||
dateHeaderValueManager.Dispose();
|
||||
systemClock.UtcNow = future;
|
||||
var result2 = dateHeaderValueManager.GetDateHeaderValue();
|
||||
var result2 = dateHeaderValueManager.GetDateHeaderValues().String;
|
||||
|
||||
Assert.Equal(now.ToString(Constants.RFC1123DateFormat), result1);
|
||||
Assert.Equal(future.ToString(Constants.RFC1123DateFormat), result2);
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
// 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 Microsoft.AspNetCore.Server.Kestrel.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||
{
|
||||
public class TestDateHeaderValueManager : DateHeaderValueManager
|
||||
{
|
||||
public override string GetDateHeaderValue()
|
||||
{
|
||||
return DateTimeOffset.UtcNow.ToString("r");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
AppLifetime = new LifetimeNotImplemented();
|
||||
Log = new TestKestrelTrace();
|
||||
ThreadPool = new LoggingThreadPool(Log);
|
||||
DateHeaderValueManager = new TestDateHeaderValueManager();
|
||||
DateHeaderValueManager = new DateHeaderValueManager();
|
||||
|
||||
ServerOptions = new KestrelServerOptions();
|
||||
ServerOptions.ShutdownTimeout = TimeSpan.FromSeconds(5);
|
||||
|
|
|
|||
Loading…
Reference in New Issue