File: SourceBuildStubs.cs
Web Access
Project: src\src\aspnetcore\src\Servers\HttpSys\src\Microsoft.AspNetCore.Server.HttpSys.csproj (Microsoft.AspNetCore.Server.HttpSys)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// This file contains stub implementations of all public API types for source-build on non-Windows platforms.
// These stubs allow reference assemblies to contain the correct API surface so that code referencing
// HttpSys types can compile on any platform, even though HttpSys only works on Windows at runtime.

using System.Collections;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Versioning;
using System.Security.AccessControl;

namespace Microsoft.AspNetCore.Server.HttpSys
{
    /// <summary>
    /// Specifies protocols for authentication.
    /// </summary>
    [Flags]
    public enum AuthenticationSchemes
    {
        /// <summary>
        /// No authentication is enabled. This should only be used when HttpSysOptions.Authentication.AllowAnonymous is enabled (see <see cref="AuthenticationManager.AllowAnonymous"/>).
        /// </summary>
        None = 0x0,

        /// <summary>
        /// Specifies basic authentication.
        /// </summary>
        Basic = 0x1,

        /// <summary>
        /// Specifies NTLM authentication.
        /// </summary>
        NTLM = 0x4,

        /// <summary>
        /// Negotiates with the client to determine the authentication scheme. If both client and server support Kerberos, it is used;
        /// otherwise, NTLM is used.
        /// </summary>
        Negotiate = 0x8,

        /// <summary>
        /// Specifies Kerberos authentication.
        /// </summary>
        Kerberos = 0x10
    }

    /// <summary>
    /// Describes the client certificate negotiation method for HTTPS connections.
    /// </summary>
    public enum ClientCertificateMethod
    {
        /// <summary>
        /// A client certificate will not be populated on the request.
        /// </summary>
        NoCertificate = 0,

        /// <summary>
        /// A client certificate will be populated if already present at the start of a request.
        /// </summary>
        AllowCertificate,

        /// <summary>
        /// The TLS session can be renegotiated to request a client certificate.
        /// </summary>
        AllowRenegotation
    }

    /// <summary>
    /// Enum declaring the allowed values for the verbosity level when http.sys reject requests due to throttling.
    /// </summary>
    public enum Http503VerbosityLevel : long
    {
        /// <summary>
        /// A 503 response is not sent; the connection is reset. This is the default HTTP Server API behavior.
        /// </summary>
        Basic = 0,

        /// <summary>
        /// The HTTP Server API sends a 503 response with a "Service Unavailable" reason phrase.
        /// </summary>
        Limited = 1,

        /// <summary>
        /// The HTTP Server API sends a 503 response with a detailed reason phrase.
        /// </summary>
        Full = 2
    }

    /// <summary>
    /// Defines the types of request processing timestamps exposed via the Http.Sys HTTP_REQUEST_TIMING_INFO extensibility point.
    /// </summary>
    /// <remarks>
    /// Use <see cref="IHttpSysRequestTimingFeature"/> to access these timestamps.
    /// </remarks>
    public enum HttpSysRequestTimingType
    {
        /// <summary>
        /// Time the connection started.
        /// </summary>
        ConnectionStart,

        /// <summary>
        /// Time the first HTTP byte is received.
        /// </summary>
        DataStart,

        /// <summary>
        /// Time TLS certificate loading starts.
        /// </summary>
        TlsCertificateLoadStart,

        /// <summary>
        /// Time TLS certificate loading ends.
        /// </summary>
        TlsCertificateLoadEnd,

        /// <summary>
        /// Time TLS leg one handshake starts.
        /// </summary>
        TlsHandshakeLeg1Start,

        /// <summary>
        /// Time TLS leg one handshake ends.
        /// </summary>
        TlsHandshakeLeg1End,

        /// <summary>
        /// Time TLS leg two handshake starts.
        /// </summary>
        TlsHandshakeLeg2Start,

        /// <summary>
        /// Time TLS leg two handshake ends.
        /// </summary>
        TlsHandshakeLeg2End,

        /// <summary>
        /// Time TLS attribute query starts.
        /// </summary>
        TlsAttributesQueryStart,

        /// <summary>
        /// Time TLS attribute query ends.
        /// </summary>
        TlsAttributesQueryEnd,

        /// <summary>
        /// Time TLS client cert query starts.
        /// </summary>
        TlsClientCertQueryStart,

        /// <summary>
        /// Time TLS client cert query ends.
        /// </summary>
        TlsClientCertQueryEnd,

        /// <summary>
        /// Time HTTP2 streaming starts.
        /// </summary>
        Http2StreamStart,

        /// <summary>
        /// Time HTTP2 header decoding starts.
        /// </summary>
        Http2HeaderDecodeStart,

        /// <summary>
        /// Time HTTP2 header decoding ends.
        /// </summary>
        Http2HeaderDecodeEnd,

        /// <summary>
        /// Time HTTP header parsing starts.
        /// </summary>
        RequestHeaderParseStart,

        /// <summary>
        /// Time HTTP header parsing ends.
        /// </summary>
        RequestHeaderParseEnd,

        /// <summary>
        /// Time Http.Sys starts to determine which request queue to route the request to.
        /// </summary>
        RequestRoutingStart,

        /// <summary>
        /// Time Http.Sys has determined which request queue to route the request to.
        /// </summary>
        RequestRoutingEnd,

        /// <summary>
        /// Time the request is queued for inspection.
        /// </summary>
        RequestQueuedForInspection,

        /// <summary>
        /// Time the request is delivered for inspection.
        /// </summary>
        RequestDeliveredForInspection,

        /// <summary>
        /// Time the request has finished being inspected.
        /// </summary>
        RequestReturnedAfterInspection,

        /// <summary>
        /// Time the request is queued for delegation.
        /// </summary>
        RequestQueuedForDelegation,

        /// <summary>
        /// Time the request is delivered for delegation.
        /// </summary>
        RequestDeliveredForDelegation,

        /// <summary>
        /// Time the request was delegated.
        /// </summary>
        RequestReturnedAfterDelegation,

        /// <summary>
        /// Time the request was queued to the final request queue for processing.
        /// </summary>
        RequestQueuedForIO,

        /// <summary>
        /// Time the request was delivered to the final request queue for processing.
        /// </summary>
        RequestDeliveredForIO,

        /// <summary>
        /// Time HTTP3 streaming starts.
        /// </summary>
        Http3StreamStart,

        /// <summary>
        /// Time HTTP3 header decoding starts.
        /// </summary>
        Http3HeaderDecodeStart,

        /// <summary>
        /// Time HTTP3 header decoding ends.
        /// </summary>
        Http3HeaderDecodeEnd,
    }

    /// <summary>
    /// Used to indicate if this server instance should create a new Http.Sys request queue
    /// or attach to an existing one.
    /// </summary>
    public enum RequestQueueMode
    {
        /// <summary>
        /// Create a new queue. This will fail if there's an existing queue with the same name.
        /// </summary>
        Create = 0,

        /// <summary>
        /// Attach to an existing queue with the name given. This will fail if the queue does not already exist.
        /// Most configuration options do not apply when attaching to an existing queue.
        /// </summary>
        Attach,

        /// <summary>
        /// Create a queue with the given name if it does not already exist, otherwise attach to the existing queue.
        /// Most configuration options do not apply when attaching to an existing queue.
        /// </summary>
        CreateOrAttach
    }

    /// <summary>
    /// This exposes the creation of delegation rules on request queues owned by the server.
    /// </summary>
    public interface IServerDelegationFeature
    {
        /// <summary>
        /// Create a delegation rule on request queue owned by the server.
        /// </summary>
        /// <param name="queueName">The name of the Http.Sys request queue.</param>
        /// <param name="urlPrefix">The URL of the Http.Sys Url Prefix.</param>
        /// <returns>
        /// Creates a <see cref="DelegationRule"/> that can used to delegate individual requests.
        /// </returns>
        DelegationRule CreateDelegationRule(string queueName, string urlPrefix);
    }

    /// <summary>
    /// Interface for delegating requests to other Http.Sys request queues.
    /// </summary>
    public interface IHttpSysRequestDelegationFeature
    {
        /// <summary>
        /// Indicates if the server can delegate this request to another HttpSys request queue.
        /// </summary>
        bool CanDelegate { get; }

        /// <summary>
        /// Attempt to delegate the request to another Http.Sys request queue. The request body
        /// must not be read nor the response started before this is invoked. Check <see cref="CanDelegate"/>
        /// before invoking.
        /// </summary>
        /// <param name="destination">The rule maintaining the handle to the destination queue.</param>
        void DelegateRequest(DelegationRule destination);
    }

    /// <summary>
    /// This exposes the Http.Sys HTTP_REQUEST_INFO extensibility point as opaque data for the caller to interperate.
    /// </summary>
    public interface IHttpSysRequestInfoFeature
    {
        /// <summary>
        /// A collection of the HTTP_REQUEST_INFO for the current request. The integer represents the identifying
        /// HTTP_REQUEST_INFO_TYPE enum value. The Memory is opaque bytes that need to be interperted in the format
        /// specified by the enum value.
        /// </summary>
        public IReadOnlyDictionary<int, ReadOnlyMemory<byte>> RequestInfo { get; }
    }

    /// <summary>
    /// Provides API to read HTTP_REQUEST_PROPERTY value from the HTTP.SYS request.
    /// </summary>
    public interface IHttpSysRequestPropertyFeature
    {
        /// <summary>
        /// Reads the TLS client hello from HTTP.SYS
        /// </summary>
        /// <param name="tlsClientHelloBytesDestination">Where the raw bytes of the TLS Client Hello message are written.</param>
        /// <param name="bytesReturned">
        /// Returns the number of bytes written to <paramref name="tlsClientHelloBytesDestination"/>.
        /// Or can return the size of the buffer needed if <paramref name="tlsClientHelloBytesDestination"/> wasn't large enough.
        /// </param>
        /// <returns>
        /// True, if fetching TLS client hello was successful, false if <paramref name="tlsClientHelloBytesDestination"/> size is not large enough.
        /// If unsuccessful for other reason throws an exception.
        /// </returns>
        bool TryGetTlsClientHello(Span<byte> tlsClientHelloBytesDestination, out int bytesReturned);
    }

    /// <summary>
    /// This exposes the Http.Sys HTTP_REQUEST_TIMING_INFO extensibility point which contains request processing timestamp data from Http.Sys.
    /// </summary>
    public interface IHttpSysRequestTimingFeature
    {
        /// <summary>
        /// Gets all Http.Sys timing timestamps
        /// </summary>
        ReadOnlySpan<long> Timestamps { get; }

        /// <summary>
        /// Gets the timestamp for the given timing.
        /// </summary>
        /// <param name="timestampType">The timestamp type to get.</param>
        /// <param name="timestamp">The value of the timestamp if set.</param>
        /// <returns>True if the given timing was set (i.e., non-zero).</returns>
        bool TryGetTimestamp(HttpSysRequestTimingType timestampType, out long timestamp);

        /// <summary>
        /// Gets the elapsed time between the two given timings.
        /// </summary>
        /// <param name="startingTimestampType">The timestamp type marking the beginning of the time period.</param>
        /// <param name="endingTimestampType">The timestamp type marking the end of the time period.</param>
        /// <param name="elapsed">A <see cref="TimeSpan"/> for the elapsed time between the starting and ending timestamps.</param>
        /// <returns>True if both given timings were set (i.e., non-zero).</returns>
        bool TryGetElapsedTime(HttpSysRequestTimingType startingTimestampType, HttpSysRequestTimingType endingTimestampType, out TimeSpan elapsed);
    }

    /// <summary>
    /// Constants for HttpSys.
    /// </summary>
    public static class HttpSysDefaults
    {
        /// <summary>
        /// The name of the authentication scheme used.
        /// </summary>
        public const string AuthenticationScheme = "Windows";
    }

    /// <summary>
    /// Exception thrown by HttpSys when an error occurs
    /// </summary>
    [SuppressMessage("Microsoft.Usage", "CA2237:MarkISerializableTypesWithSerializable")]
    public class HttpSysException : Win32Exception
    {
        internal HttpSysException()
            : base()
        {
        }

        internal HttpSysException(int errorCode)
            : base(errorCode)
        {
        }

        internal HttpSysException(int errorCode, string message)
            : base(errorCode, message)
        {
        }

        /// <inheritdoc />
        public override int ErrorCode
        {
            get
            {
                return NativeErrorCode;
            }
        }
    }

    /// <summary>
    /// Exposes the Http.Sys authentication configurations.
    /// </summary>
    public sealed class AuthenticationManager
    {
        internal AuthenticationManager()
        {
        }

        /// <summary>
        /// When attaching to an existing queue this setting must match the one used to create the queue.
        /// </summary>
        public AuthenticationSchemes Schemes { get; set; }

        /// <summary>
        /// Indicates if anonymous requests will be surfaced to the application or challenged by the server.
        /// The default value is true.
        /// </summary>
        public bool AllowAnonymous { get; set; } = true;

        /// <summary>
        /// If true the server should set HttpContext.User. If false the server will only provide an
        /// identity when explicitly requested by the AuthenticationScheme. The default is true.
        /// </summary>
        public bool AutomaticAuthentication { get; set; } = true;

        /// <summary>
        /// Sets the display name shown to users on login pages. The default is null.
        /// </summary>
        public string? AuthenticationDisplayName { get; set; }

        /// <summary>
        /// If true, the Kerberos authentication credentials are persisted per connection
        /// and re-used for subsequent anonymous requests on the same connection.
        /// Kerberos or Negotiate authentication must be enabled. The default is false.
        /// </summary>
        public bool EnableKerberosCredentialCaching { get; set; }

        /// <summary>
        /// If true, the server captures user credentials from the thread that starts the
        /// host and impersonates that user during Kerberos or Negotiate authentication.
        /// Kerberos or Negotiate authentication must be enabled. The default is false.
        /// </summary>
        public bool CaptureCredentials { get; set; }
    }

    /// <summary>
    /// Exposes the Http.Sys timeout configurations. These may also be configured in the registry.
    /// These settings do not apply when attaching to an existing queue.
    /// </summary>
    public sealed class TimeoutManager
    {
        internal TimeoutManager()
        {
        }

        /// <summary>
        /// The time, in seconds, allowed for the request entity body to arrive. The default timer is 2 minutes.
        /// </summary>
        public TimeSpan EntityBody { get; set; }

        /// <summary>
        /// The time, in seconds, allowed for the HTTP Server API to drain the entity body on a Keep-Alive connection.
        /// The default timer is 2 minutes.
        /// </summary>
        public TimeSpan DrainEntityBody { get; set; }

        /// <summary>
        /// The time, in seconds, allowed for the request to remain in the request queue before the application picks
        /// it up. The default timer is 2 minutes.
        /// </summary>
        public TimeSpan RequestQueue { get; set; }

        /// <summary>
        /// The time, in seconds, allowed for an idle connection. The default timer is 2 minutes.
        /// </summary>
        public TimeSpan IdleConnection { get; set; }

        /// <summary>
        /// The time, in seconds, allowed for the HTTP Server API to parse the request header. The default timer is
        /// 2 minutes.
        /// </summary>
        public TimeSpan HeaderWait { get; set; }

        /// <summary>
        /// The minimum send rate, in bytes-per-second, for the response. The default response send rate is 150
        /// bytes-per-second.
        /// </summary>
        public long MinSendBytesPerSecond { get; set; }
    }

    /// <summary>
    /// Rule that maintains a handle to the Request Queue and UrlPrefix to
    /// delegate to.
    /// </summary>
    public class DelegationRule : IDisposable
    {
        internal DelegationRule()
        {
        }

        /// <summary>
        /// The name of the Http.Sys request queue
        /// </summary>
        public string QueueName { get; } = string.Empty;

        /// <summary>
        /// The URL of the Http.Sys Url Prefix
        /// </summary>
        public string UrlPrefix { get; } = string.Empty;

        /// <inheritdoc />
        public void Dispose()
        {
        }
    }

    /// <summary>
    /// A set of URL parameters used to listen for incoming requests.
    /// </summary>
    public class UrlPrefix
    {
        private UrlPrefix()
        {
        }

        /// <summary>
        /// Gets a value that determines if the prefix's scheme is HTTPS.
        /// </summary>
        public bool IsHttps { get; }

        /// <summary>
        /// Gets the scheme used by the prefix.
        /// </summary>
        public string Scheme { get; } = string.Empty;

        /// <summary>
        /// Gets the host domain name used by the prefix.
        /// </summary>
        public string Host => throw new PlatformNotSupportedException();

        /// <summary>
        /// Gets a string representation of the port used by the prefix.
        /// </summary>
        public string Port { get; } = string.Empty;

        /// <summary>
        /// Gets an integer representation of the port used by the prefix.
        /// </summary>
        public int PortValue { get; }

        /// <summary>
        /// Gets the path component of the prefix.
        /// </summary>
        public string Path { get; } = string.Empty;

        /// <summary>
        /// Gets a string representation of the prefix
        /// </summary>
        public string FullPrefix { get; } = string.Empty;

        /// <summary>
        /// Creates a <see cref="UrlPrefix"/> from the given string.
        /// </summary>
        /// <param name="prefix">The string that the <see cref="UrlPrefix"/> will be created from.</param>
        /// <returns>A new <see cref="UrlPrefix"/>.</returns>
        public static UrlPrefix Create(string prefix) => throw new PlatformNotSupportedException();

        /// <summary>
        /// Creates a <see cref="UrlPrefix"/> from the given components.
        /// </summary>
        /// <param name="scheme">http or https.</param>
        /// <param name="host">The host name.</param>
        /// <param name="port">The port.</param>
        /// <param name="path">The path.</param>
        /// <returns>A new <see cref="UrlPrefix"/>.</returns>
        public static UrlPrefix Create(string scheme, string host, string port, string path) => throw new PlatformNotSupportedException();

        /// <summary>
        /// Creates a <see cref="UrlPrefix"/> from the given components.
        /// </summary>
        /// <param name="scheme">http or https.</param>
        /// <param name="host">The host name.</param>
        /// <param name="portValue">The port value.</param>
        /// <param name="path">The path.</param>
        /// <returns>A new <see cref="UrlPrefix"/>.</returns>
        public static UrlPrefix Create(string scheme, string host, int? portValue, string path) => throw new PlatformNotSupportedException();

        /// <inheritdoc />
        public override bool Equals(object? obj) => throw new PlatformNotSupportedException();

        /// <inheritdoc />
        public override int GetHashCode() => throw new PlatformNotSupportedException();

        /// <inheritdoc />
        public override string ToString() => throw new PlatformNotSupportedException();
    }

    /// <summary>
    /// A collection or URL prefixes
    /// </summary>
    public class UrlPrefixCollection : ICollection<UrlPrefix>
    {
        internal UrlPrefixCollection()
        {
        }

        /// <inheritdoc />
        public int Count => 0;

        /// <summary>
        /// Gets a value that determines if this collection is readOnly.
        /// </summary>
        public bool IsReadOnly => false;

        /// <summary>
        /// Creates a <see cref="UrlPrefix"/> from the given string, and adds it to this collection.
        /// </summary>
        /// <param name="prefix">The string representing the <see cref="UrlPrefix"/> to add to this collection.</param>
        public void Add(string prefix)
        {
        }

        /// <summary>
        /// Adds a <see cref="UrlPrefix"/> to this collection.
        /// </summary>
        /// <param name="item">The prefix to add to this collection.</param>
        public void Add(UrlPrefix item)
        {
        }

        /// <inheritdoc />
        public void Clear()
        {
        }

        /// <inheritdoc />
        public bool Contains(UrlPrefix item) => false;

        /// <inheritdoc />
        public void CopyTo(UrlPrefix[] array, int arrayIndex)
        {
        }

        /// <inheritdoc />
        public bool Remove(string prefix) => false;

        /// <inheritdoc />
        public bool Remove(UrlPrefix item) => false;

        /// <summary>
        /// Returns an enumerator that iterates through this collection.
        /// </summary>
        /// <returns>An enumerator for the collection.</returns>
        public IEnumerator<UrlPrefix> GetEnumerator() => ((IEnumerable<UrlPrefix>)Array.Empty<UrlPrefix>()).GetEnumerator();

        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    }

    /// <summary>
    /// Contains the options used by HttpSys.
    /// </summary>
    public class HttpSysOptions
    {
        /// <summary>
        /// Initializes a new <see cref="HttpSysOptions"/>.
        /// </summary>
        public HttpSysOptions()
        {
        }

        /// <summary>
        /// The name of the Http.Sys request queue.
        /// The default is <c>null</c> (Anonymous queue).
        /// </summary>
        public string? RequestQueueName { get; set; }

        /// <summary>
        /// This indicates whether the server is responsible for creating and configuring the request queue,
        /// or if it should attach to an existing queue.
        /// The default is <c>RequestQueueMode.Create</c>.
        /// </summary>
        public RequestQueueMode RequestQueueMode { get; set; }

        /// <summary>
        /// Indicates how client certificates should be populated. The default is to allow a certificate without renegotiation.
        /// </summary>
        public ClientCertificateMethod ClientCertificateMethod { get; set; } = ClientCertificateMethod.AllowCertificate;

        /// <summary>
        /// The maximum number of concurrent accepts.
        /// </summary>
        public int MaxAccepts { get; set; }

        /// <summary>
        /// Attempt kernel-mode caching for responses with eligible headers.
        /// The default is <c>true</c>.
        /// </summary>
        public bool EnableResponseCaching { get; set; } = true;

        /// <summary>
        /// The url prefixes to register with Http.Sys.
        /// </summary>
        public UrlPrefixCollection UrlPrefixes { get; } = new UrlPrefixCollection();

        /// <summary>
        /// Http.Sys authentication settings.
        /// </summary>
        public AuthenticationManager Authentication { get; } = new AuthenticationManager();

        /// <summary>
        /// Exposes the Http.Sys timeout configurations.
        /// </summary>
        public TimeoutManager Timeouts { get; } = new TimeoutManager();

        /// <summary>
        /// Gets or Sets if response body writes that fail due to client disconnects should throw exceptions or
        /// complete normally. The default is <c>false</c>.
        /// </summary>
        public bool ThrowWriteExceptions { get; set; }

        /// <summary>
        /// Enable buffering of response data in the Kernel. The default value is <c>false</c>.
        /// </summary>
        public bool EnableKernelResponseBuffering { get; set; }

        /// <summary>
        /// Gets or sets the maximum number of concurrent connections to accept. Set <c>-1</c> for infinite.
        /// Set to <c>null</c> to use the registry's machine-wide setting.
        /// The default value is <c>null</c>.
        /// </summary>
        public long? MaxConnections { get; set; }

        /// <summary>
        /// Gets or sets the maximum number of requests that will be queued up in Http.Sys.
        /// The default is 1000.
        /// </summary>
        public long RequestQueueLimit { get; set; } = 1000;

        /// <summary>
        /// Gets or sets the security descriptor for the request queue.
        /// </summary>
        public GenericSecurityDescriptor? RequestQueueSecurityDescriptor { get; set; }

        /// <summary>
        /// Gets or sets the maximum allowed size of any request body in bytes.
        /// When set to null, the maximum request body size is unlimited.
        /// The default is set to 30,000,000 bytes, which is approximately 28.6MB.
        /// </summary>
        public long? MaxRequestBodySize { get; set; } = 30000000;

        /// <summary>
        /// Control whether synchronous input/output is allowed for the HttpContext.Request.Body and HttpContext.Response.Body.
        /// The default is <c>false</c>.
        /// </summary>
        public bool AllowSynchronousIO { get; set; }

        /// <summary>
        /// Gets or sets a value that controls how http.sys reacts when rejecting requests due to throttling conditions.
        /// </summary>
        public Http503VerbosityLevel Http503Verbosity { get; set; }

        /// <summary>
        /// Inline request processing instead of dispatching to the threadpool.
        /// </summary>
        public bool UnsafePreferInlineScheduling { get; set; }

        /// <summary>
        /// Configures request headers to use Latin1 encoding.
        /// </summary>
        public bool UseLatin1RequestHeaders { get; set; }
    }
}

namespace Microsoft.AspNetCore.Hosting
{
    using Microsoft.AspNetCore.Server.HttpSys;

    /// <summary>
    /// Provides extensions method to use Http.sys as the server for the web host.
    /// </summary>
    public static class WebHostBuilderHttpSysExtensions
    {
        /// <summary>
        /// Specify Http.sys as the server to be used by the web host.
        /// </summary>
        /// <param name="hostBuilder">
        /// The Microsoft.AspNetCore.Hosting.IWebHostBuilder to configure.
        /// </param>
        /// <returns>
        /// A reference to the <see cref="IWebHostBuilder" /> parameter object.
        /// </returns>
        [SupportedOSPlatform("windows")]
        public static IWebHostBuilder UseHttpSys(this IWebHostBuilder hostBuilder) => hostBuilder;

        /// <summary>
        /// Specify Http.sys as the server to be used by the web host.
        /// </summary>
        /// <param name="hostBuilder">
        /// The Microsoft.AspNetCore.Hosting.IWebHostBuilder to configure.
        /// </param>
        /// <param name="options">
        /// A callback to configure Http.sys options.
        /// </param>
        /// <returns>
        /// A reference to the <see cref="IWebHostBuilder" /> parameter object.
        /// </returns>
        [SupportedOSPlatform("windows")]
        public static IWebHostBuilder UseHttpSys(this IWebHostBuilder hostBuilder, Action<HttpSysOptions> options) => hostBuilder;
    }
}