Improve request and response cookie handling.
This commit is contained in:
parent
ca2ef860f5
commit
ae9545a124
|
|
@ -20,3 +20,5 @@ nuget.exe
|
||||||
*.userprefs
|
*.userprefs
|
||||||
*DS_Store
|
*DS_Store
|
||||||
*.ncrunchsolution
|
*.ncrunchsolution
|
||||||
|
*.*sdf
|
||||||
|
*.ipch
|
||||||
|
|
@ -15,6 +15,7 @@ namespace Microsoft.AspNet.Abstractions
|
||||||
public abstract long? ContentLength { get; set; }
|
public abstract long? ContentLength { get; set; }
|
||||||
public abstract string ContentType { get; set; }
|
public abstract string ContentType { get; set; }
|
||||||
|
|
||||||
|
public abstract IResponseCookiesCollection Cookies { get; }
|
||||||
public abstract Task WriteAsync(string data);
|
public abstract Task WriteAsync(string data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Abstractions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A wrapper for the response Set-Cookie header
|
||||||
|
/// </summary>
|
||||||
|
public interface IResponseCookiesCollection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Add a new cookie and value
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
void Append(string key, string value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a new cookie
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="options"></param>
|
||||||
|
void Append(string key, string value, CookieOptions options);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets an expired cookie
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
void Delete(string key);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets an expired cookie
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="options"></param>
|
||||||
|
void Delete(string key, CookieOptions options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.PipelineCore.Collections
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A wrapper for the request Cookie header
|
|
||||||
/// </summary>
|
|
||||||
public class RequestCookieCollection : IEnumerable<KeyValuePair<string, string>>
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Create a new wrapper
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="store"></param>
|
|
||||||
public RequestCookieCollection(IDictionary<string, string> store)
|
|
||||||
{
|
|
||||||
if (store == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("store");
|
|
||||||
}
|
|
||||||
|
|
||||||
Store = store;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IDictionary<string, string> Store { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns null rather than throwing KeyNotFoundException
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public string this[string key]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
string value;
|
|
||||||
Store.TryGetValue(key, out value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
|
||||||
{
|
|
||||||
return Store.GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
|
||||||
{
|
|
||||||
return GetEnumerator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||||
using Microsoft.AspNet.Abstractions;
|
using Microsoft.AspNet.Abstractions;
|
||||||
using Microsoft.AspNet.PipelineCore.Infrastructure;
|
using Microsoft.AspNet.PipelineCore.Infrastructure;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.PipelineCore
|
namespace Microsoft.AspNet.PipelineCore.Collections
|
||||||
{
|
{
|
||||||
public class RequestCookiesCollection : IReadableStringCollection
|
public class RequestCookiesCollection : IReadableStringCollection
|
||||||
{
|
{
|
||||||
|
|
@ -3,20 +3,19 @@ using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNet.Abstractions.Infrastructure;
|
using Microsoft.AspNet.Abstractions.Infrastructure;
|
||||||
using Microsoft.AspNet.Abstractions;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.PipelineCore.Collections
|
namespace Microsoft.AspNet.Abstractions.Collections
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A wrapper for the response Set-Cookie header
|
/// A wrapper for the response Set-Cookie header
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ResponseCookieCollection
|
public class ResponseCookiesCollection : IResponseCookiesCollection
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new wrapper
|
/// Create a new wrapper
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="headers"></param>
|
/// <param name="headers"></param>
|
||||||
public ResponseCookieCollection(IHeaderDictionary headers)
|
public ResponseCookiesCollection(IHeaderDictionary headers)
|
||||||
{
|
{
|
||||||
if (headers == null)
|
if (headers == null)
|
||||||
{
|
{
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNet.Abstractions;
|
using Microsoft.AspNet.Abstractions;
|
||||||
|
using Microsoft.AspNet.Abstractions.Infrastructure;
|
||||||
using Microsoft.AspNet.FeatureModel;
|
using Microsoft.AspNet.FeatureModel;
|
||||||
using Microsoft.AspNet.HttpFeature;
|
using Microsoft.AspNet.HttpFeature;
|
||||||
|
using Microsoft.AspNet.PipelineCore.Collections;
|
||||||
using Microsoft.AspNet.PipelineCore.Infrastructure;
|
using Microsoft.AspNet.PipelineCore.Infrastructure;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.PipelineCore
|
namespace Microsoft.AspNet.PipelineCore
|
||||||
|
|
@ -24,7 +26,7 @@ namespace Microsoft.AspNet.PipelineCore
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var headers = _request.Fetch(_features).Headers;
|
var headers = _request.Fetch(_features).Headers;
|
||||||
string cookiesHeader = ParsingHelpers.GetHeader(headers, "Cookies") ?? "";
|
string cookiesHeader = ParsingHelpers.GetHeader(headers, Constants.Headers.Cookie) ?? "";
|
||||||
|
|
||||||
if (_cookiesCollection == null)
|
if (_cookiesCollection == null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
using Microsoft.AspNet.Abstractions;
|
||||||
|
using Microsoft.AspNet.Abstractions.Collections;
|
||||||
|
using Microsoft.AspNet.FeatureModel;
|
||||||
|
using Microsoft.AspNet.HttpFeature;
|
||||||
|
using Microsoft.AspNet.PipelineCore.Collections;
|
||||||
|
using Microsoft.AspNet.PipelineCore.Infrastructure;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.PipelineCore
|
||||||
|
{
|
||||||
|
public class DefaultCanHasResponseCookies : ICanHasResponseCookies
|
||||||
|
{
|
||||||
|
private readonly IFeatureCollection _features;
|
||||||
|
private FeatureReference<IHttpResponseInformation> _request = FeatureReference<IHttpResponseInformation>.Default;
|
||||||
|
private IResponseCookiesCollection _cookiesCollection;
|
||||||
|
|
||||||
|
public DefaultCanHasResponseCookies(IFeatureCollection features)
|
||||||
|
{
|
||||||
|
_features = features;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IResponseCookiesCollection Cookies
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var headers = _request.Fetch(_features).Headers;
|
||||||
|
if (_cookiesCollection == null)
|
||||||
|
{
|
||||||
|
_cookiesCollection = new ResponseCookiesCollection(new HeaderDictionary(headers));
|
||||||
|
}
|
||||||
|
|
||||||
|
return _cookiesCollection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,6 +16,7 @@ namespace Microsoft.AspNet.PipelineCore
|
||||||
private readonly DefaultHttpContext _context;
|
private readonly DefaultHttpContext _context;
|
||||||
private readonly IFeatureCollection _features;
|
private readonly IFeatureCollection _features;
|
||||||
private FeatureReference<IHttpResponseInformation> _response = FeatureReference<IHttpResponseInformation>.Default;
|
private FeatureReference<IHttpResponseInformation> _response = FeatureReference<IHttpResponseInformation>.Default;
|
||||||
|
private FeatureReference<ICanHasResponseCookies> _canHasCookies = FeatureReference<ICanHasResponseCookies>.Default;
|
||||||
|
|
||||||
public DefaultHttpResponse(DefaultHttpContext context, IFeatureCollection features)
|
public DefaultHttpResponse(DefaultHttpContext context, IFeatureCollection features)
|
||||||
{
|
{
|
||||||
|
|
@ -28,6 +29,11 @@ namespace Microsoft.AspNet.PipelineCore
|
||||||
get { return _response.Fetch(_features); }
|
get { return _response.Fetch(_features); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ICanHasResponseCookies CanHasResponseCookies
|
||||||
|
{
|
||||||
|
get { return _canHasCookies.Fetch(_features) ?? _canHasCookies.Update(_features, new DefaultCanHasResponseCookies(_features)); }
|
||||||
|
}
|
||||||
|
|
||||||
public override HttpContext HttpContext { get { return _context; } }
|
public override HttpContext HttpContext { get { return _context; } }
|
||||||
|
|
||||||
public override int StatusCode
|
public override int StatusCode
|
||||||
|
|
@ -79,6 +85,10 @@ namespace Microsoft.AspNet.PipelineCore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override IResponseCookiesCollection Cookies
|
||||||
|
{
|
||||||
|
get { return CanHasResponseCookies.Cookies; }
|
||||||
|
}
|
||||||
public override Task WriteAsync(string data)
|
public override Task WriteAsync(string data)
|
||||||
{
|
{
|
||||||
var bytes = Encoding.UTF8.GetBytes(data);
|
var bytes = Encoding.UTF8.GetBytes(data);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
using Microsoft.AspNet.Abstractions;
|
||||||
|
using Microsoft.AspNet.PipelineCore.Collections;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.PipelineCore
|
||||||
|
{
|
||||||
|
public interface ICanHasResponseCookies
|
||||||
|
{
|
||||||
|
IResponseCookiesCollection Cookies { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ namespace Microsoft.AspNet.Abstractions.Infrastructure
|
||||||
internal const string ETag = "ETag";
|
internal const string ETag = "ETag";
|
||||||
internal const string Location = "Location";
|
internal const string Location = "Location";
|
||||||
internal const string ContentLength = "Content-Length";
|
internal const string ContentLength = "Content-Length";
|
||||||
|
internal const string Cookie = "Cookie";
|
||||||
internal const string SetCookie = "Set-Cookie";
|
internal const string SetCookie = "Set-Cookie";
|
||||||
internal const string Expires = "Expires";
|
internal const string Expires = "Expires";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue