trim HttpHeaders
石头 编写于 2024-06-22 08:55:23
X
namespace NewLife.Web;

/// <summary>资源定位。无限制解析Url地址</summary>
public class UriInfo
{
    /// <summary>协议</summary>
    public String? Scheme { get; set; }

    /// <summary>协议</summary>
    public String Host { get; set; } = null!;

    /// <summary>协议</summary>
    public Int32 Port { get; set; }

    /// <summary>协议</summary>
    public String? PathAndQuery { get; set; }

    /// <summary>实例化</summary>
    /// <param name="value"></param>
    public UriInfo(String value) => Parse(value);

    /// <summary>主机与端口。省略默认端口</summary>
    public String Authority
    {
        get
        {
            if (Port == 0) return Host;

            if (Scheme.EqualIgnoreCase("http", "ws"))
                return Port == 80 ? Host : $"{Host}:{Port}";
            else if (Scheme.EqualIgnoreCase("https", "wss"))
                return Port == 443 ? Host : $"{Host}:{Port}";

            return $"{Host}:{Port}";
        }
    }

    /// <summary>解析Url字符串</summary>
    /// <param name="value"></param>
    public void Parse(String value)
    {
        if (value.IsNullOrWhiteSpace()) return;

        // 先处理头尾,再处理中间的主机和端口
        var p = value.IndexOf("://");
        if (p >= 0)
        {
            Scheme = value.Substring(0, p);
            p += 3;
        }
        else
            p = 0;

        var p2 = value.IndexOf('/', p);
        if (p2 > 0)
        {
            PathAndQuery = value.Substring(p2);
            value = value.Substring(p, p2 - p - 1);
        }
        else
            value = value.Substring(p);

        // 拆分主机和端口,注意IPv6地址
        p2 = value.LastIndexOf(':');
        if (p2 > 0)
        {
            Host = value.Substring(0, p2);
            Port = value.Substring(p2 + 1).ToInt();
        }
        else
        {
            Host = value;
        }
    }

    /// <summary>已重载。</summary>
    /// <returns></returns>
    public override String ToString() => $"{Scheme}://{Authority}{PathAndQuery}";
}