Add CookieBuilder

This commit is contained in:
Nate McMaster 2017-06-29 12:23:06 -07:00
parent 9bf94d3667
commit f9e0439ef1
3 changed files with 140 additions and 1 deletions

View File

@ -0,0 +1,93 @@
// 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;
namespace Microsoft.AspNetCore.Http
{
/// <summary>
/// Defines settings used to create a cookie.
/// </summary>
public class CookieBuilder
{
/// <summary>
/// The name of the cookie.
/// </summary>
public virtual string Name { get; set; }
/// <summary>
/// The cookie path.
/// </summary>
/// <remarks>
/// Determines the value that will set on <seealso cref="CookieOptions.Path"/>.
/// </remarks>
public virtual string Path { get; set; }
/// <summary>
/// The domain to associate the cookie with.
/// </summary>
/// <remarks>
/// Determines the value that will set on <seealso cref="CookieOptions.Domain"/>.
/// </remarks>
public virtual string Domain { get; set; }
/// <summary>
/// Indicates whether a cookie is accessible by client-side script.
/// </summary>
/// <remarks>
/// Determines the value that will set on <seealso cref="CookieOptions.HttpOnly"/>.
/// </remarks>
public virtual bool HttpOnly { get; set; }
/// <summary>
/// The SameSite attribute of the cookie. The default value is <see cref="SameSiteMode.Lax"/>
/// </summary>
/// <remarks>
/// Determines the value that will set on <seealso cref="CookieOptions.SameSite"/>.
/// </remarks>
public virtual SameSiteMode SameSite { get; set; } = SameSiteMode.Lax;
/// <summary>
/// The policy that will be used to determine <seealso cref="CookieOptions.Secure"/>.
/// This is determined from the <see cref="HttpContext"/> passed to <see cref="Build(HttpContext)"/>.
/// </summary>
public virtual CookieSecurePolicy SecurePolicy { get; set; }
/// <summary>
/// Gets or sets the lifespan of a cookie.
/// </summary>
public virtual TimeSpan? Expiration { get; set; }
/// <summary>
/// Creates the cookie options from the given <paramref name="context"/>.
/// </summary>
/// <param name="context">The <see cref="HttpContext"/>.</param>
/// <returns>The cookie options.</returns>
public virtual CookieOptions Build(HttpContext context) => Build(context, DateTimeOffset.Now);
/// <summary>
/// Creates the cookie options from the given <paramref name="context"/> with an expiration based on <paramref name="expiresFrom"/> and <see cref="Expiration"/>.
/// </summary>
/// <param name="context">The <see cref="HttpContext"/>.</param>
/// <param name="expiresFrom">The time to use as the base for computing <seealso cref="CookieOptions.Expires" />.</param>
/// <returns>The cookie options.</returns>
public virtual CookieOptions Build(HttpContext context, DateTimeOffset expiresFrom)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
return new CookieOptions
{
Path = Path ?? "/",
SameSite = SameSite,
HttpOnly = HttpOnly,
Domain = Domain,
Secure = SecurePolicy == CookieSecurePolicy.Always || (SecurePolicy == CookieSecurePolicy.SameAsRequest && context.Request.IsHttps),
Expires = Expiration.HasValue ? expiresFrom.Add(Expiration.Value) : default(DateTimeOffset?)
};
}
}
}

View File

@ -42,7 +42,6 @@ namespace Microsoft.AspNetCore.Http
/// <returns>true to transmit the cookie only over an SSL connection (HTTPS); otherwise, false.</returns>
public bool Secure { get; set; }
/// <summary>
/// Gets or sets the value for the SameSite attribute of the cookie. The default value is <see cref="SameSiteMode.Lax"/>
/// </summary>

View File

@ -0,0 +1,47 @@
// 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 Xunit;
namespace Microsoft.AspNetCore.Http.Abstractions.Tests
{
public class CookieBuilderTests
{
[Theory]
[InlineData(CookieSecurePolicy.Always, false, true)]
[InlineData(CookieSecurePolicy.Always, true, true)]
[InlineData(CookieSecurePolicy.SameAsRequest, true, true)]
[InlineData(CookieSecurePolicy.SameAsRequest, false, false)]
[InlineData(CookieSecurePolicy.None, true, false)]
[InlineData(CookieSecurePolicy.None, false, false)]
public void ConfiguresSecurePolicy(CookieSecurePolicy policy, bool requestIsHttps, bool secure)
{
var builder = new CookieBuilder
{
SecurePolicy = policy
};
var context = new DefaultHttpContext();
context.Request.IsHttps = requestIsHttps;
var options = builder.Build(context);
Assert.Equal(secure, options.Secure);
}
[Fact]
public void ComputesExpiration()
{
Assert.Null(new CookieBuilder().Build(new DefaultHttpContext()).Expires);
var now = DateTimeOffset.Now;
var options = new CookieBuilder { Expiration = TimeSpan.FromHours(1) }.Build(new DefaultHttpContext(), now);
Assert.Equal(now.AddHours(1), options.Expires);
}
[Fact]
public void CookieBuilderPreservesDefaultPath()
{
Assert.Equal(new CookieOptions().Path, new CookieBuilder().Build(new DefaultHttpContext()).Path);
}
}
}