#272 Make more properties settable (Items, RequestAborted, IsHttps, Query, Cookies).
This commit is contained in:
parent
c4df4a0a15
commit
dce1d0e88f
|
|
@ -17,22 +17,22 @@ namespace Microsoft.AspNet.Http
|
||||||
|
|
||||||
public abstract ConnectionInfo Connection { get; }
|
public abstract ConnectionInfo Connection { get; }
|
||||||
|
|
||||||
|
public abstract WebSocketManager WebSockets { get; }
|
||||||
|
|
||||||
public abstract AuthenticationManager Authentication { get; }
|
public abstract AuthenticationManager Authentication { get; }
|
||||||
|
|
||||||
public abstract ClaimsPrincipal User { get; set; }
|
public abstract ClaimsPrincipal User { get; set; }
|
||||||
|
|
||||||
public abstract IDictionary<object, object> Items { get; }
|
public abstract IDictionary<object, object> Items { get; set; }
|
||||||
|
|
||||||
public abstract IServiceProvider ApplicationServices { get; set; }
|
public abstract IServiceProvider ApplicationServices { get; set; }
|
||||||
|
|
||||||
public abstract IServiceProvider RequestServices { get; set; }
|
public abstract IServiceProvider RequestServices { get; set; }
|
||||||
|
|
||||||
public abstract CancellationToken RequestAborted { get; }
|
public abstract CancellationToken RequestAborted { get; set; }
|
||||||
|
|
||||||
public abstract ISessionCollection Session { get; }
|
public abstract ISessionCollection Session { get; }
|
||||||
|
|
||||||
public abstract WebSocketManager WebSockets { get; }
|
|
||||||
|
|
||||||
public abstract void Abort();
|
public abstract void Abort();
|
||||||
|
|
||||||
public abstract void Dispose();
|
public abstract void Dispose();
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace Microsoft.AspNet.Http
|
||||||
/// Returns true if the owin.RequestScheme is https.
|
/// Returns true if the owin.RequestScheme is https.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>true if this request is using https; otherwise, false.</returns>
|
/// <returns>true if this request is using https; otherwise, false.</returns>
|
||||||
public abstract bool IsHttps { get; }
|
public abstract bool IsHttps { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or set the Host header. May include the port.
|
/// Gets or set the Host header. May include the port.
|
||||||
|
|
@ -57,7 +57,7 @@ namespace Microsoft.AspNet.Http
|
||||||
/// Gets the query value collection parsed from owin.RequestQueryString.
|
/// Gets the query value collection parsed from owin.RequestQueryString.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The query value collection parsed from owin.RequestQueryString.</returns>
|
/// <returns>The query value collection parsed from owin.RequestQueryString.</returns>
|
||||||
public abstract IReadableStringCollection Query { get; }
|
public abstract IReadableStringCollection Query { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or set the owin.RequestProtocol.
|
/// Gets or set the owin.RequestProtocol.
|
||||||
|
|
@ -75,7 +75,7 @@ namespace Microsoft.AspNet.Http
|
||||||
/// Gets the collection of Cookies for this request.
|
/// Gets the collection of Cookies for this request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The collection of Cookies for this request.</returns>
|
/// <returns>The collection of Cookies for this request.</returns>
|
||||||
public abstract IReadableStringCollection Cookies { get; }
|
public abstract IReadableStringCollection Cookies { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Content-Length header
|
/// Gets or sets the Content-Length header
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ namespace Microsoft.AspNet.Http
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">The un-encoded parameter name</param>
|
/// <param name="name">The un-encoded parameter name</param>
|
||||||
/// <param name="value">The un-encoded parameter value</param>
|
/// <param name="value">The un-encoded parameter value</param>
|
||||||
|
/// <returns>The resulting QueryString</returns>
|
||||||
public static QueryString Create(string name, string value)
|
public static QueryString Create(string name, string value)
|
||||||
{
|
{
|
||||||
return new QueryString("?" + UrlEncoder.Default.UrlEncode(name) + '=' + UrlEncoder.Default.UrlEncode(value));
|
return new QueryString("?" + UrlEncoder.Default.UrlEncode(name) + '=' + UrlEncoder.Default.UrlEncode(value));
|
||||||
|
|
@ -120,7 +121,7 @@ namespace Microsoft.AspNet.Http
|
||||||
/// Creates a query string composed from the given name value pairs.
|
/// Creates a query string composed from the given name value pairs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="parameters"></param>
|
/// <param name="parameters"></param>
|
||||||
/// <returns></returns>
|
/// <returns>The resulting QueryString</returns>
|
||||||
public static QueryString Create(IEnumerable<KeyValuePair<string, string>> parameters)
|
public static QueryString Create(IEnumerable<KeyValuePair<string, string>> parameters)
|
||||||
{
|
{
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
|
|
@ -137,6 +138,30 @@ namespace Microsoft.AspNet.Http
|
||||||
return new QueryString(builder.ToString());
|
return new QueryString(builder.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a query string composed from the given name value pairs.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parameters"></param>
|
||||||
|
/// <returns>The resulting QueryString</returns>
|
||||||
|
public static QueryString Create(IEnumerable<KeyValuePair<string, string[]>> parameters)
|
||||||
|
{
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
bool first = true;
|
||||||
|
foreach (var pair in parameters)
|
||||||
|
{
|
||||||
|
foreach (var value in pair.Value)
|
||||||
|
{
|
||||||
|
builder.Append(first ? "?" : "&");
|
||||||
|
first = false;
|
||||||
|
builder.Append(UrlEncoder.Default.UrlEncode(pair.Key));
|
||||||
|
builder.Append("=");
|
||||||
|
builder.Append(UrlEncoder.Default.UrlEncode(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new QueryString(builder.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
public QueryString Add(QueryString other)
|
public QueryString Add(QueryString other)
|
||||||
{
|
{
|
||||||
if (!HasValue || Value.Equals("?", StringComparison.Ordinal))
|
if (!HasValue || Value.Equals("?", StringComparison.Ordinal))
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ namespace Microsoft.AspNet.Http.Features
|
||||||
{
|
{
|
||||||
public interface IHttpRequestLifetimeFeature
|
public interface IHttpRequestLifetimeFeature
|
||||||
{
|
{
|
||||||
CancellationToken RequestAborted { get; }
|
CancellationToken RequestAborted { get; set; }
|
||||||
void Abort();
|
void Abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,8 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
{
|
{
|
||||||
internal static class Constants
|
internal static class Constants
|
||||||
{
|
{
|
||||||
internal const string Https = "HTTPS";
|
internal const string Http = "http";
|
||||||
|
internal const string Https = "https";
|
||||||
|
|
||||||
internal static class BuilderProperties
|
internal static class BuilderProperties
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
|
|
||||||
private IHttpRequestLifetimeFeature LifetimeFeature
|
private IHttpRequestLifetimeFeature LifetimeFeature
|
||||||
{
|
{
|
||||||
get { return _lifetime.Fetch(_features); }
|
get { return _lifetime.Fetch(_features) ?? _lifetime.Update(_features, new HttpRequestLifetimeFeature()); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private ISessionFeature SessionFeature
|
private ISessionFeature SessionFeature
|
||||||
|
|
@ -103,6 +103,7 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
public override IDictionary<object, object> Items
|
public override IDictionary<object, object> Items
|
||||||
{
|
{
|
||||||
get { return ItemsFeature.Items; }
|
get { return ItemsFeature.Items; }
|
||||||
|
set { ItemsFeature.Items = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IServiceProvider ApplicationServices
|
public override IServiceProvider ApplicationServices
|
||||||
|
|
@ -117,19 +118,10 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
set { ServiceProvidersFeature.RequestServices = value; }
|
set { ServiceProvidersFeature.RequestServices = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Revision { get { return _features.Revision; } }
|
|
||||||
|
|
||||||
public override CancellationToken RequestAborted
|
public override CancellationToken RequestAborted
|
||||||
{
|
{
|
||||||
get
|
get { return LifetimeFeature.RequestAborted; }
|
||||||
{
|
set { LifetimeFeature.RequestAborted = value; }
|
||||||
var lifetime = LifetimeFeature;
|
|
||||||
if (lifetime != null)
|
|
||||||
{
|
|
||||||
return lifetime.RequestAborted;
|
|
||||||
}
|
|
||||||
return CancellationToken.None;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ISessionCollection Session
|
public override ISessionCollection Session
|
||||||
|
|
@ -167,11 +159,7 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
|
|
||||||
public override void Abort()
|
public override void Abort()
|
||||||
{
|
{
|
||||||
var lifetime = LifetimeFeature;
|
LifetimeFeature.Abort();
|
||||||
if (lifetime != null)
|
|
||||||
{
|
|
||||||
lifetime.Abort();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
public override bool IsHttps
|
public override bool IsHttps
|
||||||
{
|
{
|
||||||
get { return string.Equals(Constants.Https, Scheme, StringComparison.OrdinalIgnoreCase); }
|
get { return string.Equals(Constants.Https, Scheme, StringComparison.OrdinalIgnoreCase); }
|
||||||
|
set { Scheme = value ? Constants.Https : Constants.Http; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override HostString Host
|
public override HostString Host
|
||||||
|
|
@ -112,6 +113,7 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
public override IReadableStringCollection Query
|
public override IReadableStringCollection Query
|
||||||
{
|
{
|
||||||
get { return QueryFeature.Query; }
|
get { return QueryFeature.Query; }
|
||||||
|
set { QueryFeature.Query = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Protocol
|
public override string Protocol
|
||||||
|
|
@ -128,6 +130,7 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
public override IReadableStringCollection Cookies
|
public override IReadableStringCollection Cookies
|
||||||
{
|
{
|
||||||
get { return RequestCookiesFeature.Cookies; }
|
get { return RequestCookiesFeature.Cookies; }
|
||||||
|
set { RequestCookiesFeature.Cookies = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ContentType
|
public override string ContentType
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
// 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.Threading;
|
||||||
|
using Microsoft.AspNet.Http.Features;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Http.Features.Internal
|
||||||
|
{
|
||||||
|
public class HttpRequestLifetimeFeature : IHttpRequestLifetimeFeature
|
||||||
|
{
|
||||||
|
public CancellationToken RequestAborted { get; set; }
|
||||||
|
|
||||||
|
public void Abort()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,6 @@ namespace Microsoft.AspNet.Http.Features.Internal
|
||||||
{
|
{
|
||||||
public interface IItemsFeature
|
public interface IItemsFeature
|
||||||
{
|
{
|
||||||
IDictionary<object, object> Items { get; }
|
IDictionary<object, object> Items { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,6 +5,6 @@ namespace Microsoft.AspNet.Http.Features.Internal
|
||||||
{
|
{
|
||||||
public interface IQueryFeature
|
public interface IQueryFeature
|
||||||
{
|
{
|
||||||
IReadableStringCollection Query { get; }
|
IReadableStringCollection Query { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,6 @@ namespace Microsoft.AspNet.Http.Features.Internal
|
||||||
{
|
{
|
||||||
public interface IRequestCookiesFeature
|
public interface IRequestCookiesFeature
|
||||||
{
|
{
|
||||||
IReadableStringCollection Cookies { get; }
|
IReadableStringCollection Cookies { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13,6 +13,6 @@ namespace Microsoft.AspNet.Http.Features.Internal
|
||||||
Items = new ItemsDictionary();
|
Items = new ItemsDictionary();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDictionary<object, object> Items { get; private set; }
|
public IDictionary<object, object> Items { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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.Collections.Generic;
|
||||||
using Microsoft.AspNet.FeatureModel;
|
using Microsoft.AspNet.FeatureModel;
|
||||||
using Microsoft.AspNet.Http.Internal;
|
using Microsoft.AspNet.Http.Internal;
|
||||||
|
|
@ -41,13 +42,22 @@ namespace Microsoft.AspNet.Http.Features.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
var queryString = _request.Fetch(_features).QueryString;
|
var queryString = _request.Fetch(_features).QueryString;
|
||||||
if (_query == null || _queryString != queryString)
|
if (_query == null || !string.Equals(_queryString, queryString, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
_queryString = queryString;
|
_queryString = queryString;
|
||||||
_query = new ReadableStringCollection(QueryHelpers.ParseQuery(queryString));
|
_query = new ReadableStringCollection(QueryHelpers.ParseQuery(queryString));
|
||||||
}
|
}
|
||||||
return _query;
|
return _query;
|
||||||
}
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_query = value;
|
||||||
|
if (_features != null)
|
||||||
|
{
|
||||||
|
_queryString = _query == null ? string.Empty : QueryString.Create(_query).ToString();
|
||||||
|
_request.Fetch(_features).QueryString = _queryString;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -50,19 +50,37 @@ namespace Microsoft.AspNet.Http.Features.Internal
|
||||||
values = new string[0];
|
values = new string[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_cookiesCollection == null)
|
if (_cookieHeaders == null || !Enumerable.SequenceEqual(_cookieHeaders, values, StringComparer.Ordinal))
|
||||||
{
|
|
||||||
_cookieHeaders = values;
|
|
||||||
_cookiesCollection = new RequestCookiesCollection();
|
|
||||||
_cookiesCollection.Reparse(values);
|
|
||||||
}
|
|
||||||
else if (!Enumerable.SequenceEqual(_cookieHeaders, values, StringComparer.Ordinal))
|
|
||||||
{
|
{
|
||||||
_cookieHeaders = values;
|
_cookieHeaders = values;
|
||||||
|
if (_cookiesCollection == null)
|
||||||
|
{
|
||||||
|
_cookiesCollection = new RequestCookiesCollection();
|
||||||
|
_cookies = _cookiesCollection;
|
||||||
|
}
|
||||||
_cookiesCollection.Reparse(values);
|
_cookiesCollection.Reparse(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _cookiesCollection;
|
return _cookies;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_cookies = value;
|
||||||
|
_cookieHeaders = null;
|
||||||
|
_cookiesCollection = _cookies as RequestCookiesCollection;
|
||||||
|
if (_cookies != null && _features != null)
|
||||||
|
{
|
||||||
|
var headers = new List<string>();
|
||||||
|
foreach (var pair in _cookies)
|
||||||
|
{
|
||||||
|
foreach (var cookieValue in pair.Value)
|
||||||
|
{
|
||||||
|
headers.Add(new CookieHeaderValue(pair.Key, cookieValue).ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_cookieHeaders = headers.ToArray();
|
||||||
|
_request.Fetch(_features).Headers[HeaderNames.Cookie] = _cookieHeaders;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,7 @@ namespace Microsoft.AspNet.Owin
|
||||||
CancellationToken IHttpRequestLifetimeFeature.RequestAborted
|
CancellationToken IHttpRequestLifetimeFeature.RequestAborted
|
||||||
{
|
{
|
||||||
get { return Prop<CancellationToken>(OwinConstants.CallCancelled); }
|
get { return Prop<CancellationToken>(OwinConstants.CallCancelled); }
|
||||||
|
set { Prop(OwinConstants.CallCancelled, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHttpRequestLifetimeFeature.Abort()
|
void IHttpRequestLifetimeFeature.Abort()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
// 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 System.Security.Claims;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Http.Features.Authentication;
|
||||||
|
using Microsoft.AspNet.Http.Features.Authentication.Internal;
|
||||||
|
using Microsoft.AspNet.Http.Internal;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Http.Authentication.Internal
|
||||||
|
{
|
||||||
|
public class AuthenticationManagerTests
|
||||||
|
{
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task AuthenticateWithNoAuthMiddlewareThrows()
|
||||||
|
{
|
||||||
|
var context = CreateContext();
|
||||||
|
Assert.Throws<InvalidOperationException>(() => context.Authentication.Authenticate("Foo"));
|
||||||
|
await Assert.ThrowsAsync<InvalidOperationException>(async () => await context.Authentication.AuthenticateAsync("Foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ChallengeWithNoAuthMiddlewareMayThrow()
|
||||||
|
{
|
||||||
|
var context = CreateContext();
|
||||||
|
context.Authentication.Challenge();
|
||||||
|
Assert.Equal(401, context.Response.StatusCode);
|
||||||
|
|
||||||
|
Assert.Throws<InvalidOperationException>(() => context.Authentication.Challenge("Foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SignInWithNoAuthMiddlewareThrows()
|
||||||
|
{
|
||||||
|
var context = CreateContext();
|
||||||
|
Assert.Throws<InvalidOperationException>(() => context.Authentication.SignIn("Foo", new ClaimsPrincipal()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SignOutWithNoAuthMiddlewareMayThrow()
|
||||||
|
{
|
||||||
|
var context = CreateContext();
|
||||||
|
context.Authentication.SignOut();
|
||||||
|
|
||||||
|
Assert.Throws<InvalidOperationException>(() => context.Authentication.SignOut("Foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void SignInOutIn()
|
||||||
|
{
|
||||||
|
var context = CreateContext();
|
||||||
|
var handler = new AuthHandler();
|
||||||
|
context.SetFeature<IHttpAuthenticationFeature>(new HttpAuthenticationFeature() { Handler = handler });
|
||||||
|
var user = new ClaimsPrincipal();
|
||||||
|
context.Authentication.SignIn("ignored", user);
|
||||||
|
Assert.True(handler.SignedIn);
|
||||||
|
context.Authentication.SignOut("ignored");
|
||||||
|
Assert.False(handler.SignedIn);
|
||||||
|
context.Authentication.SignIn("ignored", user);
|
||||||
|
Assert.True(handler.SignedIn);
|
||||||
|
context.Authentication.SignOut("ignored", new AuthenticationProperties() { RedirectUri = "~/logout" });
|
||||||
|
Assert.False(handler.SignedIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AuthHandler : IAuthenticationHandler
|
||||||
|
{
|
||||||
|
public bool SignedIn { get; set; }
|
||||||
|
|
||||||
|
public void Authenticate(AuthenticateContext context)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task AuthenticateAsync(AuthenticateContext context)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Challenge(ChallengeContext context)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetDescriptions(DescribeSchemesContext context)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SignIn(SignInContext context)
|
||||||
|
{
|
||||||
|
SignedIn = true;
|
||||||
|
context.Accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SignOut(SignOutContext context)
|
||||||
|
{
|
||||||
|
SignedIn = false;
|
||||||
|
context.Accept();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpContext CreateContext()
|
||||||
|
{
|
||||||
|
var context = new DefaultHttpContext();
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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.Linq;
|
using System.Linq;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNet.FeatureModel;
|
using Microsoft.AspNet.FeatureModel;
|
||||||
using Microsoft.AspNet.Http.Authentication;
|
using Microsoft.AspNet.Http.Features.Internal;
|
||||||
using Microsoft.AspNet.Http.Features.Authentication;
|
|
||||||
using Microsoft.AspNet.Http.Features.Authentication.Internal;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Http.Internal
|
namespace Microsoft.AspNet.Http.Internal
|
||||||
|
|
@ -44,91 +41,31 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task AuthenticateWithNoAuthMiddlewareThrows()
|
public void GetItems_DefaultCollectionProvided()
|
||||||
{
|
{
|
||||||
var context = CreateContext();
|
var context = new DefaultHttpContext(new FeatureCollection());
|
||||||
Assert.Throws<InvalidOperationException>(() => context.Authentication.Authenticate("Foo"));
|
Assert.Null(context.GetFeature<IItemsFeature>());
|
||||||
await Assert.ThrowsAsync<InvalidOperationException>(async () => await context.Authentication.AuthenticateAsync("Foo"));
|
var items = context.Items;
|
||||||
|
Assert.NotNull(context.GetFeature<IItemsFeature>());
|
||||||
|
Assert.NotNull(items);
|
||||||
|
Assert.Same(items, context.Items);
|
||||||
|
var item = new object();
|
||||||
|
context.Items["foo"] = item;
|
||||||
|
Assert.Same(item, context.Items["foo"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ChallengeWithNoAuthMiddlewareMayThrow()
|
public void SetItems_NewCollectionUsed()
|
||||||
{
|
{
|
||||||
var context = CreateContext();
|
var context = new DefaultHttpContext(new FeatureCollection());
|
||||||
context.Authentication.Challenge();
|
Assert.Null(context.GetFeature<IItemsFeature>());
|
||||||
Assert.Equal(401, context.Response.StatusCode);
|
var items = new Dictionary<object, object>();
|
||||||
|
context.Items = items;
|
||||||
Assert.Throws<InvalidOperationException>(() => context.Authentication.Challenge("Foo"));
|
Assert.NotNull(context.GetFeature<IItemsFeature>());
|
||||||
}
|
Assert.Same(items, context.Items);
|
||||||
|
var item = new object();
|
||||||
[Fact]
|
items["foo"] = item;
|
||||||
public void SignInWithNoAuthMiddlewareThrows()
|
Assert.Same(item, context.Items["foo"]);
|
||||||
{
|
|
||||||
var context = CreateContext();
|
|
||||||
Assert.Throws<InvalidOperationException>(() => context.Authentication.SignIn("Foo", new ClaimsPrincipal()));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void SignOutWithNoAuthMiddlewareMayThrow()
|
|
||||||
{
|
|
||||||
var context = CreateContext();
|
|
||||||
context.Authentication.SignOut();
|
|
||||||
|
|
||||||
Assert.Throws<InvalidOperationException>(() => context.Authentication.SignOut("Foo"));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void SignInOutIn()
|
|
||||||
{
|
|
||||||
var context = CreateContext();
|
|
||||||
var handler = new AuthHandler();
|
|
||||||
context.SetFeature<IHttpAuthenticationFeature>(new HttpAuthenticationFeature() { Handler = handler });
|
|
||||||
var user = new ClaimsPrincipal();
|
|
||||||
context.Authentication.SignIn("ignored", user);
|
|
||||||
Assert.True(handler.SignedIn);
|
|
||||||
context.Authentication.SignOut("ignored");
|
|
||||||
Assert.False(handler.SignedIn);
|
|
||||||
context.Authentication.SignIn("ignored", user);
|
|
||||||
Assert.True(handler.SignedIn);
|
|
||||||
context.Authentication.SignOut("ignored", new AuthenticationProperties() { RedirectUri = "~/logout" });
|
|
||||||
Assert.False(handler.SignedIn);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class AuthHandler : IAuthenticationHandler
|
|
||||||
{
|
|
||||||
public bool SignedIn { get; set; }
|
|
||||||
|
|
||||||
public void Authenticate(AuthenticateContext context)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task AuthenticateAsync(AuthenticateContext context)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Challenge(ChallengeContext context)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GetDescriptions(DescribeSchemesContext context)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SignIn(SignInContext context)
|
|
||||||
{
|
|
||||||
SignedIn = true;
|
|
||||||
context.Accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SignOut(SignOutContext context)
|
|
||||||
{
|
|
||||||
SignedIn = false;
|
|
||||||
context.Accept();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpContext CreateContext()
|
private HttpContext CreateContext()
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,78 @@ namespace Microsoft.AspNet.Http.Internal
|
||||||
Assert.Equal(expected, headers["Host"][0]);
|
Assert.Equal(expected, headers["Host"][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsHttps_CorrectlyReflectsScheme()
|
||||||
|
{
|
||||||
|
var request = new DefaultHttpContext().Request;
|
||||||
|
Assert.Equal(string.Empty, request.Scheme);
|
||||||
|
Assert.False(request.IsHttps);
|
||||||
|
request.IsHttps = true;
|
||||||
|
Assert.Equal("https", request.Scheme);
|
||||||
|
request.IsHttps = false;
|
||||||
|
Assert.Equal("http", request.Scheme);
|
||||||
|
request.Scheme = "ftp";
|
||||||
|
Assert.False(request.IsHttps);
|
||||||
|
request.Scheme = "HTTPS";
|
||||||
|
Assert.True(request.IsHttps);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Query_GetAndSet()
|
||||||
|
{
|
||||||
|
var request = new DefaultHttpContext().Request;
|
||||||
|
var requestFeature = request.HttpContext.GetFeature<IHttpRequestFeature>();
|
||||||
|
Assert.Equal(string.Empty, requestFeature.QueryString);
|
||||||
|
Assert.Equal(QueryString.Empty, request.QueryString);
|
||||||
|
var query0 = request.Query;
|
||||||
|
Assert.NotNull(query0);
|
||||||
|
Assert.Equal(0, query0.Count);
|
||||||
|
|
||||||
|
requestFeature.QueryString = "?name0=value0&name1=value1";
|
||||||
|
var query1 = request.Query;
|
||||||
|
Assert.NotSame(query0, query1);
|
||||||
|
Assert.Equal(2, query1.Count);
|
||||||
|
Assert.Equal("value0", query1["name0"]);
|
||||||
|
Assert.Equal("value1", query1["name1"]);
|
||||||
|
|
||||||
|
var query2 = new ReadableStringCollection(new Dictionary<string, string[]>()
|
||||||
|
{
|
||||||
|
{ "name2", new[] { "value2" } }
|
||||||
|
});
|
||||||
|
|
||||||
|
request.Query = query2;
|
||||||
|
Assert.Same(query2, request.Query);
|
||||||
|
Assert.Equal("?name2=value2", requestFeature.QueryString);
|
||||||
|
Assert.Equal(new QueryString("?name2=value2"), request.QueryString);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Cookies_GetAndSet()
|
||||||
|
{
|
||||||
|
var request = new DefaultHttpContext().Request;
|
||||||
|
var cookieHeaders = request.Headers.GetValues("Cookie");
|
||||||
|
Assert.Null(cookieHeaders);
|
||||||
|
var cookies0 = request.Cookies;
|
||||||
|
Assert.Equal(0, cookies0.Count);
|
||||||
|
|
||||||
|
request.Headers.SetValues("Cookie", new[] { "name0=value0", "name1=value1" });
|
||||||
|
var cookies1 = request.Cookies;
|
||||||
|
Assert.Same(cookies0, cookies1);
|
||||||
|
Assert.Equal(2, cookies1.Count);
|
||||||
|
Assert.Equal("value0", cookies1["name0"]);
|
||||||
|
Assert.Equal("value1", cookies1["name1"]);
|
||||||
|
|
||||||
|
var cookies2 = new ReadableStringCollection(new Dictionary<string, string[]>()
|
||||||
|
{
|
||||||
|
{ "name2", new[] { "value2" } }
|
||||||
|
});
|
||||||
|
request.Cookies = cookies2;
|
||||||
|
Assert.Same(cookies2, request.Cookies);
|
||||||
|
Assert.Equal("value2", request.Cookies["name2"]);
|
||||||
|
cookieHeaders = request.Headers.GetValues("Cookie");
|
||||||
|
Assert.Equal(new[] { "name2=value2" }, cookieHeaders);
|
||||||
|
}
|
||||||
|
|
||||||
private static HttpRequest CreateRequest(IDictionary<string, string[]> headers)
|
private static HttpRequest CreateRequest(IDictionary<string, string[]> headers)
|
||||||
{
|
{
|
||||||
var context = new DefaultHttpContext();
|
var context = new DefaultHttpContext();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue