Http Abstractions for parsing Http headers needed for conneg.
This commit is contained in:
parent
d13f6474d8
commit
b8ab5c5063
26
Mvc.sln
26
Mvc.sln
|
|
@ -2,6 +2,7 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.21901.1
|
||||
VisualStudioVersion = 14.0.21806.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}"
|
||||
EndProject
|
||||
|
|
@ -54,6 +55,9 @@ EndProject
|
|||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "RazorWebSite", "test\WebSites\RazorWebSite\RazorWebSite.kproj", "{B07CAF59-11ED-40E3-A5DB-E1178F84FA78}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ValueProvidersSite", "test\WebSites\ValueProvidersSite\ValueProvidersSite.kproj", "{14F79E79-AE79-48FA-95DE-D794EF4EABB3}"
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.HeaderValueAbstractions", "src\Microsoft.AspNet.Mvc.HeaderValueAbstractions\Microsoft.AspNet.Mvc.HeaderValueAbstractions.kproj", "{98335B23-E4B9-4CAD-9749-0DED32A659A1}"
|
||||
EndProject
|
||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.HeaderValueAbstractions.Tests", "test\Microsoft.AspNet.Mvc.HeaderValueAbstractions.Test\Microsoft.AspNet.Mvc.HeaderValueAbstractions.Tests.kproj", "{E69FD235-2042-43A4-9970-59CB29955B4E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
|
@ -285,6 +289,26 @@ Global
|
|||
{14F79E79-AE79-48FA-95DE-D794EF4EABB3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{14F79E79-AE79-48FA-95DE-D794EF4EABB3}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{14F79E79-AE79-48FA-95DE-D794EF4EABB3}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{98335B23-E4B9-4CAD-9749-0DED32A659A1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{E69FD235-2042-43A4-9970-59CB29955B4E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E69FD235-2042-43A4-9970-59CB29955B4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E69FD235-2042-43A4-9970-59CB29955B4E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E69FD235-2042-43A4-9970-59CB29955B4E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{E69FD235-2042-43A4-9970-59CB29955B4E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{E69FD235-2042-43A4-9970-59CB29955B4E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -313,5 +337,7 @@ Global
|
|||
{A853B2BA-4449-4908-A416-5A3C027FC22B} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{B07CAF59-11ED-40E3-A5DB-E1178F84FA78} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{14F79E79-AE79-48FA-95DE-D794EF4EABB3} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||
{98335B23-E4B9-4CAD-9749-0DED32A659A1} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
||||
{E69FD235-2042-43A4-9970-59CB29955B4E} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
|
||||
{
|
||||
public static class FormattingUtilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Quality factor to indicate a perfect match.
|
||||
/// </summary>
|
||||
public const double Match = 1.0;
|
||||
|
||||
/// <summary>
|
||||
/// Quality factor to indicate no match.
|
||||
/// </summary>
|
||||
public const double NoMatch = 0.0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
|
||||
{
|
||||
public class MediaTypeHeaderValue
|
||||
{
|
||||
public string Charset { get; set; }
|
||||
|
||||
public string MediaType { get; set; }
|
||||
|
||||
public string MediaSubType { get; set; }
|
||||
|
||||
public MediaTypeHeaderValueRange MediaTypeRange { get; set; }
|
||||
|
||||
public string RawValue
|
||||
{
|
||||
get
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
stringBuilder.Append(MediaType);
|
||||
stringBuilder.Append('/');
|
||||
stringBuilder.Append(MediaSubType);
|
||||
if (!string.IsNullOrEmpty(Charset))
|
||||
{
|
||||
stringBuilder.Append(";charset=");
|
||||
stringBuilder.Append(Charset);
|
||||
}
|
||||
|
||||
foreach (var parameter in Parameters)
|
||||
{
|
||||
if (string.Equals(parameter.Key, "charset", System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
stringBuilder.Append(";");
|
||||
stringBuilder.Append(parameter.Key);
|
||||
stringBuilder.Append("=");
|
||||
stringBuilder.Append(parameter.Value);
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public IDictionary<string, string> Parameters { get; set; }
|
||||
|
||||
public static MediaTypeHeaderValue Parse(string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var inputArray = input.Split(new[] { ';' }, 2);
|
||||
var mediaTypeParts = inputArray[0].Split('/');
|
||||
if (mediaTypeParts.Length != 2)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: throw if the media type and subtypes are invalid.
|
||||
var mediaType = mediaTypeParts[0].Trim();
|
||||
var mediaSubType = mediaTypeParts[1].Trim();
|
||||
var mediaTypeRange = MediaTypeHeaderValueRange.None;
|
||||
if (mediaType == "*" && mediaSubType == "*")
|
||||
{
|
||||
mediaTypeRange = MediaTypeHeaderValueRange.AllMediaRange;
|
||||
}
|
||||
else if (mediaSubType == "*")
|
||||
{
|
||||
mediaTypeRange = MediaTypeHeaderValueRange.SubtypeMediaRange;
|
||||
}
|
||||
|
||||
Dictionary<string, string> parameters = null;
|
||||
string charset = null;
|
||||
if (inputArray.Length == 2)
|
||||
{
|
||||
parameters = ParseParameters(inputArray[1]);
|
||||
parameters.TryGetValue("charset", out charset);
|
||||
}
|
||||
|
||||
var mediaTypeHeader = new MediaTypeHeaderValue()
|
||||
{
|
||||
MediaType = mediaType,
|
||||
MediaSubType = mediaSubType,
|
||||
MediaTypeRange = mediaTypeRange,
|
||||
Charset = charset,
|
||||
Parameters = parameters ?? new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase),
|
||||
};
|
||||
|
||||
return mediaTypeHeader;
|
||||
}
|
||||
|
||||
protected static Dictionary<string, string> ParseParameters(string inputString)
|
||||
{
|
||||
var acceptParameters = inputString.Split(';');
|
||||
var parameterNameValue = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var parameter in acceptParameters)
|
||||
{
|
||||
var index = parameter.Split('=');
|
||||
if (index.Length == 2)
|
||||
{
|
||||
// TODO: throw exception if this is not the case.
|
||||
parameterNameValue.Add(index[0].Trim(), index[1].Trim());
|
||||
}
|
||||
}
|
||||
|
||||
return parameterNameValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance is a subset of passed <see cref="MediaTypeHeaderValue"/>.
|
||||
/// If the media type and media type parameters of this media type are all present
|
||||
/// and match those of <paramref name="otherMediaType"/> then it is a match even though
|
||||
/// <paramref name="otherMediaType"/> may have additional parameters.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">The first media type.</param>
|
||||
/// <param name="otherMediaType">The second media type.</param>
|
||||
/// <returns><c>true</c> if this is a subset of <paramref name="otherMediaType"/>; false otherwise.</returns>
|
||||
public bool IsSubsetOf(MediaTypeHeaderValue otherMediaType)
|
||||
{
|
||||
if (otherMediaType == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!MediaType.Equals(otherMediaType.MediaType, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (otherMediaType.MediaTypeRange != MediaTypeHeaderValueRange.AllMediaRange)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!MediaSubType.Equals(otherMediaType.MediaSubType, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (otherMediaType.MediaTypeRange != MediaTypeHeaderValueRange.SubtypeMediaRange)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (Parameters != null)
|
||||
{
|
||||
if (Parameters.Count != 0 &&
|
||||
(otherMediaType.Parameters == null || otherMediaType.Parameters.Count == 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// So far we either have a full match or a subset match. Now check that all of
|
||||
// mediaType1's parameters are present and equal in mediatype2
|
||||
if(!MatchParameters(Parameters, otherMediaType.Parameters))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool MatchParameters(IDictionary<string, string> parameters1,
|
||||
IDictionary<string, string> parameters2)
|
||||
{
|
||||
foreach (var parameterKey in parameters1.Keys)
|
||||
{
|
||||
string parameterValue2 = null;
|
||||
if (!parameters2.TryGetValue(parameterKey, out parameterValue2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parameterValue2 == null || !parameterValue2.Equals(parameters1[parameterKey]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public enum MediaTypeHeaderValueRange
|
||||
{
|
||||
/// <summary>
|
||||
/// Not a media type range
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// A subtype media range, e.g. "application/*".
|
||||
/// </summary>
|
||||
SubtypeMediaRange,
|
||||
|
||||
/// <summary>
|
||||
/// An all media range, e.g. "*/*".
|
||||
/// </summary>
|
||||
AllMediaRange,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// 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.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
|
||||
{
|
||||
public class MediaTypeWithQualityHeaderValue : MediaTypeHeaderValue
|
||||
{
|
||||
public double? Quality { get; private set; }
|
||||
|
||||
public static new MediaTypeWithQualityHeaderValue Parse(string input)
|
||||
{
|
||||
var mediaTypeHeaderValue = MediaTypeHeaderValue.Parse(input);
|
||||
if (mediaTypeHeaderValue == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var quality = FormattingUtilities.Match;
|
||||
string qualityStringValue = null;
|
||||
if (mediaTypeHeaderValue.Parameters.TryGetValue("q", out qualityStringValue))
|
||||
{
|
||||
if(!Double.TryParse(qualityStringValue, out quality))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
new MediaTypeWithQualityHeaderValue()
|
||||
{
|
||||
MediaType = mediaTypeHeaderValue.MediaType,
|
||||
MediaSubType = mediaTypeHeaderValue.MediaSubType,
|
||||
MediaTypeRange = mediaTypeHeaderValue.MediaTypeRange,
|
||||
Charset = mediaTypeHeaderValue.Charset,
|
||||
Parameters = mediaTypeHeaderValue.Parameters,
|
||||
Quality = quality,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="__ToolsVersion__" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">12.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>98335b23-e4b9-4cad-9749-0ded32a659a1</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="FormattingUtilities.cs" />
|
||||
<Compile Include="MediaTypeHeaderValue.cs" />
|
||||
<Compile Include="MediaTypeHeaderValueRange.cs" />
|
||||
<Compile Include="MediaTypeWithQualityHeaderValue.cs" />
|
||||
<Compile Include="StringWithQualityHeaderValue.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="project.json" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
|
||||
{
|
||||
public class StringWithQualityHeaderValue
|
||||
{
|
||||
public double? Quality { get; set; }
|
||||
|
||||
public string RawValue { get; set; }
|
||||
|
||||
public string Value { get; set; }
|
||||
|
||||
public static StringWithQualityHeaderValue Parse(string input)
|
||||
{
|
||||
var inputArray = input.Split(new[] { ';' }, 2);
|
||||
var value = inputArray[0].Trim();
|
||||
|
||||
// Unspecified q factor value is equal to a match.
|
||||
var quality = FormattingUtilities.Match;
|
||||
if (inputArray.Length > 1)
|
||||
{
|
||||
var parameter = inputArray[1].Trim();
|
||||
var nameValuePair = parameter.Split(new[] { '=' }, 2);
|
||||
if (nameValuePair.Length > 1 && nameValuePair[0].Trim().Equals("q"))
|
||||
{
|
||||
// TODO: all extraneous parameters are ignored. Throw/return null if that is the case.
|
||||
if(!Double.TryParse(nameValuePair[1].Trim(), out quality))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var stringWithQualityHeader = new StringWithQualityHeaderValue()
|
||||
{
|
||||
Quality = quality,
|
||||
Value = value,
|
||||
RawValue = input
|
||||
};
|
||||
|
||||
return stringWithQualityHeader;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"dependencies": {},
|
||||
"configurations": {
|
||||
"net45": {},
|
||||
"k10": {
|
||||
"dependencies": {
|
||||
"System.Collections": "4.0.0.0",
|
||||
"System.Runtime": "4.0.20.0",
|
||||
"System.Runtime.Extensions": "4.0.10.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
"Microsoft.Framework.ConfigurationModel.Json": "1.0.0-*",
|
||||
"Microsoft.Framework.DependencyInjection": "1.0.0-*",
|
||||
"Microsoft.Framework.Runtime.Interfaces": "1.0.0-*",
|
||||
"Microsoft.AspNet.PipelineCore": "1.0.0-*",
|
||||
"RoutingWebSite": "",
|
||||
"RazorWebSite": "",
|
||||
"ValueProvidersSite": "",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,135 @@
|
|||
// 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.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
|
||||
{
|
||||
public class MediaTypeHeaderValueParsingTests
|
||||
{
|
||||
public static IEnumerable<object[]> GetValidMediaTypeWithQualityHeaderValues
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
"*",
|
||||
"*",
|
||||
null,
|
||||
MediaTypeHeaderValueRange.AllMediaRange,
|
||||
new Dictionary<string, string>(),
|
||||
FormattingUtilities.Match,
|
||||
"*/*"
|
||||
};
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
"text",
|
||||
"*",
|
||||
"utf-8",
|
||||
MediaTypeHeaderValueRange.SubtypeMediaRange,
|
||||
new Dictionary<string, string>() { { "charset", "utf-8" }, { "foo", "bar" } },
|
||||
FormattingUtilities.Match,
|
||||
"text/*;charset=utf-8;foo=bar",
|
||||
};
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
"text",
|
||||
"plain",
|
||||
"utf-8",
|
||||
MediaTypeHeaderValueRange.None,
|
||||
new Dictionary<string, string>() { { "charset", "utf-8" }, { "foo", "bar" }, { "q", "0.0" } },
|
||||
FormattingUtilities.NoMatch,
|
||||
"text/plain;charset=utf-8;foo=bar;q=0.0",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData("GetValidMediaTypeWithQualityHeaderValues")]
|
||||
public void MediaTypeWithQualityHeaderValue_ParseSuccessfully(string mediaType,
|
||||
string mediaSubType,
|
||||
string charset,
|
||||
MediaTypeHeaderValueRange range,
|
||||
IDictionary<string, string> parameters,
|
||||
double quality,
|
||||
string rawValue)
|
||||
{
|
||||
var parsedValue = MediaTypeWithQualityHeaderValue.Parse(rawValue);
|
||||
// Act and Assert
|
||||
Assert.Equal(rawValue, parsedValue.RawValue);
|
||||
Assert.Equal(mediaType, parsedValue.MediaType);
|
||||
Assert.Equal(mediaSubType, parsedValue.MediaSubType);
|
||||
Assert.Equal(charset, parsedValue.Charset);
|
||||
Assert.Equal(range, parsedValue.MediaTypeRange);
|
||||
ValidateParametes(parameters, parsedValue.Parameters);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("*/*;", "*/*", true)]
|
||||
[InlineData("text/*;", "text/*", true)]
|
||||
[InlineData("text/plain;", "text/plain", true)]
|
||||
[InlineData("*/*;", "*/*;charset=utf-8;", true)]
|
||||
[InlineData("text/*;", "*/*;charset=utf-8;", true)]
|
||||
[InlineData("text/plain;", "*/*;charset=utf-8;", true)]
|
||||
[InlineData("text/plain;", "text/*;charset=utf-8;", true)]
|
||||
[InlineData("text/plain;", "text/plain;charset=utf-8;", true)]
|
||||
[InlineData("text/plain;charset=utf-8;foo=bar;q=0.0", "text/plain;charset=utf-8;foo=bar;q=0.0", true)]
|
||||
[InlineData("text/plain;charset=utf-8;foo=bar;q=0.0", "text/*;charset=utf-8;foo=bar;q=0.0", true)]
|
||||
[InlineData("text/plain;charset=utf-8;foo=bar;q=0.0", "*/*;charset=utf-8;foo=bar;q=0.0", true)]
|
||||
[InlineData("*/*;", "text/plain;charset=utf-8;foo=bar;q=0.0", false)]
|
||||
[InlineData("text/*;", "text/plain;charset=utf-8;foo=bar;q=0.0", false)]
|
||||
[InlineData("text/plain;missingparam=4;", "text/plain;charset=utf-8;foo=bar;q=0.0", false)]
|
||||
[InlineData("text/plain;missingparam=4;", "text/*;charset=utf-8;foo=bar;q=0.0", false)]
|
||||
[InlineData("text/plain;missingparam=4;", "*/*;charset=utf-8;foo=bar;q=0.0", false)]
|
||||
public void MediaTypeHeaderValue_IsSubTypeTests(string mediaType1,
|
||||
string mediaType2,
|
||||
bool isMediaType1Subset)
|
||||
{
|
||||
var parsedMediaType1 = MediaTypeWithQualityHeaderValue.Parse(mediaType1);
|
||||
var parsedMediaType2 = MediaTypeWithQualityHeaderValue.Parse(mediaType2);
|
||||
|
||||
// Act
|
||||
var isSubset = parsedMediaType1.IsSubsetOf(parsedMediaType2);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(isMediaType1Subset, isSubset);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("text/plain;charset=utf-16;foo=bar", "text/plain;charset=utf-8;foo=bar")]
|
||||
[InlineData("text/plain;charset=utf-16;foo=bar", "text/plain;charset=utf-16;foo=bar1")]
|
||||
[InlineData("text/plain;charset=utf-16;foo=bar", "text/json;charset=utf-16;foo=bar")]
|
||||
[InlineData("text/plain;charset=utf-16;foo=bar", "application/plain;charset=utf-16;foo=bar")]
|
||||
[InlineData("text/plain;charset=utf-16;foo=bar", "application/json;charset=utf-8;foo=bar1")]
|
||||
public void MediaTypeHeaderValue_UpdateValue_RawValueGetsUpdated(string mediaTypeValue,
|
||||
string expectedRawValue)
|
||||
{
|
||||
// Arrange
|
||||
var parsedOldValue = MediaTypeHeaderValue.Parse(mediaTypeValue);
|
||||
var parsedNewValue = MediaTypeHeaderValue.Parse(expectedRawValue);
|
||||
|
||||
// Act
|
||||
parsedOldValue.Charset = parsedNewValue.Charset;
|
||||
parsedOldValue.Parameters = parsedNewValue.Parameters;
|
||||
parsedOldValue.MediaType = parsedNewValue.MediaType;
|
||||
parsedOldValue.MediaSubType = parsedNewValue.MediaSubType;
|
||||
parsedOldValue.MediaTypeRange = parsedNewValue.MediaTypeRange;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedRawValue, parsedOldValue.RawValue);
|
||||
}
|
||||
|
||||
private static void ValidateParametes(IDictionary<string, string> expectedParameters,
|
||||
IDictionary<string, string> actualParameters)
|
||||
{
|
||||
Assert.Equal(expectedParameters.Count, actualParameters.Count);
|
||||
foreach (var key in expectedParameters.Keys)
|
||||
{
|
||||
Assert.Equal(expectedParameters[key], actualParameters[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="__ToolsVersion__" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">12.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>e69fd235-2042-43a4-9970-59cb29955b4e</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<ActiveTargetFramework>net45</ActiveTargetFramework>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration">
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="project.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="StringWithQualityHeaderValueParsingTests.cs" />
|
||||
<Compile Include="MediaTypeHeaderValueParsingTests.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// 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 Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.HeaderValueAbstractions
|
||||
{
|
||||
public class StringWithQualityHeaderValueParsingTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("*", FormattingUtilities.Match, "*")]
|
||||
[InlineData("*", 0.7, "*;q=.7")]
|
||||
[InlineData("iso-8859-5", FormattingUtilities.Match, "iso-8859-5")]
|
||||
[InlineData("unicode-1-1", 0.8, "unicode-1-1;q=0.8")]
|
||||
[InlineData("unicode-1-1", 0.8, "unicode-1-1;q =0.8")]
|
||||
[InlineData("unicode-1-1", 0.8, "unicode-1-1;q = 0.8")]
|
||||
[InlineData("unicode-1-1", 1.0, "unicode-1-1;quxx = 0.8")] // quxx gets ignored.
|
||||
public void StringWithQualityHeaderValue_ParseSuccessfully(string value,
|
||||
double quality,
|
||||
string rawValue)
|
||||
{
|
||||
var parsedValue = StringWithQualityHeaderValue.Parse(rawValue);
|
||||
// Act and Assert
|
||||
Assert.Equal(rawValue, parsedValue.RawValue);
|
||||
Assert.Equal(value, parsedValue.Value);
|
||||
Assert.Equal(quality, parsedValue.Quality);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Http": "",
|
||||
"Microsoft.AspNet.Mvc.HeaderValueAbstractions": "",
|
||||
"Microsoft.AspNet.Testing": "1.0.0-*",
|
||||
"Xunit.KRunner": "1.0.0-*"
|
||||
},
|
||||
"commands": {
|
||||
"test": "Xunit.KRunner"
|
||||
},
|
||||
"configurations": {
|
||||
"net45": {
|
||||
"dependencies": {
|
||||
"System.Runtime": "4.0.20.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue