/// <summary> /// Limits the bandwith used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="getBytesPerSecond"> /// A delegate to retrieve the maximum number of bytes per second to be transferred. /// Allows you to supply different values at runtime. Use 0 or a negative number to specify infinite bandwidth. /// </param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxBytesToWrite</exception> public static MidFunc MaxBandwidthGlobal(Func<int> getBytesPerSecond, string loggerName = null) { getBytesPerSecond.MustNotNull("getMaxBytesToWrite"); loggerName = string.IsNullOrWhiteSpace(loggerName) ? "LimitsMiddleware.MaxBandwidthGlobal" : loggerName; var logger = LogProvider.GetLogger(loggerName); var requestTokenBucket = new FixedTokenBucket(getBytesPerSecond); var responseTokenBucket = new FixedTokenBucket(getBytesPerSecond); logger.Debug("Configure streams to be globally limited to."); return next => async env => { using (requestTokenBucket.RegisterRequest()) using (responseTokenBucket.RegisterRequest()) { var context = new OwinContext(env); Stream requestBodyStream = context.Request.Body ?? Stream.Null; Stream responseBodyStream = context.Response.Body; context.Request.Body = new ThrottledStream(requestBodyStream, requestTokenBucket); context.Response.Body = new ThrottledStream(responseBodyStream, responseTokenBucket); //TODO consider SendFile interception await next(env).ConfigureAwait(false); } }; }
/// <summary> /// Limits the bandwith used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="getBytesPerSecond">A delegate to retrieve the maximum number of bytes per second to be transferred. /// Allows you to supply different values at runtime. Use 0 or a negative number to specify infinite bandwidth.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxBytesToWrite</exception> public static MidFunc MaxBandwidthGlobal(Func <int> getBytesPerSecond) { getBytesPerSecond.MustNotNull("getMaxBytesToWrite"); var logger = LogProvider.GetLogger("LimitsMiddleware.MaxBandwidthGlobal"); var requestTokenBucket = new FixedTokenBucket(getBytesPerSecond); var responseTokenBucket = new FixedTokenBucket(getBytesPerSecond); logger.Debug("Configure streams to be globally limited."); return (next => async env => { using (requestTokenBucket.RegisterRequest()) using (responseTokenBucket.RegisterRequest()) { var context = new OwinContext(env); Stream requestBodyStream = context.Request.Body ?? Stream.Null; Stream responseBodyStream = context.Response.Body; context.Request.Body = new ThrottledStream(requestBodyStream, requestTokenBucket); context.Response.Body = new ThrottledStream(responseBodyStream, responseTokenBucket); //TODO consider SendFile interception await next(env).ConfigureAwait(false); } }); }
/// <summary> /// Limits the bandwith used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="getMaxBytesPerSecond"> /// A delegate to retrieve the maximum number of bytes per second to be transferred. /// Allows you to supply different values at runtime. Use 0 or a negative number to specify infinite bandwidth. /// </param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxBytesPerSecond</exception> public static MidFunc MaxBandwidthPerRequest(Func <RequestContext, int> getMaxBytesPerSecond) { getMaxBytesPerSecond.MustNotNull("getMaxBytesPerSecond"); return (next => async env => { var context = new OwinContext(env); Stream requestBodyStream = context.Request.Body ?? Stream.Null; Stream responseBodyStream = context.Response.Body; var limitsRequestContext = new RequestContext(context.Request); var requestTokenBucket = new FixedTokenBucket( () => getMaxBytesPerSecond(limitsRequestContext)); var responseTokenBucket = new FixedTokenBucket( () => getMaxBytesPerSecond(limitsRequestContext)); using (requestTokenBucket.RegisterRequest()) using (responseTokenBucket.RegisterRequest()) { context.Request.Body = new ThrottledStream(requestBodyStream, requestTokenBucket); context.Response.Body = new ThrottledStream(responseBodyStream, responseTokenBucket); //TODO consider SendFile interception await next(env).ConfigureAwait(false); } }); }
/// <summary> /// Adds a minimum delay before sending the response. /// </summary> /// <param name="getMinDelay">A delegate to return the min response delay.</param> /// <returns>The OWIN builder instance.</returns> /// <exception cref="System.ArgumentNullException">getMinDelay</exception> public static MidFunc MinResponseDelay(Func<RequestContext, TimeSpan> getMinDelay) { getMinDelay.MustNotNull("getMinDelay"); var logger = LogProvider.GetLogger("LimitsMiddleware.MinResponseDelay"); return next => async env => { var context = new OwinContext(env); var limitsRequestContext = new RequestContext(context.Request); var delay = getMinDelay(limitsRequestContext); if (delay <= TimeSpan.Zero) { await next(env); return; } logger.Debug("Delaying response by {0}".FormatWith(delay)); await Task.Delay(delay, context.Request.CallCancelled); await next(env); }; }
/// <summary> /// Limits the length of the URL. /// </summary> /// <param name="getMaxUrlLength">A delegate to get the maximum URL length.</param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxUrlLength</exception> public static MidFunc MaxUrlLength(Func <RequestContext, int> getMaxUrlLength, string loggerName = null) { getMaxUrlLength.MustNotNull("getMaxUrlLength"); loggerName = string.IsNullOrWhiteSpace(loggerName) ? "LimitsMiddleware.MaxUrlLength" : loggerName; var logger = LogProvider.GetLogger(loggerName); return (next => env => { var context = new OwinContext(env); int maxUrlLength = getMaxUrlLength(new RequestContext(context.Request)); string unescapedUri = Uri.UnescapeDataString(context.Request.Uri.AbsoluteUri); logger.Debug("Checking request url length."); if (unescapedUri.Length > maxUrlLength) { logger.Info( "Url \"{0}\"(Length: {2}) exceeds allowed length of {1}. Request rejected.".FormatWith( unescapedUri, maxUrlLength, unescapedUri.Length)); context.Response.StatusCode = 414; context.Response.ReasonPhrase = "Request-URI Too Large"; context.Response.Write(context.Response.ReasonPhrase); return Task.FromResult(0); } logger.Debug("Check passed. Request forwarded."); return next(env); }); }
/// <summary> /// Timeouts the connection if there hasn't been an read activity on the request body stream or any /// write activity on the response body stream. /// </summary> /// <param name="builder">The IAppBuilder instance.</param> /// <param name="getTimeout">A delegate to retrieve the timeout timespan. Allows you /// to supply different values at runtime.</param> /// <returns>The IAppBuilder instance.</returns> public static IAppBuilder ConnectionTimeout(this IAppBuilder builder, Func<TimeSpan> getTimeout) { builder.MustNotNull("builder"); getTimeout.MustNotNull("getTimeout"); return ConnectionTimeout(builder, new ConnectionTimeoutOptions(getTimeout)); }
/// <summary> /// Limits the bandwith used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="getMaxBytesPerSecond"> /// A delegate to retrieve the maximum number of bytes per second to be transferred. /// Allows you to supply different values at runtime. Use 0 or a negative number to specify infinite bandwidth. /// </param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxBytesPerSecond</exception> public static MidFunc MaxBandwidthPerRequest(Func<RequestContext, int> getMaxBytesPerSecond) { getMaxBytesPerSecond.MustNotNull("getMaxBytesPerSecond"); return next => async env => { var context = new OwinContext(env); Stream requestBodyStream = context.Request.Body ?? Stream.Null; Stream responseBodyStream = context.Response.Body; var limitsRequestContext = new RequestContext(context.Request); var requestTokenBucket = new FixedTokenBucket( () => getMaxBytesPerSecond(limitsRequestContext)); var responseTokenBucket = new FixedTokenBucket( () => getMaxBytesPerSecond(limitsRequestContext)); using (requestTokenBucket.RegisterRequest()) using (responseTokenBucket.RegisterRequest()) { context.Request.Body = new ThrottledStream(requestBodyStream, requestTokenBucket); context.Response.Body = new ThrottledStream(responseBodyStream, responseTokenBucket); //TODO consider SendFile interception await next(env).ConfigureAwait(false); } }; }
/// <summary> /// Adds a minimum delay before sending the response. /// </summary> /// <param name="getMinDelay">A delegate to return the min response delay.</param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>The OWIN builder instance.</returns> /// <exception cref="System.ArgumentNullException">getMinDelay</exception> public static MidFunc MinResponseDelay(Func <RequestContext, TimeSpan> getMinDelay, string loggerName = null) { getMinDelay.MustNotNull("getMinDelay"); loggerName = string.IsNullOrWhiteSpace(loggerName) ? "LimitsMiddleware.MinResponseDelay" : loggerName; var logger = LogProvider.GetLogger(loggerName); return (next => async env => { var context = new OwinContext(env); var limitsRequestContext = new RequestContext(context.Request); var delay = getMinDelay(limitsRequestContext); if (delay <= TimeSpan.Zero) { await next(env); return; } logger.Debug("Delaying response by {0}".FormatWith(delay)); await Task.Delay(delay, context.Request.CallCancelled); await next(env); }); }
/// <summary> /// Timeouts the connection if there hasn't been an read activity on the request body stream or any /// write activity on the response body stream. /// </summary> /// <param name="getTimeout"> /// A delegate to retrieve the timeout timespan. Allows you /// to supply different values at runtime. /// </param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getTimeout</exception> public static MidFunc ConnectionTimeout( Func <RequestContext, TimeSpan> getTimeout, string loggerName = null) { getTimeout.MustNotNull("getTimeout"); loggerName = string.IsNullOrWhiteSpace(loggerName) ? "LimitsMiddleware.ConnectionTimeout" : loggerName; var logger = LogProvider.GetLogger(loggerName); return (next => env => { var context = new OwinContext(env); var limitsRequestContext = new RequestContext(context.Request); var requestBodyStream = context.Request.Body ?? Stream.Null; var responseBodyStream = context.Response.Body; var connectionTimeout = getTimeout(limitsRequestContext); context.Request.Body = new TimeoutStream(requestBodyStream, connectionTimeout, logger); context.Response.Body = new TimeoutStream(responseBodyStream, connectionTimeout, logger); return next(env); }); }
/// <summary> /// Timeouts the connection if there hasn't been an read activity on the request body stream or any /// write activity on the response body stream. /// </summary> /// <param name="getTimeout"> /// A delegate to retrieve the timeout timespan. Allows you /// to supply different values at runtime. /// </param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getTimeout</exception> public static MidFunc ConnectionTimeout( Func<RequestContext, TimeSpan> getTimeout, string loggerName = null) { getTimeout.MustNotNull("getTimeout"); loggerName = string.IsNullOrWhiteSpace(loggerName) ? "LimitsMiddleware.ConnectionTimeout" : loggerName; var logger = LogProvider.GetLogger(loggerName); return next => env => { var context = new OwinContext(env); var limitsRequestContext = new RequestContext(context.Request); var requestBodyStream = context.Request.Body ?? Stream.Null; var responseBodyStream = context.Response.Body; var connectionTimeout = getTimeout(limitsRequestContext); context.Request.Body = new TimeoutStream(requestBodyStream, connectionTimeout, logger); context.Response.Body = new TimeoutStream(responseBodyStream, connectionTimeout, logger); return next(env); }; }
/// <summary> /// Limits the length of the URL. /// </summary> /// <param name="getMaxUrlLength">A delegate to get the maximum URL length.</param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxUrlLength</exception> public static MidFunc MaxUrlLength(Func<RequestContext, int> getMaxUrlLength, string loggerName = null) { getMaxUrlLength.MustNotNull("getMaxUrlLength"); loggerName = string.IsNullOrWhiteSpace(loggerName) ? "LimitsMiddleware.MaxUrlLength" : loggerName; var logger = LogProvider.GetLogger(loggerName); return next => env => { var context = new OwinContext(env); int maxUrlLength = getMaxUrlLength(new RequestContext(context.Request)); string unescapedUri = Uri.UnescapeDataString(context.Request.Uri.AbsoluteUri); logger.Debug("Checking request url length."); if (unescapedUri.Length > maxUrlLength) { logger.Info( "Url \"{0}\"(Length: {2}) exceeds allowed length of {1}. Request rejected.".FormatWith( unescapedUri, maxUrlLength, unescapedUri.Length)); context.Response.StatusCode = 414; context.Response.ReasonPhrase = "Request-URI Too Large"; context.Response.Write(context.Response.ReasonPhrase); return Task.FromResult(0); } logger.Debug("Check passed. Request forwarded."); return next(env); }; }
/// <summary> /// Limits the length of the URL. /// </summary> /// <param name="app">The IAppBuilder instance.</param> /// <param name="getMaxUrlLength">A delegate to get the maximum URL length.</param> /// <returns>The IAppBuilder instance.</returns> public static IAppBuilder MaxUrlLength(this IAppBuilder app, Func <RequestContext, int> getMaxUrlLength) { app.MustNotNull("app"); getMaxUrlLength.MustNotNull("getMaxUrlLength"); app.Use(Limits.MaxUrlLength(getMaxUrlLength)); return(app); }
/// <summary> /// Limits the number of concurrent requests that can be handled used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="getMaxConcurrentRequests"> /// A delegate to retrieve the maximum number of concurrent requests. Allows you /// to supply different values at runtime. Use 0 or a negative number to specify unlimited number of concurrent /// requests. /// </param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxConcurrentRequests</exception> public static MidFunc MaxConcurrentRequests( Func <int> getMaxConcurrentRequests, string loggerName = null) { getMaxConcurrentRequests.MustNotNull("getMaxConcurrentRequests"); return(MaxConcurrentRequests(_ => getMaxConcurrentRequests(), loggerName)); }
/// <summary> /// Limits the length of the URL. /// </summary> /// <param name="app">The IAppBuilder instance.</param> /// <param name="getMaxUrlLength">A delegate to get the maximum URL length.</param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>The IAppBuilder instance.</returns> public static IAppBuilder MaxUrlLength(this IAppBuilder app, Func <int> getMaxUrlLength, string loggerName = null) { app.MustNotNull("app"); getMaxUrlLength.MustNotNull("getMaxUrlLength"); app.Use(Limits.MaxUrlLength(getMaxUrlLength, loggerName)); return(app); }
/// <summary> /// Limits the bandwith used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="getMaxBytesPerSecond">A delegate to retrieve the maximum number of bytes per second to be transferred. /// Allows you to supply different values at runtime. Use 0 or a negative number to specify infinite bandwidth.</param> /// <returns>An OWIN middleware delegate.</returns> /// <param name="app">The IAppBuilder instance.</param> /// <exception cref="System.ArgumentNullException">app</exception> /// <exception cref="System.ArgumentNullException">getMaxBytesPerSecond</exception> public static IAppBuilder MaxBandwidthPerRequest(this IAppBuilder app, Func <RequestContext, int> getMaxBytesPerSecond) { app.MustNotNull("app"); getMaxBytesPerSecond.MustNotNull("getMaxBytesPerSecond"); app.Use(Limits.MaxBandwidthPerRequest(getMaxBytesPerSecond)); return(app); }
/// <summary> /// Limits the number of concurrent requests that can be handled used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="getMaxConcurrentRequests"> /// A delegate to retrieve the maximum number of concurrent requests. Allows you /// to supply different values at runtime. Use 0 or a negative number to specify unlimited number of concurrent /// requests. /// </param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxConcurrentRequests</exception> public static MidFunc MaxConcurrentRequests( Func<int> getMaxConcurrentRequests, string loggerName = null) { getMaxConcurrentRequests.MustNotNull("getMaxConcurrentRequests"); return MaxConcurrentRequests(_ => getMaxConcurrentRequests(), loggerName); }
/// <summary> /// Limits the bandwith used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="getMaxBytesPerSecond">A delegate to retrieve the maximum number of bytes per second to be transferred. /// Allows you to supply different values at runtime. Use 0 or a negative number to specify infinite bandwidth.</param> /// <returns>An OWIN middleware delegate.</returns> /// <param name="app">The IAppBuilder instance.</param> /// <exception cref="System.ArgumentNullException">app</exception> /// <exception cref="System.ArgumentNullException">getMaxBytesPerSecond</exception> public static IAppBuilder MaxBandwidthPerRequest(this IAppBuilder app, Func<RequestContext, int> getMaxBytesPerSecond) { app.MustNotNull("app"); getMaxBytesPerSecond.MustNotNull("getMaxBytesPerSecond"); app.Use(Limits.MaxBandwidthPerRequest(getMaxBytesPerSecond)); return app; }
/// <summary> /// Limits the length of the URL. /// </summary> /// <param name="app">The IAppBuilder instance.</param> /// <param name="getMaxUrlLength">A delegate to get the maximum URL length.</param> /// <returns>The IAppBuilder instance.</returns> public static IAppBuilder MaxUrlLength(this IAppBuilder app, Func<RequestContext, int> getMaxUrlLength) { app.MustNotNull("app"); getMaxUrlLength.MustNotNull("getMaxUrlLength"); app.Use(Limits.MaxUrlLength(getMaxUrlLength)); return app; }
/// <summary> /// Limits the length of the URL. /// </summary> /// <param name="app">The IAppBuilder instance.</param> /// <param name="getMaxUrlLength">A delegate to get the maximum URL length.</param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>The IAppBuilder instance.</returns> public static IAppBuilder MaxUrlLength(this IAppBuilder app, Func<int> getMaxUrlLength, string loggerName = null) { app.MustNotNull("app"); getMaxUrlLength.MustNotNull("getMaxUrlLength"); app.Use(Limits.MaxUrlLength(getMaxUrlLength, loggerName)); return app; }
/// <summary> /// Limits the number of concurrent requests that can be handled used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="app">The IAppBuilder instance.</param> /// <param name="getMaxConcurrentRequests"> /// A delegate to retrieve the maximum number of concurrent requests. Allows you /// to supply different values at runtime. Use 0 or a negative number to specify unlimited number of concurrent /// requests. /// </param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>The IAppBuilder instance.</returns> public static IAppBuilder MaxConcurrentRequests(this IAppBuilder app, Func <int> getMaxConcurrentRequests, string loggerName = null) { app.MustNotNull("app"); getMaxConcurrentRequests.MustNotNull("getMaxConcurrentRequests"); app.Use(Limits.MaxConcurrentRequests(getMaxConcurrentRequests, loggerName)); return(app); }
/// <summary> /// Timeouts the connection if there hasn't been an read activity on the request body stream or any /// write activity on the response body stream. /// </summary> /// <param name="app">The IAppBuilder instance.</param> /// <param name="getTimeout">A delegate to retrieve the timeout timespan. Allows you /// to supply different values at runtime.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getTimeout</exception> public static IAppBuilder ConnectionTimeout(this IAppBuilder app, Func <RequestContext, TimeSpan> getTimeout) { app.MustNotNull("app"); getTimeout.MustNotNull("getTimeout"); app.Use(Limits.ConnectionTimeout(getTimeout)); return(app); }
/// <summary> /// Limits the number of concurrent requests that can be handled used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="app">The IAppBuilder instance.</param> /// <param name="getMaxConcurrentRequests">A delegate to retrieve the maximum number of concurrent requests. Allows you /// to supply different values at runtime. Use 0 or a negative number to specify unlimited number of concurrent requests.</param> /// <returns>The IAppBuilder instance.</returns> public static IAppBuilder MaxConcurrentRequests(this IAppBuilder app, Func <RequestContext, int> getMaxConcurrentRequests) { app.MustNotNull("app"); getMaxConcurrentRequests.MustNotNull("getMaxConcurrentRequests"); app.Use(Limits.MaxConcurrentRequests(getMaxConcurrentRequests)); return(app); }
/// <summary> /// Limits the length of the query string. /// </summary> /// <param name="app">The IAppBuilder instance.</param> /// <param name="getMaxQueryStringLength">A delegate to get the maximum query string length.</param> /// <returns>The IAppBuilder instance.</returns> public static IAppBuilder MaxQueryStringLength(this IAppBuilder app, Func <int> getMaxQueryStringLength) { app.MustNotNull("app"); getMaxQueryStringLength.MustNotNull("getMaxQueryStringLength"); app.Use(Limits.MaxQueryStringLength(getMaxQueryStringLength)); return(app); }
/// <summary> /// Limits the length of the query string. /// </summary> /// <param name="app">The IAppBuilder instance.</param> /// <param name="getMaxQueryStringLength">A delegate to get the maximum query string length.</param> /// <returns>The IAppBuilder instance.</returns> public static IAppBuilder MaxQueryStringLength(this IAppBuilder app, Func<int> getMaxQueryStringLength) { app.MustNotNull("app"); getMaxQueryStringLength.MustNotNull("getMaxQueryStringLength"); app.Use(Limits.MaxQueryStringLength(getMaxQueryStringLength)); return app; }
/// <summary> /// Limits the number of concurrent requests that can be handled used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="app">The IAppBuilder instance.</param> /// <param name="getMaxConcurrentRequests">A delegate to retrieve the maximum number of concurrent requests. Allows you /// to supply different values at runtime. Use 0 or a negative number to specify unlimited number of concurrent requests.</param> /// <returns>The IAppBuilder instance.</returns> public static IAppBuilder MaxConcurrentRequests(this IAppBuilder app, Func<RequestContext, int> getMaxConcurrentRequests) { app.MustNotNull("app"); getMaxConcurrentRequests.MustNotNull("getMaxConcurrentRequests"); app.Use(Limits.MaxConcurrentRequests(getMaxConcurrentRequests)); return app; }
/// <summary> /// Timeouts the connection if there hasn't been an read activity on the request body stream or any /// write activity on the response body stream. /// </summary> /// <param name="app">The IAppBuilder instance.</param> /// <param name="getTimeout">A delegate to retrieve the timeout timespan. Allows you /// to supply different values at runtime.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getTimeout</exception> public static IAppBuilder ConnectionTimeout(this IAppBuilder app, Func<RequestContext, TimeSpan> getTimeout) { app.MustNotNull("app"); getTimeout.MustNotNull("getTimeout"); app.Use(Limits.ConnectionTimeout(getTimeout)); return app; }
/// <summary> /// Timeouts the connection if there hasn't been an read activity on the request body stream or any /// write activity on the response body stream. /// </summary> /// <param name="app">The IAppBuilder instance.</param> /// <param name="getTimeout"> /// A delegate to retrieve the timeout timespan. Allows you /// to supply different values at runtime. /// </param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>The IAppBuilder instance.</returns> public static IAppBuilder ConnectionTimeout(this IAppBuilder app, Func<TimeSpan> getTimeout, string loggerName = null) { app.MustNotNull("app"); getTimeout.MustNotNull("getTimeout"); app.Use(Limits.ConnectionTimeout(getTimeout, loggerName)); return app; }
/// <summary> /// Limits the length of the query string. /// </summary> /// <param name="app">The IAppBuilder instance.</param> /// <param name="getMaxQueryStringLength">A delegate to get the maximum query string length.</param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>The IAppBuilder instance.</returns> public static IAppBuilder MaxQueryStringLength(this IAppBuilder app, Func<RequestContext, int> getMaxQueryStringLength, string loggerName = null) { app.MustNotNull("app"); getMaxQueryStringLength.MustNotNull("getMaxQueryStringLength"); app.Use(Limits.MaxQueryStringLength(getMaxQueryStringLength, loggerName)); return app; }
/// <summary> /// Limits the number of concurrent requests that can be handled used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="getMaxConcurrentRequests"> /// A delegate to retrieve the maximum number of concurrent requests. Allows you /// to supply different values at runtime. Use 0 or a negative number to specify unlimited number of concurrent /// requests. /// </param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxConcurrentRequests</exception> public static MidFunc MaxConcurrentRequests( Func <RequestContext, int> getMaxConcurrentRequests, string loggerName = null) { getMaxConcurrentRequests.MustNotNull("getMaxConcurrentRequests"); loggerName = string.IsNullOrWhiteSpace(loggerName) ? "LimitsMiddleware.MaxConcurrentRequests" : loggerName; var logger = LogProvider.GetLogger(loggerName); var concurrentRequestCounter = 0; return (next => async env => { var owinRequest = new OwinRequest(env); var limitsRequestContext = new RequestContext(owinRequest); int maxConcurrentRequests = getMaxConcurrentRequests(limitsRequestContext); if (maxConcurrentRequests <= 0) { maxConcurrentRequests = int.MaxValue; } try { int concurrentRequests = Interlocked.Increment(ref concurrentRequestCounter); logger.Debug("Concurrent request {0}/{1}.".FormatWith(concurrentRequests, maxConcurrentRequests)); if (concurrentRequests > maxConcurrentRequests) { logger.Info("Limit ({0}). Request rejected." .FormatWith(maxConcurrentRequests, concurrentRequests)); var response = new OwinContext(env).Response; response.StatusCode = 503; response.ReasonPhrase = "Service Unavailable"; response.Write(response.ReasonPhrase); return; } await next(env); } finally { int concurrentRequests = Interlocked.Decrement(ref concurrentRequestCounter); logger.Debug("Concurrent request {0}/{1}.".FormatWith(concurrentRequests, maxConcurrentRequests)); } }); }
/// <summary> /// Limits the number of concurrent requests that can be handled used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="getMaxConcurrentRequests"> /// A delegate to retrieve the maximum number of concurrent requests. Allows you /// to supply different values at runtime. Use 0 or a negative number to specify unlimited number of concurrent /// requests. /// </param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxConcurrentRequests</exception> public static MidFunc MaxConcurrentRequests( Func<RequestContext, int> getMaxConcurrentRequests, string loggerName = null) { getMaxConcurrentRequests.MustNotNull("getMaxConcurrentRequests"); loggerName = string.IsNullOrWhiteSpace(loggerName) ? "LimitsMiddleware.MaxConcurrentRequests" : loggerName; var logger = LogProvider.GetLogger(loggerName); var concurrentRequestCounter = 0; return next => async env => { var owinRequest = new OwinRequest(env); var limitsRequestContext = new RequestContext(owinRequest); int maxConcurrentRequests = getMaxConcurrentRequests(limitsRequestContext); if (maxConcurrentRequests <= 0) { maxConcurrentRequests = int.MaxValue; } try { int concurrentRequests = Interlocked.Increment(ref concurrentRequestCounter); logger.Debug("Concurrent request {0}/{1}.".FormatWith(concurrentRequests, maxConcurrentRequests)); if (concurrentRequests > maxConcurrentRequests) { logger.Info("Limit ({0}). Request rejected." .FormatWith(maxConcurrentRequests, concurrentRequests)); var response = new OwinContext(env).Response; response.StatusCode = 503; response.ReasonPhrase = "Service Unavailable"; response.Write(response.ReasonPhrase); return; } await next(env); } finally { int concurrentRequests = Interlocked.Decrement(ref concurrentRequestCounter); logger.Debug("Concurrent request {0}/{1}.".FormatWith(concurrentRequests, maxConcurrentRequests)); } }; }
/// <summary> /// Limits the length of the query string. /// </summary> /// <param name="getMaxQueryStringLength">A delegate to get the maximum query string length.</param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxQueryStringLength</exception> public static MidFunc MaxQueryStringLength( Func <RequestContext, int> getMaxQueryStringLength, string loggerName = null) { getMaxQueryStringLength.MustNotNull("getMaxQueryStringLength"); loggerName = string.IsNullOrWhiteSpace(loggerName) ? "LimitsMiddleware.MaxQueryStringLength" : loggerName; var logger = LogProvider.GetLogger(loggerName); return (next => async env => { var context = new OwinContext(env); var requestContext = new RequestContext(context.Request); QueryString queryString = context.Request.QueryString; if (queryString.HasValue) { int maxQueryStringLength = getMaxQueryStringLength(requestContext); string unescapedQueryString = Uri.UnescapeDataString(queryString.Value); logger.Debug("Querystring of request with an unescaped length of {0}".FormatWith(unescapedQueryString.Length)); if (unescapedQueryString.Length > maxQueryStringLength) { logger.Info("Querystring (Length {0}) too long (allowed {1}). Request rejected.".FormatWith( unescapedQueryString.Length, maxQueryStringLength)); context.Response.StatusCode = 414; context.Response.ReasonPhrase = "Request-URI Too Large"; context.Response.Write(context.Response.ReasonPhrase); return; } } else { logger.Debug("No querystring."); } await next(env); }); }
/// <summary> /// Timeouts the connection if there hasn't been an read activity on the request body stream or any /// write activity on the response body stream. /// </summary> /// <param name="getTimeout">A delegate to retrieve the timeout timespan. Allows you /// to supply different values at runtime.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getTimeout</exception> public static MidFunc ConnectionTimeout(Func <RequestContext, TimeSpan> getTimeout) { getTimeout.MustNotNull("getTimeout"); var logger = LogProvider.GetLogger("LimitsMiddleware.ConnectionTimeout"); return (next => env => { var context = new OwinContext(env); var limitsRequestContext = new RequestContext(context.Request); Stream requestBodyStream = context.Request.Body ?? Stream.Null; Stream responseBodyStream = context.Response.Body; TimeSpan connectionTimeout = getTimeout(limitsRequestContext); context.Request.Body = new TimeoutStream(requestBodyStream, connectionTimeout); context.Response.Body = new TimeoutStream(responseBodyStream, connectionTimeout); return next(env); }); }
/// <summary> /// Timeouts the connection if there hasn't been an read activity on the request body stream or any /// write activity on the response body stream. /// </summary> /// <param name="getTimeout">A delegate to retrieve the timeout timespan. Allows you /// to supply different values at runtime.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getTimeout</exception> public static MidFunc ConnectionTimeout(Func<RequestContext, TimeSpan> getTimeout) { getTimeout.MustNotNull("getTimeout"); var logger = LogProvider.GetLogger("LimitsMiddleware.ConnectionTimeout"); return next => env => { var context = new OwinContext(env); var limitsRequestContext = new RequestContext(context.Request); Stream requestBodyStream = context.Request.Body ?? Stream.Null; Stream responseBodyStream = context.Response.Body; TimeSpan connectionTimeout = getTimeout(limitsRequestContext); context.Request.Body = new TimeoutStream(requestBodyStream, connectionTimeout); context.Response.Body = new TimeoutStream(responseBodyStream, connectionTimeout); return next(env); }; }
/// <summary> /// Limits the length of the query string. /// </summary> /// <param name="getMaxQueryStringLength">A delegate to get the maximum query string length.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxQueryStringLength</exception> public static MidFunc MaxQueryStringLength(Func<RequestContext, int> getMaxQueryStringLength) { getMaxQueryStringLength.MustNotNull("getMaxQueryStringLength"); var logger = LogProvider.GetLogger("LimitsMiddleware.MaxQueryStringLength"); return next => async env => { var context = new OwinContext(env); var requestContext = new RequestContext(context.Request); QueryString queryString = context.Request.QueryString; if (queryString.HasValue) { int maxQueryStringLength = getMaxQueryStringLength(requestContext); string unescapedQueryString = Uri.UnescapeDataString(queryString.Value); logger.Debug("Querystring of request with an unescaped length of {0}".FormatWith(unescapedQueryString.Length)); if (unescapedQueryString.Length > maxQueryStringLength) { logger.Info("Querystring (Length {0}) too long (allowed {1}). Request rejected.".FormatWith( unescapedQueryString.Length, maxQueryStringLength)); context.Response.StatusCode = 414; context.Response.ReasonPhrase = "Request-URI Too Large"; context.Response.Write(context.Response.ReasonPhrase); return; } } else { logger.Debug("No querystring."); } await next(env); }; }
/// <summary> /// Initializes a new instance of the <see cref="ConnectionTimeoutOptions"/> class. /// </summary> /// <param name="getTimeout">A delegate to retrieve the timeout timespan. Allows you /// to supply different values at runtime.</param> public ConnectionTimeoutOptions(Func<TimeSpan> getTimeout) { getTimeout.MustNotNull("getTimeout"); _getTimeout = getTimeout; }
/// <summary> /// Adds a minimum delay before sending the response. /// </summary> /// <param name="getMinDelay">A delegate to return the min response delay.</param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>The OWIN builder instance.</returns> /// <exception cref="System.ArgumentNullException">getMinDelay</exception> public static MidFunc MinResponseDelay(Func <RequestContext, int> getMinDelay, string loggerName = null) { getMinDelay.MustNotNull("getMinDelay"); return(MinResponseDelay(context => TimeSpan.FromMilliseconds(getMinDelay(context)), loggerName)); }
/// <summary> /// Adds a minimum delay before sending the response. /// </summary> /// <param name="getMinDelay">A delegate to return the min response delay.</param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>The OWIN builder instance.</returns> /// <exception cref="System.ArgumentNullException">getMinDelay</exception> public static MidFunc MinResponseDelay(Func <TimeSpan> getMinDelay, string loggerName = null) { getMinDelay.MustNotNull("getMinDelay"); return(MinResponseDelay(_ => getMinDelay(), loggerName)); }
/// <summary> /// Limits the bandwith used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="getMaxBytesPerSecond"> /// A delegate to retrieve the maximum number of bytes per second to be transferred. /// Allows you to supply different values at runtime. Use 0 or a negative number to specify infinite bandwidth. /// </param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxBytesPerSecond</exception> public static MidFunc MaxBandwidthPerRequest(Func<int> getMaxBytesPerSecond) { getMaxBytesPerSecond.MustNotNull("getMaxBytesPerSecond"); return MaxBandwidthPerRequest(_ => getMaxBytesPerSecond()); }
/// <summary> /// Limits the number of concurrent requests that can be handled used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="getMaxConcurrentRequests">A delegate to retrieve the maximum number of concurrent requests. Allows you /// to supply different values at runtime. Use 0 or a negative number to specify unlimited number of concurrent requests.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxConcurrentRequests</exception> public static MidFunc MaxConcurrentRequests(Func<int> getMaxConcurrentRequests) { getMaxConcurrentRequests.MustNotNull("getMaxConcurrentRequests"); return MaxConcurrentRequests(_ => getMaxConcurrentRequests()); }
/// <summary> /// Limits the length of the request content. /// </summary> /// <param name="builder">The OWIN builder instance.</param> /// <param name="getMaxContentLength">A delegate to get the maximum content length.</param> /// <returns>The OWIN builder instance.</returns> /// <exception cref="System.ArgumentNullException">builder</exception> /// <exception cref="System.ArgumentNullException">getMaxContentLength</exception> public static BuildFunc MaxRequestContentLength(this BuildFunc builder, Func<int> getMaxContentLength) { builder.MustNotNull("builder"); getMaxContentLength.MustNotNull("getMaxContentLength"); return MaxRequestContentLength(builder, new MaxRequestContentLengthOptions(getMaxContentLength)); }
/// <summary> /// Initializes a new instance of the <see cref="MaxQueryStringLengthOptions"/> class. /// </summary> /// <param name="getMaxQueryStringLength">A delegate to get the maximum query string length.</param> public MaxQueryStringLengthOptions(Func<int> getMaxQueryStringLength) { getMaxQueryStringLength.MustNotNull("getMaxQueryStringLength"); _getMaxQueryStringLength = getMaxQueryStringLength; }
/// <summary> /// Initializes a new instance of the <see cref="MaxRequestContentLengthOptions"/> class. /// </summary> /// <param name="getMaxContentLength">A delegate to get the maximum content length.</param> public MaxRequestContentLengthOptions(Func<int> getMaxContentLength) { getMaxContentLength.MustNotNull("getMaxContentLength"); _getMaxContentLength = getMaxContentLength; }
/// <summary> /// Timeouts the connection if there hasn't been an read activity on the request body stream or any /// write activity on the response body stream. /// </summary> /// <param name="getTimeout">A delegate to retrieve the timeout timespan. Allows you /// to supply different values at runtime.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getTimeout</exception> public static MidFunc ConnectionTimeout(Func<TimeSpan> getTimeout) { getTimeout.MustNotNull("getTimeout"); return ConnectionTimeout(new ConnectionTimeoutOptions(getTimeout)); }
/// <summary> /// Limits the number of concurrent requests that can be handled used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="builder">The IAppBuilder instance.</param> /// <param name="getMaxConcurrentRequests">A delegate to retrieve the maximum number of concurrent requests. Allows you /// to supply different values at runtime. Use 0 or a negative number to specify unlimited number of concurrent requests.</param> /// <returns>The IAppBuilder instance.</returns> public static IAppBuilder MaxConcurrentRequests(this IAppBuilder builder, Func<int> getMaxConcurrentRequests) { builder.MustNotNull("builder"); getMaxConcurrentRequests.MustNotNull("getMaxConcurrentRequests"); return MaxConcurrentRequests(builder, new MaxConcurrentRequestOptions(getMaxConcurrentRequests)); }
/// <summary> /// Limits the length of the URL. /// </summary> /// <param name="builder">The IAppBuilder instance.</param> /// <param name="getMaxUrlLength">A delegate to get the maximum URL length.</param> /// <returns>The IAppBuilder instance.</returns> public static IAppBuilder MaxUrlLength(this IAppBuilder builder, Func<int> getMaxUrlLength) { builder.MustNotNull("builder"); getMaxUrlLength.MustNotNull("getMaxUrlLength"); return MaxUrlLength(builder, new MaxUrlLengthOptions(getMaxUrlLength)); }
/// <summary> /// Limits the bandwith used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="getMaxBytesPerSecond"> /// A delegate to retrieve the maximum number of bytes per second to be transferred. /// Allows you to supply different values at runtime. Use 0 or a negative number to specify infinite bandwidth. /// </param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxBytesPerSecond</exception> public static MidFunc MaxBandwidthPerRequest(Func <int> getMaxBytesPerSecond) { getMaxBytesPerSecond.MustNotNull("getMaxBytesPerSecond"); return(MaxBandwidthPerRequest(_ => getMaxBytesPerSecond())); }
/// <summary> /// Limits the number of concurrent requests that can be handled used by the subsequent stages in the owin pipeline. /// </summary> /// <param name="getMaxConcurrentRequests">A delegate to retrieve the maximum number of concurrent requests. Allows you /// to supply different values at runtime. Use 0 or a negative number to specify unlimited number of concurrent requests.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxConcurrentRequests</exception> public static MidFunc MaxConcurrentRequests(Func <int> getMaxConcurrentRequests) { getMaxConcurrentRequests.MustNotNull("getMaxConcurrentRequests"); return(MaxConcurrentRequests(_ => getMaxConcurrentRequests())); }
/// <summary> /// Timeouts the connection if there hasn't been an read activity on the request body stream or any /// write activity on the response body stream. /// </summary> /// <param name="getTimeout">A delegate to retrieve the timeout timespan. Allows you /// to supply different values at runtime.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getTimeout</exception> public static MidFunc ConnectionTimeout(Func <TimeSpan> getTimeout) { getTimeout.MustNotNull("getTimeout"); return(ConnectionTimeout(_ => getTimeout())); }
/// <summary> /// Timeouts the connection if there hasn't been an read activity on the request body stream or any /// write activity on the response body stream. /// </summary> /// <param name="getTimeout"> /// A delegate to retrieve the timeout timespan. Allows you /// to supply different values at runtime. /// </param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getTimeout</exception> public static MidFunc ConnectionTimeout(Func <TimeSpan> getTimeout, string loggerName = null) { getTimeout.MustNotNull("getTimeout"); return(ConnectionTimeout(_ => getTimeout(), loggerName)); }
/// <summary> /// Adds a minimum delay before sending the response. /// </summary> /// <param name="getMinDelay">A delegate to return the min response delay.</param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>The OWIN builder instance.</returns> /// <exception cref="System.ArgumentNullException">getMinDelay</exception> public static MidFunc MinResponseDelay(Func<RequestContext, int> getMinDelay, string loggerName = null) { getMinDelay.MustNotNull("getMinDelay"); return MinResponseDelay(context => TimeSpan.FromMilliseconds(getMinDelay(context)), loggerName); }
/// <summary> /// Limits the length of the URL. /// </summary> /// <param name="getMaxUrlLength">A delegate to get the maximum URL length.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxUrlLength</exception> public static MidFunc MaxUrlLength(Func<int> getMaxUrlLength) { getMaxUrlLength.MustNotNull("getMaxUrlLength"); return MaxUrlLength(new MaxUrlLengthOptions(getMaxUrlLength)); }
/// <summary> /// Adds a minimum delay before sending the response. /// </summary> /// <param name="getMinDelay">A delegate to return the min response delay.</param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>The OWIN builder instance.</returns> /// <exception cref="System.ArgumentNullException">getMinDelay</exception> public static MidFunc MinResponseDelay(Func<TimeSpan> getMinDelay, string loggerName = null) { getMinDelay.MustNotNull("getMinDelay"); return MinResponseDelay(_ => getMinDelay(), loggerName); }
/// <summary> /// Limits the length of the request content. /// </summary> /// <param name="getMaxContentLength">A delegate to get the maximum content length.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxContentLength</exception> public static MidFunc MaxRequestContentLength(Func <int> getMaxContentLength) { getMaxContentLength.MustNotNull("getMaxContentLength"); return(MaxRequestContentLength(_ => getMaxContentLength())); }
/// <summary> /// Limits the length of the request content. /// </summary> /// <param name="getMaxContentLength">A delegate to get the maximum content length.</param> /// <param name="loggerName">(Optional) The name of the logger log messages are written to.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxContentLength</exception> public static MidFunc MaxRequestContentLength(Func <int> getMaxContentLength, string loggerName = null) { getMaxContentLength.MustNotNull("getMaxContentLength"); return(MaxRequestContentLength(_ => getMaxContentLength(), loggerName)); }
/// <summary> /// Limits the length of the request content. /// </summary> /// <param name="getMaxContentLength">A delegate to get the maximum content length.</param> /// <returns>An OWIN middleware delegate.</returns> /// <exception cref="System.ArgumentNullException">getMaxContentLength</exception> public static MidFunc MaxRequestContentLength(Func <RequestContext, int> getMaxContentLength) { getMaxContentLength.MustNotNull("getMaxContentLength"); var logger = LogProvider.GetLogger("LimitsMiddleware.MaxRequestContentLength"); return (next => async env => { var context = new OwinContext(env); IOwinRequest request = context.Request; string requestMethod = request.Method.Trim().ToUpper(); if (requestMethod == "GET" || requestMethod == "HEAD") { logger.Debug("GET or HEAD request without checking forwarded."); await next(env); return; } int maxContentLength = getMaxContentLength(new RequestContext(request)); logger.Debug("Max valid content length is {0}.".FormatWith(maxContentLength)); if (!IsChunkedRequest(request)) { logger.Debug("Not a chunked request. Checking content length header."); string contentLengthHeaderValue = request.Headers.Get("Content-Length"); if (contentLengthHeaderValue == null) { logger.Info("No content length header provided. Request rejected."); SetResponseStatusCodeAndReasonPhrase(context, 411, "Length Required"); return; } int contentLength; if (!int.TryParse(contentLengthHeaderValue, out contentLength)) { logger.Info("Invalid content length header value. Value: {0}".FormatWith(contentLengthHeaderValue)); SetResponseStatusCodeAndReasonPhrase(context, 400, "Bad Request"); return; } if (contentLength > maxContentLength) { logger.Info("Content length of {0} exceeds maximum of {1}. Request rejected.".FormatWith( contentLength, maxContentLength)); SetResponseStatusCodeAndReasonPhrase(context, 413, "Request Entity Too Large"); return; } logger.Debug("Content length header check passed."); } else { logger.Debug("Chunked request. Content length header not checked."); } request.Body = new ContentLengthLimitingStream(request.Body, maxContentLength); logger.Debug("Request body stream configured with length limiting stream of {0}.".FormatWith(maxContentLength)); try { logger.Debug("Request forwarded."); await next(env); logger.Debug("Processing finished."); } catch (ContentLengthExceededException) { logger.Info("Content length of {0} exceeded. Request canceled and rejected.".FormatWith(maxContentLength)); SetResponseStatusCodeAndReasonPhrase(context, 413, "Request Entity Too Large"); } }); }
/// <summary> /// Adds a minimum delay before sending the response. /// </summary> /// <param name="getMinDelay">A delegate to return the min response delay.</param> /// <returns>The OWIN builder instance.</returns> /// <exception cref="System.ArgumentNullException">getMinDelay</exception> public static MidFunc MinResponseDelay(Func <TimeSpan> getMinDelay) { getMinDelay.MustNotNull("getMinDelay"); return(MinResponseDelay(_ => getMinDelay())); }