Giraffe icon indicating copy to clipboard operation
Giraffe copied to clipboard

Feature request - request limitation

Open stijnmoreels opened this issue 5 years ago • 2 comments

Is your feature request related to a problem? Please describe. Provide basic request limitations, in the context of a more secure/safe API implementations out of the box.

Describe the solution you'd like Some extra middleware functions that limit requests based on header and body information, using the existing HTTP feature for the body size.

/// Functionality to limit HTTP requests based on header and body information.
[<AutoOpen>]
module Limit =
  /// Limits to only requests with one of the specified `Content-Type` headers,
  /// returning `406 NotAcceptable` when the request header doesn't exists in the set of specified types.
  let contentTypes contentTypes =
    fun next (ctx : HttpContext) ->
      match Option.ofObj ctx.Request.ContentType with
      | Some t when Seq.contains t contentTypes -> next ctx
      | Some _ -> RequestErrors.notAcceptable (text "request header 'Content-Type' doesn't had expected value") earlyReturn ctx
      | None -> RequestErrors.notAcceptable (text "expected to have request header 'Content-Type'") earlyReturn ctx

  /// Limits to only requests with a specific `Content-Type` header, 
  /// returning `406 NotAcceptable` when the request header value doesn't match the specified type.
  let contentType contentType = contentTypes [ contentType ]

  /// Limits request `Content-Length` header to a specified length, 
  /// returning `406 NotAcceptable` when no such header is present or the value exceeds the maximum specified length.
  let contentLength l =
    fun next (ctx : HttpContext) ->
      match Option.ofNullable (ctx.Request.GetTypedHeaders().ContentLength) with
      | Some v when v <= l ->  next ctx
      | Some _ -> RequestErrors.notAcceptable (text "request header 'Content-Length' is too large") earlyReturn ctx
      | None -> RequestErrors.notAcceptable (text "request doesn't contain 'Content-Length' header") earlyReturn ctx

  /// Limits the request body size to a specified length, returing `413 Payload Too Large` if the body size exceeds the specified maximum.
  let maxBodySize l =
    fun next (ctx : HttpContext) ->
      ctx.Features.Get<IHttpMaxRequestBodySizeFeature>().MaxRequestBodySize <- Nullable<_> l
      try next ctx
      with :? BadHttpRequestException as ex when ex.StatusCode = 413 ->
        (clearResponse >=> setStatusCode ex.StatusCode >=> text "request body too large") earlyReturn ctx

Is this too 'application-specific' to be added to Giraffe? I guess since we have a mustAccept core function, we could have some extra's as well. All in the context of having some boilerplate code to make the application more safer by default.

stijnmoreels avatar Dec 11 '19 12:12 stijnmoreels

Hi, thanks for this suggestion. There could be value in exposing such extra handlers if they are generic enough. What are the typical checks that you can think of that you would like to add handlers for? Just the 3 from above or did you have more in mind?

dustinmoris avatar Apr 12 '20 19:04 dustinmoris

Hi! They're could be more of course. These were just the ones I thought were the most valueable to add from an application security perspective.

stijnmoreels avatar Apr 13 '20 05:04 stijnmoreels