#167: Update cookie APIs to use shared core.
This commit is contained in:
parent
09d6ab03bc
commit
e818783ba4
|
|
@ -4,8 +4,7 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Core.Infrastructure;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNet.Http.Core.Collections
|
||||
{
|
||||
|
|
@ -73,12 +72,20 @@ namespace Microsoft.AspNet.Http.Core.Collections
|
|||
return _dictionary.TryGetValue(key, out value) ? new[] { value } : null;
|
||||
}
|
||||
|
||||
private static readonly char[] SemicolonAndComma = { ';', ',' };
|
||||
|
||||
public void Reparse(string cookiesHeader)
|
||||
public void Reparse(IList<string> values)
|
||||
{
|
||||
_dictionary.Clear();
|
||||
ParsingHelpers.ParseDelimited(cookiesHeader, SemicolonAndComma, AddCookieCallback, _dictionary);
|
||||
|
||||
IList<CookieHeaderValue> cookies;
|
||||
if (CookieHeaderValue.TryParseList(values, out cookies))
|
||||
{
|
||||
foreach (var cookie in cookies)
|
||||
{
|
||||
var name = Uri.UnescapeDataString(cookie.Name.Replace('+', ' '));
|
||||
var value = Uri.UnescapeDataString(cookie.Value.Replace('+', ' '));
|
||||
_dictionary[name] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, string[]>> GetEnumerator()
|
||||
|
|
@ -93,14 +100,5 @@ namespace Microsoft.AspNet.Http.Core.Collections
|
|||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
private static readonly Action<string, string, object> AddCookieCallback = (name, value, state) =>
|
||||
{
|
||||
var dictionary = (IDictionary<string, string>)state;
|
||||
if (!dictionary.ContainsKey(name))
|
||||
{
|
||||
dictionary.Add(name, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.WebEncoders;
|
||||
|
|
@ -34,7 +33,11 @@ namespace Microsoft.AspNet.Http.Core.Collections
|
|||
/// <param name="value"></param>
|
||||
public void Append(string key, string value)
|
||||
{
|
||||
Headers.AppendValues(HeaderNames.SetCookie, UrlEncoder.Default.UrlEncode(key) + "=" + UrlEncoder.Default.UrlEncode(value) + "; path=/");
|
||||
Headers.AppendValues(HeaderNames.SetCookie,
|
||||
new SetCookieHeaderValue(
|
||||
UrlEncoder.Default.UrlEncode(key),
|
||||
UrlEncoder.Default.UrlEncode(value))
|
||||
{ Path = "/" }.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -45,23 +48,17 @@ namespace Microsoft.AspNet.Http.Core.Collections
|
|||
/// <param name="options"></param>
|
||||
public void Append(string key, string value, [NotNull] CookieOptions options)
|
||||
{
|
||||
bool domainHasValue = !string.IsNullOrEmpty(options.Domain);
|
||||
bool pathHasValue = !string.IsNullOrEmpty(options.Path);
|
||||
bool expiresHasValue = options.Expires.HasValue;
|
||||
|
||||
string setCookieValue = string.Concat(
|
||||
UrlEncoder.Default.UrlEncode(key),
|
||||
"=",
|
||||
UrlEncoder.Default.UrlEncode(value ?? string.Empty),
|
||||
!domainHasValue ? null : "; domain=",
|
||||
!domainHasValue ? null : options.Domain,
|
||||
!pathHasValue ? null : "; path=",
|
||||
!pathHasValue ? null : options.Path,
|
||||
!expiresHasValue ? null : "; expires=",
|
||||
!expiresHasValue ? null : options.Expires.Value.ToString("ddd, dd-MMM-yyyy HH:mm:ss ", CultureInfo.InvariantCulture) + "GMT",
|
||||
!options.Secure ? null : "; secure",
|
||||
!options.HttpOnly ? null : "; HttpOnly");
|
||||
Headers.AppendValues(HeaderNames.SetCookie, setCookieValue);
|
||||
Headers.AppendValues(HeaderNames.SetCookie,
|
||||
new SetCookieHeaderValue(
|
||||
UrlEncoder.Default.UrlEncode(key),
|
||||
UrlEncoder.Default.UrlEncode(value))
|
||||
{
|
||||
Domain = options.Domain,
|
||||
Path = options.Path,
|
||||
Expires = options.Expires,
|
||||
Secure = options.Secure,
|
||||
HttpOnly = options.HttpOnly,
|
||||
}.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -70,9 +67,10 @@ namespace Microsoft.AspNet.Http.Core.Collections
|
|||
/// <param name="key"></param>
|
||||
public void Delete(string key)
|
||||
{
|
||||
Func<string, bool> predicate = value => value.StartsWith(key + "=", StringComparison.OrdinalIgnoreCase);
|
||||
var encodedKeyPlusEquals = UrlEncoder.Default.UrlEncode(key) + "=";
|
||||
Func<string, bool> predicate = value => value.StartsWith(encodedKeyPlusEquals, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
var deleteCookies = new[] { UrlEncoder.Default.UrlEncode(key) + "=; expires=Thu, 01-Jan-1970 00:00:00 GMT" };
|
||||
var deleteCookies = new[] { encodedKeyPlusEquals + "; expires=Thu, 01-Jan-1970 00:00:00 GMT" };
|
||||
IList<string> existingValues = Headers.GetValues(HeaderNames.SetCookie);
|
||||
if (existingValues == null || existingValues.Count == 0)
|
||||
{
|
||||
|
|
@ -91,6 +89,7 @@ namespace Microsoft.AspNet.Http.Core.Collections
|
|||
/// <param name="options"></param>
|
||||
public void Delete(string key, [NotNull] CookieOptions options)
|
||||
{
|
||||
var encodedKeyPlusEquals = UrlEncoder.Default.UrlEncode(key) + "=";
|
||||
bool domainHasValue = !string.IsNullOrEmpty(options.Domain);
|
||||
bool pathHasValue = !string.IsNullOrEmpty(options.Path);
|
||||
|
||||
|
|
@ -98,18 +97,18 @@ namespace Microsoft.AspNet.Http.Core.Collections
|
|||
if (domainHasValue)
|
||||
{
|
||||
rejectPredicate = value =>
|
||||
value.StartsWith(key + "=", StringComparison.OrdinalIgnoreCase) &&
|
||||
value.StartsWith(encodedKeyPlusEquals, StringComparison.OrdinalIgnoreCase) &&
|
||||
value.IndexOf("domain=" + options.Domain, StringComparison.OrdinalIgnoreCase) != -1;
|
||||
}
|
||||
else if (pathHasValue)
|
||||
{
|
||||
rejectPredicate = value =>
|
||||
value.StartsWith(key + "=", StringComparison.OrdinalIgnoreCase) &&
|
||||
value.StartsWith(encodedKeyPlusEquals, StringComparison.OrdinalIgnoreCase) &&
|
||||
value.IndexOf("path=" + options.Path, StringComparison.OrdinalIgnoreCase) != -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rejectPredicate = value => value.StartsWith(key + "=", StringComparison.OrdinalIgnoreCase);
|
||||
rejectPredicate = value => value.StartsWith(encodedKeyPlusEquals, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
IList<string> existingValues = Headers.GetValues(HeaderNames.SetCookie);
|
||||
|
|
|
|||
|
|
@ -496,71 +496,6 @@ namespace Microsoft.AspNet.Http.Core.Infrastructure
|
|||
|
||||
internal static class ParsingHelpers
|
||||
{
|
||||
private static readonly Action<string, string, object> AddCookieCallback = (name, value, state) =>
|
||||
{
|
||||
var dictionary = (IDictionary<string, string>)state;
|
||||
if (!dictionary.ContainsKey(name))
|
||||
{
|
||||
dictionary.Add(name, value);
|
||||
}
|
||||
};
|
||||
|
||||
private static readonly char[] SemicolonAndComma = new[] { ';', ',' };
|
||||
|
||||
internal static T GetItem<T>(HttpRequest request, string key)
|
||||
{
|
||||
object value;
|
||||
return request.HttpContext.Items.TryGetValue(key, out value) ? (T)value : default(T);
|
||||
}
|
||||
|
||||
internal static void SetItem<T>(HttpRequest request, string key, T value)
|
||||
{
|
||||
request.HttpContext.Items[key] = value;
|
||||
}
|
||||
|
||||
internal static void ParseCookies(string cookiesHeader, IDictionary<string, string> cookiesCollection)
|
||||
{
|
||||
ParseDelimited(cookiesHeader, SemicolonAndComma, AddCookieCallback, cookiesCollection);
|
||||
}
|
||||
|
||||
internal static void ParseDelimited(string text, char[] delimiters, Action<string, string, object> callback, object state)
|
||||
{
|
||||
int textLength = text.Length;
|
||||
int equalIndex = text.IndexOf('=');
|
||||
if (equalIndex == -1)
|
||||
{
|
||||
equalIndex = textLength;
|
||||
}
|
||||
int scanIndex = 0;
|
||||
while (scanIndex < textLength)
|
||||
{
|
||||
int delimiterIndex = text.IndexOfAny(delimiters, scanIndex);
|
||||
if (delimiterIndex == -1)
|
||||
{
|
||||
delimiterIndex = textLength;
|
||||
}
|
||||
if (equalIndex < delimiterIndex)
|
||||
{
|
||||
while (scanIndex != equalIndex && char.IsWhiteSpace(text[scanIndex]))
|
||||
{
|
||||
++scanIndex;
|
||||
}
|
||||
string name = text.Substring(scanIndex, equalIndex - scanIndex);
|
||||
string value = text.Substring(equalIndex + 1, delimiterIndex - equalIndex - 1);
|
||||
callback(
|
||||
Uri.UnescapeDataString(name.Replace('+', ' ')),
|
||||
Uri.UnescapeDataString(value.Replace('+', ' ')),
|
||||
state);
|
||||
equalIndex = text.IndexOf('=', delimiterIndex);
|
||||
if (equalIndex == -1)
|
||||
{
|
||||
equalIndex = textLength;
|
||||
}
|
||||
}
|
||||
scanIndex = delimiterIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetHeader(IDictionary<string, string[]> headers, string key)
|
||||
{
|
||||
string[] values = GetHeaderUnmodified(headers, key);
|
||||
|
|
@ -729,48 +664,6 @@ namespace Microsoft.AspNet.Http.Core.Infrastructure
|
|||
}
|
||||
}
|
||||
|
||||
private static readonly Action<string, string, object> AppendItemCallback = (name, value, state) =>
|
||||
{
|
||||
var dictionary = (IDictionary<string, List<String>>)state;
|
||||
|
||||
List<string> existing;
|
||||
if (!dictionary.TryGetValue(name, out existing))
|
||||
{
|
||||
dictionary.Add(name, new List<string>(1) { value });
|
||||
}
|
||||
else
|
||||
{
|
||||
existing.Add(value);
|
||||
}
|
||||
};
|
||||
|
||||
internal static string GetJoinedValue(IDictionary<string, string[]> store, string key)
|
||||
{
|
||||
string[] values = GetUnmodifiedValues(store, key);
|
||||
return values == null ? null : string.Join(",", values);
|
||||
}
|
||||
|
||||
internal static string[] GetUnmodifiedValues([NotNull] IDictionary<string, string[]> store, string key)
|
||||
{
|
||||
string[] values;
|
||||
return store.TryGetValue(key, out values) ? values : null;
|
||||
}
|
||||
|
||||
//internal static string GetHost(HttpRequest request)
|
||||
//{
|
||||
// IHeaderDictionary headers = request.Headers;
|
||||
|
||||
// string host = GetHeader(headers, "Host");
|
||||
// if (!string.IsNullOrWhiteSpace(host))
|
||||
// {
|
||||
// return host;
|
||||
// }
|
||||
|
||||
// string localIpAddress = request.LocalIpAddress ?? "localhost";
|
||||
// var localPort = request.Get<string>(OwinConstants.CommonKeys.LocalPort);
|
||||
// return string.IsNullOrWhiteSpace(localPort) ? localIpAddress : (localIpAddress + ":" + localPort);
|
||||
//}
|
||||
|
||||
public static long? GetContentLength([NotNull] IHeaderDictionary headers)
|
||||
{
|
||||
const NumberStyles styles = NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.FeatureModel;
|
||||
using Microsoft.AspNet.Http.Core.Collections;
|
||||
using Microsoft.AspNet.Http.Core.Infrastructure;
|
||||
|
|
@ -15,7 +16,7 @@ namespace Microsoft.AspNet.Http.Core
|
|||
{
|
||||
private readonly IFeatureCollection _features;
|
||||
private readonly FeatureReference<IHttpRequestFeature> _request = FeatureReference<IHttpRequestFeature>.Default;
|
||||
private string _cookiesHeader;
|
||||
private string[] _cookieHeaders;
|
||||
private RequestCookiesCollection _cookiesCollection;
|
||||
private IReadableStringCollection _cookies;
|
||||
|
||||
|
|
@ -44,18 +45,22 @@ namespace Microsoft.AspNet.Http.Core
|
|||
}
|
||||
|
||||
var headers = _request.Fetch(_features).Headers;
|
||||
string cookiesHeader = ParsingHelpers.GetHeader(headers, HeaderNames.Cookie) ?? string.Empty;
|
||||
string[] values;
|
||||
if (!headers.TryGetValue(HeaderNames.Cookie, out values))
|
||||
{
|
||||
values = new string[0];
|
||||
}
|
||||
|
||||
if (_cookiesCollection == null)
|
||||
{
|
||||
_cookieHeaders = values;
|
||||
_cookiesCollection = new RequestCookiesCollection();
|
||||
_cookiesCollection.Reparse(cookiesHeader);
|
||||
_cookiesHeader = cookiesHeader;
|
||||
_cookiesCollection.Reparse(values);
|
||||
}
|
||||
else if (!string.Equals(_cookiesHeader, cookiesHeader, StringComparison.Ordinal))
|
||||
else if (!Enumerable.SequenceEqual(_cookieHeaders, values, StringComparer.Ordinal))
|
||||
{
|
||||
_cookiesCollection.Reparse(cookiesHeader);
|
||||
_cookiesHeader = cookiesHeader;
|
||||
_cookieHeaders = values;
|
||||
_cookiesCollection.Reparse(values);
|
||||
}
|
||||
|
||||
return _cookiesCollection;
|
||||
|
|
|
|||
Loading…
Reference in New Issue