using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Store.Framework.Models
{
///
/// Cookie集合,支持普通 Cookie 字符串和 API 返回的 Cookie JSON。
///
[JsonConverter(typeof(CookiesJsonConverter))]
public class Cookies : Dictionary
{
private readonly string oldCookie;
public Cookies(string cookie)
{
oldCookie = cookie;
Load(cookie);
}
///
/// Cookie字符串
///
public string CookieString
{
get
{
return GetCookieString();
}
}
///
/// 获取指定值
///
///
/// 默认值
///
public string GetValue(string key, string defvalue)
{
if (ContainsKey(key))
{
return this[key];
}
return defvalue;
}
///
/// 添加或修改
///
///
///
public void AddOrUpdate(string key, string value)
{
if (!this.ContainsKey(key))
{
Add(key, value);
}
else
{
this[key] = value;
}
}
///
/// 获取Cookies字符串
///
///
public virtual string GetCookieString()
{
var list = this.Select(a => { return $"{a.Key}={a.Value}"; });
return string.Join(";", list);
}
///
/// 转为浏览器 Cookie 字符串。
///
public override string ToString()
{
var list = this.Select(a => { return $"{a.Key}={a.Value}"; });
return string.Join("; ", list);
}
///
/// 隐式转换
///
///
public static implicit operator string(Cookies cookie)
{
return cookie.GetCookieString();
}
internal static Cookies FromToken(JToken token)
{
Cookies cookies = new Cookies(string.Empty);
if (token == null || token.Type == JTokenType.Null)
return cookies;
if (token.Type == JTokenType.String)
return new Cookies(token.ToString());
cookies.AddToken(token);
return cookies;
}
private void Load(string cookie)
{
Clear();
if (string.IsNullOrWhiteSpace(cookie))
return;
try
{
AddToken(JToken.Parse(cookie));
if (Count > 0)
return;
}
catch (JsonException)
{
}
SplitCookie(Decode(cookie));
}
private void AddToken(JToken token)
{
if (token == null || token.Type == JTokenType.Null)
return;
if (token is JArray array)
{
foreach (JToken item in array)
{
AddCookie(item);
}
return;
}
AddCookie(token);
}
private void AddCookie(JToken token)
{
if (token == null || token.Type == JTokenType.Null)
return;
if (token.Type == JTokenType.String)
{
string value = token.ToString();
int index = value.IndexOf('=');
if (index <= 0)
return;
AddOrUpdate(value.Substring(0, index).Trim(), value.Substring(index + 1).Trim());
return;
}
JToken name = token["Name"] ?? token["name"];
JToken valueToken = token["Value"] ?? token["value"];
if (name == null || valueToken == null)
return;
AddOrUpdate(name.ToString(), valueToken.ToString());
}
///
/// 拆分普通 Cookie 字符串。
///
private void SplitCookie(string cookie)
{
Clear();
if (string.IsNullOrEmpty(cookie))
return;
Regex regCookie = new Regex("(?.+?)=(?.+?)(;|$)");
if (regCookie.IsMatch(cookie))
{
MatchCollection matchs = regCookie.Matches(cookie);
foreach (Match item in matchs)
{
string key = item.Groups["key"].Value.Trim();
string value = item.Groups["value"].Value.Trim();
if (!ContainsKey(key))
{
this.Add(key, value);
}
}
}
}
private static string Decode(string value)
{
return (value ?? string.Empty)
.Replace("&", "&")
.Replace("%", "%")
.Replace("+", "+")
.Replace(""", "\"");
}
}
///
/// Cookie JSON 转换器。
///
public class CookiesJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(Cookies).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
if (reader.TokenType == JsonToken.String)
return new Cookies(reader.Value?.ToString());
return Cookies.FromToken(JToken.Load(reader));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Cookies cookies = value as Cookies;
writer.WriteValue(cookies?.GetCookieString());
}
}
}