parent
e320755734
commit
a4a4e490c5
|
|
@ -107,21 +107,25 @@ namespace Microsoft.AspNetCore.Http
|
|||
|
||||
public bool Equals(FragmentString other)
|
||||
{
|
||||
return string.Equals(_value, other._value);
|
||||
if (!HasValue && !other.HasValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return string.Equals(_value, other._value, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj))
|
||||
{
|
||||
return false;
|
||||
return !HasValue;
|
||||
}
|
||||
return obj is FragmentString && Equals((FragmentString)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (_value != null ? _value.GetHashCode() : 0);
|
||||
return (HasValue ? _value.GetHashCode() : 0);
|
||||
}
|
||||
|
||||
public static bool operator ==(FragmentString left, FragmentString right)
|
||||
|
|
|
|||
|
|
@ -205,6 +205,10 @@ namespace Microsoft.AspNetCore.Http
|
|||
/// <returns></returns>
|
||||
public bool Equals(HostString other)
|
||||
{
|
||||
if (!HasValue && !other.HasValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
|
|
@ -217,7 +221,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
{
|
||||
if (ReferenceEquals(null, obj))
|
||||
{
|
||||
return false;
|
||||
return !HasValue;
|
||||
}
|
||||
return obj is HostString && Equals((HostString)obj);
|
||||
}
|
||||
|
|
@ -228,7 +232,7 @@ namespace Microsoft.AspNetCore.Http
|
|||
/// <returns></returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (_value != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0);
|
||||
return (HasValue ? StringComparer.OrdinalIgnoreCase.GetHashCode(_value) : 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -215,21 +215,25 @@ namespace Microsoft.AspNetCore.Http
|
|||
|
||||
public bool Equals(QueryString other)
|
||||
{
|
||||
return string.Equals(_value, other._value);
|
||||
if (!HasValue && !other.HasValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return string.Equals(_value, other._value, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj))
|
||||
{
|
||||
return false;
|
||||
return !HasValue;
|
||||
}
|
||||
return obj is QueryString && Equals((QueryString)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _value?.GetHashCode() ?? 0;
|
||||
return (HasValue ? _value.GetHashCode() : 0);
|
||||
}
|
||||
|
||||
public static bool operator ==(QueryString left, QueryString right)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ namespace Microsoft.AspNetCore.Http.Extensions
|
|||
/// </summary>
|
||||
public static class UriHelper
|
||||
{
|
||||
private const string ForwardSlash = "/";
|
||||
private const string Pound = "#";
|
||||
private const string QuestionMark = "?";
|
||||
private const string SchemeDelimiter = "://";
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -70,6 +73,67 @@ namespace Microsoft.AspNetCore.Http.Extensions
|
|||
.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seperates the given absolute URI string into components. Assumes no PathBase.
|
||||
/// </summary>
|
||||
/// <param name="uri">A string representation of the uri.</param>
|
||||
/// <param name="scheme">http, https, etc.</param>
|
||||
/// <param name="host">The host portion of the uri normally included in the Host header. This may include the port.</param>
|
||||
/// <param name="path">The portion of the request path that identifies the requested resource.</param>
|
||||
/// <param name="query">The query, if any.</param>
|
||||
/// <param name="fragment">The fragment, if any.</param>
|
||||
public static void FromAbsolute(
|
||||
string uri,
|
||||
out string scheme,
|
||||
out HostString host,
|
||||
out PathString path,
|
||||
out QueryString query,
|
||||
out FragmentString fragment)
|
||||
{
|
||||
if (uri == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uri));
|
||||
}
|
||||
// Satisfy the out parameters
|
||||
path = new PathString();
|
||||
query = new QueryString();
|
||||
fragment = new FragmentString();
|
||||
var startIndex = uri.IndexOf(SchemeDelimiter);
|
||||
|
||||
if (startIndex < 0)
|
||||
{
|
||||
throw new FormatException("No scheme delimiter in uri.");
|
||||
}
|
||||
|
||||
scheme = uri.Substring(0, startIndex);
|
||||
|
||||
// PERF: Calculate the end of the scheme for next IndexOf
|
||||
startIndex += SchemeDelimiter.Length;
|
||||
|
||||
var searchIndex = -1;
|
||||
var limit = uri.Length;
|
||||
|
||||
if ((searchIndex = uri.IndexOf(Pound, startIndex)) >= 0 && searchIndex < limit)
|
||||
{
|
||||
fragment = FragmentString.FromUriComponent(uri.Substring(searchIndex));
|
||||
limit = searchIndex;
|
||||
}
|
||||
|
||||
if ((searchIndex = uri.IndexOf(QuestionMark, startIndex)) >= 0 && searchIndex < limit)
|
||||
{
|
||||
query = QueryString.FromUriComponent(uri.Substring(searchIndex, limit - searchIndex));
|
||||
limit = searchIndex;
|
||||
}
|
||||
|
||||
if ((searchIndex = uri.IndexOf(ForwardSlash, startIndex)) >= 0 && searchIndex < limit)
|
||||
{
|
||||
path = PathString.FromUriComponent(uri.Substring(searchIndex, limit - searchIndex));
|
||||
limit = searchIndex;
|
||||
}
|
||||
|
||||
host = HostString.FromUriComponent(uri.Substring(startIndex, limit - startIndex));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a string from the given absolute or relative Uri that is appropriately encoded for use in
|
||||
/// HTTP headers. Note that a unicode host name will be encoded as punycode.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
// 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 Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Http.Abstractions.Tests
|
||||
{
|
||||
public class FragmentStringTests
|
||||
{
|
||||
[Fact]
|
||||
public void Equals_EmptyFragmentStringAndDefaultFragmentString()
|
||||
{
|
||||
// Act and Assert
|
||||
Assert.Equal(FragmentString.Empty, default(FragmentString));
|
||||
Assert.Equal(default(FragmentString), FragmentString.Empty);
|
||||
// explicitly checking == operator
|
||||
Assert.True(FragmentString.Empty == default(FragmentString));
|
||||
Assert.True(default(FragmentString) == FragmentString.Empty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotEquals_DefaultFragmentStringAndNonNullFragmentString()
|
||||
{
|
||||
// Arrange
|
||||
var fragmentString = new FragmentString("#col=1");
|
||||
|
||||
// Act and Assert
|
||||
Assert.NotEqual(fragmentString, default(FragmentString));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotEquals_EmptyFragmentStringAndNonNullFragmentString()
|
||||
{
|
||||
// Arrange
|
||||
var fragmentString = new FragmentString("#col=1");
|
||||
|
||||
// Act and Assert
|
||||
Assert.NotEqual(fragmentString, FragmentString.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -92,5 +92,36 @@ namespace Microsoft.AspNetCore.Http
|
|||
Assert.Equal(expectedHost, host);
|
||||
Assert.Equal(expectedPort, port);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Equals_EmptyHostStringAndDefaultHostString()
|
||||
{
|
||||
// Act and Assert
|
||||
Assert.Equal(new HostString(string.Empty), default(HostString));
|
||||
Assert.Equal(default(HostString), new HostString(string.Empty));
|
||||
// explicitly checking == operator
|
||||
Assert.True(new HostString(string.Empty) == default(HostString));
|
||||
Assert.True(default(HostString) == new HostString(string.Empty));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotEquals_DefaultHostStringAndNonNullHostString()
|
||||
{
|
||||
// Arrange
|
||||
var hostString = new HostString("example.com");
|
||||
|
||||
// Act and Assert
|
||||
Assert.NotEqual(hostString, default(HostString));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotEquals_EmptyHostStringAndNonNullHostString()
|
||||
{
|
||||
// Arrange
|
||||
var hostString = new HostString("example.com");
|
||||
|
||||
// Act and Assert
|
||||
Assert.NotEqual(hostString, new HostString(string.Empty));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,5 +105,36 @@ namespace Microsoft.AspNetCore.Http.Abstractions
|
|||
var q2 = q1.Add(name2, value2);
|
||||
Assert.Equal(expected, q2.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Equals_EmptyQueryStringAndDefaultQueryString()
|
||||
{
|
||||
// Act and Assert
|
||||
Assert.Equal(QueryString.Empty, default(QueryString));
|
||||
Assert.Equal(default(QueryString), QueryString.Empty);
|
||||
// explicitly checking == operator
|
||||
Assert.True(QueryString.Empty == default(QueryString));
|
||||
Assert.True(default(QueryString) == QueryString.Empty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotEquals_DefaultQueryStringAndNonNullQueryString()
|
||||
{
|
||||
// Arrange
|
||||
var queryString = new QueryString("?foo=1");
|
||||
|
||||
// Act and Assert
|
||||
Assert.NotEqual(queryString, default(QueryString));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotEquals_EmptyQueryStringAndNonNullQueryString()
|
||||
{
|
||||
// Arrange
|
||||
var queryString = new QueryString("?foo=1");
|
||||
|
||||
// Act and Assert
|
||||
Assert.NotEqual(queryString, QueryString.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,5 +66,68 @@ namespace Microsoft.AspNetCore.Http.Extensions
|
|||
|
||||
Assert.Equal("http://my.hoψst:80/un?escaped/base/un?escaped?name=val%23ue", request.GetDisplayUrl());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("http://example.com", "http", "example.com", "", "", "")]
|
||||
[InlineData("https://example.com", "https", "example.com", "", "", "")]
|
||||
[InlineData("http://example.com/foo/bar", "http", "example.com", "/foo/bar", "", "")]
|
||||
[InlineData("http://example.com/foo/bar?baz=1", "http", "example.com", "/foo/bar", "?baz=1", "")]
|
||||
[InlineData("http://example.com/foo#col=2", "http", "example.com", "/foo", "", "#col=2")]
|
||||
[InlineData("http://example.com/foo?bar=1#col=2", "http", "example.com", "/foo", "?bar=1", "#col=2")]
|
||||
[InlineData("http://example.com?bar=1#col=2", "http", "example.com", "", "?bar=1", "#col=2")]
|
||||
[InlineData("http://example.com#frag?stillfrag/stillfrag", "http", "example.com", "", "", "#frag?stillfrag/stillfrag")]
|
||||
[InlineData("http://example.com?q/stillq#frag?stillfrag/stillfrag", "http", "example.com", "", "?q/stillq", "#frag?stillfrag/stillfrag")]
|
||||
[InlineData("http://example.com/fo%23o#col=2", "http", "example.com", "/fo#o", "", "#col=2")]
|
||||
[InlineData("http://example.com/fo%3Fo#col=2", "http", "example.com", "/fo?o", "", "#col=2")]
|
||||
[InlineData("ftp://example.com/", "ftp", "example.com", "/", "", "")]
|
||||
[InlineData("https://127.0.0.0:80/bar", "https", "127.0.0.0:80", "/bar", "", "")]
|
||||
[InlineData("http://[1080:0:0:0:8:800:200C:417A]/index.html", "http", "[1080:0:0:0:8:800:200C:417A]", "/index.html", "", "")]
|
||||
[InlineData("http://example.com///", "http", "example.com", "///", "", "")]
|
||||
[InlineData("http://example.com///", "http", "example.com", "///", "", "")]
|
||||
public void FromAbsoluteUriParsingChecks(
|
||||
string uri,
|
||||
string expectedScheme,
|
||||
string expectedHost,
|
||||
string expectedPath,
|
||||
string expectedQuery,
|
||||
string expectedFragment)
|
||||
{
|
||||
string scheme = null;
|
||||
var host = new HostString();
|
||||
var path = new PathString();
|
||||
var query = new QueryString();
|
||||
var fragment = new FragmentString();
|
||||
UriHelper.FromAbsolute(uri, out scheme, out host, out path, out query, out fragment);
|
||||
|
||||
Assert.Equal(scheme, expectedScheme);
|
||||
Assert.Equal(host, new HostString(expectedHost));
|
||||
Assert.Equal(path, new PathString(expectedPath));
|
||||
Assert.Equal(query, new QueryString(expectedQuery));
|
||||
Assert.Equal(fragment, new FragmentString(expectedFragment));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FromAbsoluteToBuildAbsolute()
|
||||
{
|
||||
var scheme = "http";
|
||||
var host = new HostString("example.com");
|
||||
var path = new PathString("/index.html");
|
||||
var query = new QueryString("?foo=1");
|
||||
var fragment = new FragmentString("#col=1");
|
||||
var request = UriHelper.BuildAbsolute(scheme, host, path:path, query:query, fragment:fragment);
|
||||
|
||||
string resScheme = null;
|
||||
var resHost = new HostString();
|
||||
var resPath = new PathString();
|
||||
var resQuery = new QueryString();
|
||||
var resFragment = new FragmentString();
|
||||
UriHelper.FromAbsolute(request, out resScheme, out resHost, out resPath, out resQuery, out resFragment);
|
||||
|
||||
Assert.Equal(scheme, resScheme);
|
||||
Assert.Equal(host, resHost);
|
||||
Assert.Equal(path, resPath);
|
||||
Assert.Equal(query, resQuery);
|
||||
Assert.Equal(fragment, resFragment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue