diff --git a/src/System.Net.Http/src/System/Net/Http/Headers/HeaderUtilities.cs b/src/System.Net.Http/src/System/Net/Http/Headers/HeaderUtilities.cs index e18dea76b5bc..1952e3f129df 100644 --- a/src/System.Net.Http/src/System/Net/Http/Headers/HeaderUtilities.cs +++ b/src/System.Net.Http/src/System/Net/Http/Headers/HeaderUtilities.cs @@ -291,7 +291,7 @@ internal static int GetNextNonEmptyOrWhitespaceIndex(string input, int startInde return current; } - internal static DateTimeOffset? GetDateTimeOffsetValue(HeaderDescriptor descriptor, HttpHeaders store) + internal static DateTimeOffset? GetDateTimeOffsetValue(HeaderDescriptor descriptor, HttpHeaders store, DateTimeOffset? defaultValue = null) { Debug.Assert(store != null); @@ -300,6 +300,11 @@ internal static int GetNextNonEmptyOrWhitespaceIndex(string input, int startInde { return (DateTimeOffset)storedValue; } + else if (defaultValue != null && store.Contains(descriptor)) + { + return defaultValue; + } + return null; } diff --git a/src/System.Net.Http/src/System/Net/Http/Headers/HttpContentHeaders.cs b/src/System.Net.Http/src/System/Net/Http/Headers/HttpContentHeaders.cs index 974de64e83a6..c4bfb4ff3bee 100644 --- a/src/System.Net.Http/src/System/Net/Http/Headers/HttpContentHeaders.cs +++ b/src/System.Net.Http/src/System/Net/Http/Headers/HttpContentHeaders.cs @@ -133,7 +133,7 @@ public MediaTypeHeaderValue ContentType public DateTimeOffset? Expires { - get { return HeaderUtilities.GetDateTimeOffsetValue(KnownHeaders.Expires.Descriptor, this); } + get { return HeaderUtilities.GetDateTimeOffsetValue(KnownHeaders.Expires.Descriptor, this, DateTimeOffset.MinValue); } set { SetOrRemoveParsedValue(KnownHeaders.Expires.Descriptor, value); } } diff --git a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs index 5f5abc4b9013..9f8d33f86a19 100644 --- a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs +++ b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Headers.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net.Http.Headers; using System.Net.Test.Common; using System.Text; using System.Threading; @@ -21,6 +22,8 @@ public abstract class HttpClientHandlerTest_Headers : HttpClientHandlerTestBase { public HttpClientHandlerTest_Headers(ITestOutputHelper output) : base(output) { } + private sealed class DerivedHttpHeaders : HttpHeaders { } + [Fact] public async Task SendAsync_UserAgent_CorrectlyWritten() { @@ -94,6 +97,63 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => }); } + [Fact] + public async Task GetAsync_MissingExpires_ReturnNull() + { + await LoopbackServerFactory.CreateClientAndServerAsync(async uri => + { + using (var client = CreateHttpClient()) + { + HttpResponseMessage response = await client.GetAsync(uri); + Assert.Null(response.Content.Headers.Expires); + } + }, + async server => + { + await server.HandleRequestAsync(HttpStatusCode.OK); + }); + } + + [Theory] + [InlineData("Thu, 01 Dec 1994 16:00:00 GMT", true)] + [InlineData("-1", false)] + [InlineData("0", false)] + public async Task SendAsync_Expires_Success(string value, bool isValid) + { + await LoopbackServerFactory.CreateClientAndServerAsync(async uri => + { + using (var client = CreateHttpClient()) + { + var message = new HttpRequestMessage(HttpMethod.Get, uri); + HttpResponseMessage response = await client.SendAsync(message); + Assert.NotNull(response.Content.Headers.Expires); + // Invalid date should be converted to MinValue so everything is expired. + Assert.Equal(isValid ? DateTime.Parse(value) : DateTimeOffset.MinValue, response.Content.Headers.Expires); + } + }, + async server => + { + IList headers = new HttpHeaderData[] { new HttpHeaderData("Expires", value) }; + + HttpRequestData requestData = await server.HandleRequestAsync(HttpStatusCode.OK, headers); + }); + } + + [Theory] + [InlineData("-1", false)] + [InlineData("Thu, 01 Dec 1994 16:00:00 GMT", true)] + public void HeadersAdd_CustomExpires_Success(string value, bool isValid) + { + var headers = new DerivedHttpHeaders(); + if (!isValid) + { + Assert.Throws(() => headers.Add("Expires", value)); + } + Assert.True(headers.TryAddWithoutValidation("Expires", value)); + Assert.Equal(1, Enumerable.Count(headers.GetValues("Expires"))); + Assert.Equal(value, headers.GetValues("Expires").First()); + } + [OuterLoop("Uses external server")] [Theory] [InlineData(false)]