diff --git a/src/Microsoft.AspNet.Http.Extensions/HeaderDictionaryTypeExtensions.cs b/src/Microsoft.AspNet.Http.Extensions/HeaderDictionaryTypeExtensions.cs index 02178a65cd..db8eb01b76 100644 --- a/src/Microsoft.AspNet.Http.Extensions/HeaderDictionaryTypeExtensions.cs +++ b/src/Microsoft.AspNet.Http.Extensions/HeaderDictionaryTypeExtensions.cs @@ -23,12 +23,14 @@ namespace Microsoft.AspNet.Http return new ResponseHeaders(response.Headers); } - public static DateTimeOffset? GetDate([NotNull] this IHeaderDictionary headers, [NotNull] string name) + // These are all shared helpers used by both RequestHeaders and ResponseHeaders + + internal static DateTimeOffset? GetDate([NotNull] this IHeaderDictionary headers, [NotNull] string name) { return headers.Get(name); } - public static void Set([NotNull] this IHeaderDictionary headers, [NotNull] string name, object value) + internal static void Set([NotNull] this IHeaderDictionary headers, [NotNull] string name, object value) { if (value == null) { @@ -40,7 +42,7 @@ namespace Microsoft.AspNet.Http } } - public static void SetList([NotNull] this IHeaderDictionary headers, [NotNull] string name, IList values) + internal static void SetList([NotNull] this IHeaderDictionary headers, [NotNull] string name, IList values) { if (values == null || values.Count == 0) { @@ -52,7 +54,7 @@ namespace Microsoft.AspNet.Http } } - public static void SetDate([NotNull] this IHeaderDictionary headers, [NotNull] string name, DateTimeOffset? value) + internal static void SetDate([NotNull] this IHeaderDictionary headers, [NotNull] string name, DateTimeOffset? value) { if (value.HasValue) { @@ -64,16 +66,6 @@ namespace Microsoft.AspNet.Http } } - public static void Append([NotNull] this IHeaderDictionary headers, [NotNull] string name, [NotNull] object value) - { - headers.Append(name, value.ToString()); - } - - public static void AppendList([NotNull] this IHeaderDictionary headers, [NotNull] string name, [NotNull] IList values) - { - headers.AppendValues(name, values.Select(value => value.ToString()).ToArray()); - } - private static IDictionary KnownParsers = new Dictionary() { { typeof(CacheControlHeaderValue), new Func(value => { CacheControlHeaderValue result; return CacheControlHeaderValue.TryParse(value, out result) ? result : null; }) }, @@ -96,7 +88,7 @@ namespace Microsoft.AspNet.Http { typeof(SetCookieHeaderValue), new Func, IList>(value => { IList result; return SetCookieHeaderValue.TryParseList(value, out result) ? result : null; }) }, }; - public static T Get([NotNull] this IHeaderDictionary headers, string name) + internal static T Get([NotNull] this IHeaderDictionary headers, string name) { object temp; if (KnownParsers.TryGetValue(typeof(T), out temp)) @@ -114,7 +106,7 @@ namespace Microsoft.AspNet.Http return GetViaReflection(value); } - public static IList GetList([NotNull] this IHeaderDictionary headers, string name) + internal static IList GetList([NotNull] this IHeaderDictionary headers, string name) { object temp; if (KnownListParsers.TryGetValue(typeof(T), out temp)) diff --git a/src/Microsoft.AspNet.Http.Extensions/HttpResponseSendingExtensions.cs b/src/Microsoft.AspNet.Http.Extensions/HttpResponseSendingExtensions.cs deleted file mode 100644 index 40d4f1c3c7..0000000000 --- a/src/Microsoft.AspNet.Http.Extensions/HttpResponseSendingExtensions.cs +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) Microsoft Open Technologies, Inc. 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 System.Threading.Tasks; -using Microsoft.Framework.Internal; - -namespace Microsoft.AspNet.Http -{ - /// - /// Convenience methods for writing to the response. - /// - public static class HttpResponseSendingExtensions - { - /// - /// Sends a response with the given Content-Type and body. UTF-8 encoding will be used, and the Content-Length header will be set accordingly. - /// - /// - /// - /// - /// - /// - public static Task SendAsync([NotNull] this HttpResponse response, [NotNull] string text, [NotNull] string contentType, CancellationToken cancellationToken = default(CancellationToken)) - { - return response.SendAsync(text, Encoding.UTF8, contentType, cancellationToken); - } - - /// - /// Sends a response with the given Content-Type, encoding, and body. The Content-Length header will be set accordingly. - /// - /// - /// - /// - /// - /// - /// - public static Task SendAsync([NotNull] this HttpResponse response, [NotNull] string text, [NotNull] Encoding encoding, [NotNull] string contentType, CancellationToken cancellationToken = default(CancellationToken)) - { - if (string.IsNullOrEmpty(contentType)) - { - throw new ArgumentException("Empty Content-Type is not allowed."); - } - if (contentType.IndexOf("charset=", StringComparison.OrdinalIgnoreCase) < 0) - { - contentType += "; charset=" + encoding.WebName; - } - response.ContentType = contentType; - return response.SendAsync(text, encoding, cancellationToken); - } - - /// - /// Sends a response with the given body. UTF-8 encoding will be used, and the Content-Length header will be set accordingly. - /// - /// - /// - /// - /// - public static Task SendAsync([NotNull] this HttpResponse response, [NotNull] string text, CancellationToken cancellationToken = default(CancellationToken)) - { - return response.SendAsync(text, Encoding.UTF8, cancellationToken); - } - - /// - /// Sends a response with the given encoding and body. The Content-Length header will be set accordingly. - /// - /// - /// - /// - /// - /// - public static Task SendAsync([NotNull] this HttpResponse response, [NotNull] string text, [NotNull] Encoding encoding, CancellationToken cancellationToken = default(CancellationToken)) - { - byte[] data = encoding.GetBytes(text); - return response.SendAsync(data, cancellationToken); - } - - /// - /// Sends a response with the given Content-Type and body. The Content-Length header will be set accordingly. - /// - /// - /// - /// - /// - /// - public static Task SendAsync([NotNull] this HttpResponse response, [NotNull] byte[] data, [NotNull] string contentType, CancellationToken cancellationToken = default(CancellationToken)) - { - return response.SendAsync(new ArraySegment(data), contentType, cancellationToken); - } - - /// - /// Sends a response with the given Content-Type and body. The Content-Length header will be set accordingly. - /// - /// - /// - /// - /// - /// - public static Task SendAsync([NotNull] this HttpResponse response, ArraySegment data, [NotNull] string contentType, CancellationToken cancellationToken = default(CancellationToken)) - { - if (string.IsNullOrEmpty(contentType)) - { - throw new ArgumentException("Empty Content-Type is not allowed."); - } - response.ContentType = contentType; - return response.SendAsync(data, cancellationToken); - } - - /// - /// Sends a response with the given body. The Content-Length header will be set accordingly. - /// - /// - /// - /// - /// - public static Task SendAsync([NotNull] this HttpResponse response, [NotNull] byte[] data, CancellationToken cancellationToken = default(CancellationToken)) - { - return response.SendAsync(new ArraySegment(data), cancellationToken); - } - - /// - /// Sends a response with the given body. The Content-Length header will be set accordingly. - /// - /// - /// - /// - /// - /// - /// - public static Task SendAsync([NotNull] this HttpResponse response, [NotNull] byte[] data, int offset, int count, CancellationToken cancellationToken = default(CancellationToken)) - { - return response.SendAsync(new ArraySegment(data, offset, count), cancellationToken); - } - - /// - /// Sends a response with the given body. The Content-Length header will be set accordingly. - /// - /// - /// - /// - /// - public static Task SendAsync([NotNull] this HttpResponse response, ArraySegment data, CancellationToken cancellationToken = default(CancellationToken)) - { - if (data.Array == null) - { - throw new ArgumentException("The Array cannot be null.", "data"); // TODO: LOC - } - response.ContentLength = data.Count; - return response.Body.WriteAsync(data.Array, data.Offset, data.Count, cancellationToken); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Http.Extensions/RequestHeaders.cs b/src/Microsoft.AspNet.Http.Extensions/RequestHeaders.cs index 21499b8092..fb10af0bab 100644 --- a/src/Microsoft.AspNet.Http.Extensions/RequestHeaders.cs +++ b/src/Microsoft.AspNet.Http.Extensions/RequestHeaders.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.Framework.Internal; using Microsoft.Net.Http.Headers; @@ -256,5 +257,35 @@ namespace Microsoft.AspNet.Http.Headers Headers.Set(HeaderNames.Range, value); } } + + public T Get(string name) + { + return Headers.Get(name); + } + + public IList GetList(string name) + { + return Headers.GetList(name); + } + + public void Set([NotNull] string name, object value) + { + Headers.Set(name, value); + } + + public void SetList([NotNull] string name, IList values) + { + Headers.SetList(name, values); + } + + public void Append([NotNull] string name, [NotNull] object value) + { + Headers.Append(name, value.ToString()); + } + + public void AppendList([NotNull] string name, [NotNull] IList values) + { + Headers.AppendValues(name, values.Select(value => value.ToString()).ToArray()); + } } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Http.Extensions/ResponseHeaders.cs b/src/Microsoft.AspNet.Http.Extensions/ResponseHeaders.cs index c88430eed8..3f4103ab83 100644 --- a/src/Microsoft.AspNet.Http.Extensions/ResponseHeaders.cs +++ b/src/Microsoft.AspNet.Http.Extensions/ResponseHeaders.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.AspNet.Http.Extensions; using Microsoft.Framework.Internal; using Microsoft.Net.Http.Headers; @@ -153,5 +154,35 @@ namespace Microsoft.AspNet.Http.Headers Headers.SetList(HeaderNames.SetCookie, value); } } + + public T Get(string name) + { + return Headers.Get(name); + } + + public IList GetList(string name) + { + return Headers.GetList(name); + } + + public void Set([NotNull] string name, object value) + { + Headers.Set(name, value); + } + + public void SetList([NotNull] string name, IList values) + { + Headers.SetList(name, values); + } + + public void Append([NotNull] string name, [NotNull] object value) + { + Headers.Append(name, value.ToString()); + } + + public void AppendList([NotNull] string name, [NotNull] IList values) + { + Headers.AppendValues(name, values.Select(value => value.ToString()).ToArray()); + } } } \ No newline at end of file diff --git a/test/Microsoft.AspNet.Http.Extensions.Tests/HeaderDictionaryTypeExtensionsTest.cs b/test/Microsoft.AspNet.Http.Extensions.Tests/HeaderDictionaryTypeExtensionsTest.cs index ccd20be196..4495cbb364 100644 --- a/test/Microsoft.AspNet.Http.Extensions.Tests/HeaderDictionaryTypeExtensionsTest.cs +++ b/test/Microsoft.AspNet.Http.Extensions.Tests/HeaderDictionaryTypeExtensionsTest.cs @@ -15,10 +15,10 @@ namespace Microsoft.AspNet.Http.Headers [Fact] public void GetT_KnownTypeWithValidValue_Success() { - var headers = new HeaderDictionary(); - headers[HeaderNames.ContentType] = "text/plain"; + var context = new DefaultHttpContext(); + context.Request.Headers[HeaderNames.ContentType] = "text/plain"; - var result = headers.Get(HeaderNames.ContentType); + var result = context.Request.GetTypedHeaders().Get(HeaderNames.ContentType); var expected = new MediaTypeHeaderValue("text/plain"); Assert.Equal(expected, result); @@ -27,9 +27,9 @@ namespace Microsoft.AspNet.Http.Headers [Fact] public void GetT_KnownTypeWithMissingValue_Null() { - var headers = new HeaderDictionary(); + var context = new DefaultHttpContext(); - var result = headers.Get(HeaderNames.ContentType); + var result = context.Request.GetTypedHeaders().Get(HeaderNames.ContentType); Assert.Null(result); } @@ -37,10 +37,10 @@ namespace Microsoft.AspNet.Http.Headers [Fact] public void GetT_KnownTypeWithInvalidValue_Null() { - var headers = new HeaderDictionary(); - headers[HeaderNames.ContentType] = "invalid"; + var context = new DefaultHttpContext(); + context.Request.Headers[HeaderNames.ContentType] = "invalid"; - var result = headers.Get(HeaderNames.ContentType); + var result = context.Request.GetTypedHeaders().Get(HeaderNames.ContentType); Assert.Null(result); } @@ -48,48 +48,48 @@ namespace Microsoft.AspNet.Http.Headers [Fact] public void GetT_UnknownTypeWithTryParseAndValidValue_Success() { - var headers = new HeaderDictionary(); - headers["custom"] = "valid"; + var context = new DefaultHttpContext(); + context.Request.Headers["custom"] = "valid"; - var result = headers.Get("custom"); + var result = context.Request.GetTypedHeaders().Get("custom"); Assert.NotNull(result); } [Fact] public void GetT_UnknownTypeWithTryParseAndInvalidValue_Null() { - var headers = new HeaderDictionary(); - headers["custom"] = "invalid"; + var context = new DefaultHttpContext(); + context.Request.Headers["custom"] = "invalid"; - var result = headers.Get("custom"); + var result = context.Request.GetTypedHeaders().Get("custom"); Assert.Null(result); } [Fact] public void GetT_UnknownTypeWithTryParseAndMissingValue_Null() { - var headers = new HeaderDictionary(); + var context = new DefaultHttpContext(); - var result = headers.Get("custom"); + var result = context.Request.GetTypedHeaders().Get("custom"); Assert.Null(result); } [Fact] public void GetT_UnknownTypeWithoutTryParse_Throws() { - var headers = new HeaderDictionary(); - headers["custom"] = "valid"; + var context = new DefaultHttpContext(); + context.Request.Headers["custom"] = "valid"; - Assert.Throws(() => headers.Get("custom")); + Assert.Throws(() => context.Request.GetTypedHeaders().Get("custom")); } [Fact] public void GetListT_KnownTypeWithValidValue_Success() { - var headers = new HeaderDictionary(); - headers[HeaderNames.Accept] = "text/plain; q=0.9, text/other, */*"; + var context = new DefaultHttpContext(); + context.Request.Headers[HeaderNames.Accept] = "text/plain; q=0.9, text/other, */*"; - var result = headers.GetList(HeaderNames.Accept); + var result = context.Request.GetTypedHeaders().GetList(HeaderNames.Accept); var expected = new[] { new MediaTypeHeaderValue("text/plain", 0.9), @@ -102,9 +102,9 @@ namespace Microsoft.AspNet.Http.Headers [Fact] public void GetListT_KnownTypeWithMissingValue_Null() { - var headers = new HeaderDictionary(); + var context = new DefaultHttpContext(); - var result = headers.GetList(HeaderNames.Accept); + var result = context.Request.GetTypedHeaders().GetList(HeaderNames.Accept); Assert.Null(result); } @@ -112,10 +112,10 @@ namespace Microsoft.AspNet.Http.Headers [Fact] public void GetListT_KnownTypeWithInvalidValue_Null() { - var headers = new HeaderDictionary(); - headers[HeaderNames.Accept] = "invalid"; + var context = new DefaultHttpContext(); + context.Request.Headers[HeaderNames.Accept] = "invalid"; - var result = headers.GetList(HeaderNames.Accept); + var result = context.Request.GetTypedHeaders().GetList(HeaderNames.Accept); Assert.Null(result); } @@ -123,10 +123,10 @@ namespace Microsoft.AspNet.Http.Headers [Fact] public void GetListT_UnknownTypeWithTryParseListAndValidValue_Success() { - var headers = new HeaderDictionary(); - headers["custom"] = "valid"; + var context = new DefaultHttpContext(); + context.Request.Headers["custom"] = "valid"; - var results = headers.GetList("custom"); + var results = context.Request.GetTypedHeaders().GetList("custom"); Assert.NotNull(results); Assert.Equal(new[] { new TestHeaderValue() }.ToList(), results); } @@ -134,29 +134,29 @@ namespace Microsoft.AspNet.Http.Headers [Fact] public void GetListT_UnknownTypeWithTryParseListAndInvalidValue_Null() { - var headers = new HeaderDictionary(); - headers["custom"] = "invalid"; + var context = new DefaultHttpContext(); + context.Request.Headers["custom"] = "invalid"; - var results = headers.GetList("custom"); + var results = context.Request.GetTypedHeaders().GetList("custom"); Assert.Null(results); } [Fact] public void GetListT_UnknownTypeWithTryParseListAndMissingValue_Null() { - var headers = new HeaderDictionary(); + var context = new DefaultHttpContext(); - var results = headers.GetList("custom"); + var results = context.Request.GetTypedHeaders().GetList("custom"); Assert.Null(results); } [Fact] public void GetListT_UnknownTypeWithoutTryParseList_Throws() { - var headers = new HeaderDictionary(); - headers["custom"] = "valid"; + var context = new DefaultHttpContext(); + context.Request.Headers["custom"] = "valid"; - Assert.Throws(() => headers.GetList("custom")); + Assert.Throws(() => context.Request.GetTypedHeaders().GetList("custom")); } public class TestHeaderValue diff --git a/test/Microsoft.AspNet.Http.Extensions.Tests/HttpResponseSendingExtensionsTests.cs b/test/Microsoft.AspNet.Http.Extensions.Tests/HttpResponseSendingExtensionsTests.cs deleted file mode 100644 index 6f30bc053a..0000000000 --- a/test/Microsoft.AspNet.Http.Extensions.Tests/HttpResponseSendingExtensionsTests.cs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.IO; -using System.Text; -using System.Threading.Tasks; -using Xunit; - -namespace Microsoft.AspNet.Http.Extensions -{ - public class HttpResponseSendingExtensionsTests - { - [Fact] - public async Task SendData_SendBytes() - { - HttpContext context = CreateRequest(); - await context.Response.SendAsync(new byte[10]); - - Assert.Equal(10, context.Response.Body.Length); - Assert.Equal(10, context.Response.ContentLength); - Assert.Null(context.Response.ContentType); - } - - [Fact] - public async Task SendData_SendBytesAndContentType() - { - HttpContext context = CreateRequest(); - await context.Response.SendAsync(new byte[10], "text/html"); - - Assert.Equal(10, context.Response.Body.Length); - Assert.Equal(10, context.Response.ContentLength); - Assert.Equal("text/html", context.Response.ContentType); - } - - [Fact] - public async Task SendData_SendText() - { - HttpContext context = CreateRequest(); - await context.Response.SendAsync("Hello World"); - - Assert.Equal(11, context.Response.Body.Length); - Assert.Equal(11, context.Response.ContentLength); - Assert.Null(context.Response.ContentType); - } - - [Fact] - public async Task SendData_SendTextWithContentType() - { - HttpContext context = CreateRequest(); - await context.Response.SendAsync("Hello World", "text/html"); - - Assert.Equal(11, context.Response.Body.Length); - Assert.Equal(11, context.Response.ContentLength); - Assert.Equal("text/html; charset=utf-8", context.Response.ContentType); - } - - [Fact] - public async Task SendData_SendTextWithEncoding() - { - HttpContext context = CreateRequest(); - await context.Response.SendAsync("Hello World", Encoding.UTF32); - - Assert.Equal(44, context.Response.Body.Length); - Assert.Equal(44, context.Response.ContentLength); - Assert.Null(context.Response.ContentType); - } - - [Fact] - public async Task SendData_SendTextWithContentTypeAndEncoding() - { - HttpContext context = CreateRequest(); - await context.Response.SendAsync("Hello World", Encoding.UTF32, "text/html"); - - Assert.Equal(44, context.Response.Body.Length); - Assert.Equal(44, context.Response.ContentLength); - Assert.Equal("text/html; charset=utf-32", context.Response.ContentType); - } - - private HttpContext CreateRequest() - { - HttpContext context = new DefaultHttpContext(); - context.Response.Body = new MemoryStream(); - return context; - } - } -}