Files
KJD/Store.Framework/Models/Cookies.cs
T
2026-09-14 09:16:59 +08:00

229 lines
6.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Store.Framework.Models
{
/// <summary>
/// Cookie集合,支持普通 Cookie 字符串和 API 返回的 Cookie JSON。
/// </summary>
[JsonConverter(typeof(CookiesJsonConverter))]
public class Cookies : Dictionary<string, string>
{
private readonly string oldCookie;
public Cookies(string cookie)
{
oldCookie = cookie;
Load(cookie);
}
/// <summary>
/// Cookie字符串
/// </summary>
public string CookieString
{
get
{
return GetCookieString();
}
}
/// <summary>
/// 获取指定值
/// </summary>
/// <param name="key"></param>
/// <param name="defvalue">默认值</param>
/// <returns></returns>
public string GetValue(string key, string defvalue)
{
if (ContainsKey(key))
{
return this[key];
}
return defvalue;
}
/// <summary>
/// 添加或修改
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddOrUpdate(string key, string value)
{
if (!this.ContainsKey(key))
{
Add(key, value);
}
else
{
this[key] = value;
}
}
/// <summary>
/// 获取Cookies字符串
/// </summary>
/// <returns></returns>
public virtual string GetCookieString()
{
var list = this.Select(a => { return $"{a.Key}={a.Value}"; });
return string.Join(";", list);
}
/// <summary>
/// 转为浏览器 Cookie 字符串。
/// </summary>
public override string ToString()
{
var list = this.Select(a => { return $"{a.Key}={a.Value}"; });
return string.Join("; ", list);
}
/// <summary>
/// 隐式转换
/// </summary>
/// <param name="cookie"></param>
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());
}
/// <summary>
/// 拆分普通 Cookie 字符串。
/// </summary>
private void SplitCookie(string cookie)
{
Clear();
if (string.IsNullOrEmpty(cookie))
return;
Regex regCookie = new Regex("(?<key>.+?)=(?<value>.+?)(;|$)");
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(""", "\"");
}
}
/// <summary>
/// Cookie JSON 转换器。
/// </summary>
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());
}
}
}