File: System\Net\Http\Headers\AltSvcHeaderValue.cs
Web Access
Project: src\src\libraries\System.Net.Http\src\System.Net.Http.csproj (System.Net.Http)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Globalization;
using System.Text;
 
namespace System.Net.Http.Headers
{
    /// <remarks>
    /// Kept internal for now:
    /// A user depending on this strongly-typed header is dubious, as Alt-Svc values can also be received via the ALTSVC frame in HTTP/2.
    /// This type does not conform to the typical API for header values, and should be updated if ever made public.
    /// </remarks>
    internal sealed class AltSvcHeaderValue
    {
        public static AltSvcHeaderValue Clear { get; } = new AltSvcHeaderValue("clear", host: null, port: 0, maxAge: TimeSpan.Zero, persist: false);
 
        public AltSvcHeaderValue(string alpnProtocolName, string? host, int port, TimeSpan maxAge, bool persist)
        {
            AlpnProtocolName = alpnProtocolName;
            Host = host;
            Port = port;
            MaxAge = maxAge;
            Persist = persist;
        }
 
        public string AlpnProtocolName { get; }
 
        /// <summary>
        /// The name of the host serving this alternate service.
        /// If null, the alternate service is on the same host this header was received from.
        /// </summary>
        public string? Host { get; }
 
        public int Port { get; }
 
        /// <summary>
        /// The time span this alternate service is valid for.
        /// If not specified by the header, defaults to 24 hours.
        /// </summary>
        /// <remarks>TODO: if made public, should this be defaulted or nullable?</remarks>
        public TimeSpan MaxAge { get; }
 
        /// <summary>
        /// If true, the service should persist across network changes.
        /// Otherwise, the service should be invalidated if a network change is detected.
        /// </summary>
        /// <remarks>TODO: if made public, this should be made internal as Persist is left open-ended and can be non-boolean in the future.</remarks>
        public bool Persist { get; }
 
        public override string ToString()
        {
            var sb = new ValueStringBuilder(stackalloc char[256]);
 
            sb.Append(AlpnProtocolName);
            sb.Append("=\"");
            if (Host != null)
            {
                sb.Append(Host);
            }
            sb.Append(':');
            sb.AppendSpanFormattable((uint)Port);
            sb.Append('"');
 
            if (MaxAge != TimeSpan.FromTicks(AltSvcHeaderParser.DefaultMaxAgeTicks))
            {
                sb.Append("; ma=");
                sb.AppendSpanFormattable(MaxAge.Ticks / TimeSpan.TicksPerSecond, provider: CultureInfo.InvariantCulture);
            }
 
            if (Persist)
            {
                sb.Append("; persist=1");
            }
 
            return sb.ToString();
        }
    }
}