Hello community, here is the log from the commit of package ghc-wai-extra for openSUSE:Factory checked in at 2020-10-23 15:15:28 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ghc-wai-extra (Old) and /work/SRC/openSUSE:Factory/.ghc-wai-extra.new.3463 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-wai-extra" Fri Oct 23 15:15:28 2020 rev:4 rq:842776 version:3.1.1 Changes: -------- --- /work/SRC/openSUSE:Factory/ghc-wai-extra/ghc-wai-extra.changes 2020-09-30 19:53:49.440754276 +0200 +++ /work/SRC/openSUSE:Factory/.ghc-wai-extra.new.3463/ghc-wai-extra.changes 2020-10-23 15:15:33.734169407 +0200 @@ -1,0 +2,8 @@ +Tue Oct 6 08:55:59 UTC 2020 - psim...@suse.com + +- Update wai-extra to version 3.1.1. + ## 3.1.1 + + * 'Network.Wai.Middleware.RequestSizeLimit': Add a new middleware to reject request bodies above a certain size. [#818](https://github.com/yesodweb/wai/pull/818/files) + +------------------------------------------------------------------- Old: ---- wai-extra-3.1.0.tar.gz New: ---- wai-extra-3.1.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ghc-wai-extra.spec ++++++ --- /var/tmp/diff_new_pack.JoSplP/_old 2020-10-23 15:15:36.450170717 +0200 +++ /var/tmp/diff_new_pack.JoSplP/_new 2020-10-23 15:15:36.454170719 +0200 @@ -19,7 +19,7 @@ %global pkg_name wai-extra %bcond_with tests Name: ghc-%{pkg_name} -Version: 3.1.0 +Version: 3.1.1 Release: 0 Summary: Provides some basic WAI handlers and middleware License: MIT ++++++ wai-extra-3.1.0.tar.gz -> wai-extra-3.1.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wai-extra-3.1.0/ChangeLog.md new/wai-extra-3.1.1/ChangeLog.md --- old/wai-extra-3.1.0/ChangeLog.md 2020-09-21 12:43:49.000000000 +0200 +++ new/wai-extra-3.1.1/ChangeLog.md 2020-10-05 20:20:57.000000000 +0200 @@ -1,5 +1,9 @@ # Changelog for wai-extra +## 3.1.1 + +* 'Network.Wai.Middleware.RequestSizeLimit': Add a new middleware to reject request bodies above a certain size. [#818](https://github.com/yesodweb/wai/pull/818/files) + ## 3.1.0 * `Network.Wai.Test`: Add support for source locations to assertion primitives [#817](https://github.com/yesodweb/wai/pull/817) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wai-extra-3.1.0/Network/Wai/Middleware/RequestSizeLimit/Internal.hs new/wai-extra-3.1.1/Network/Wai/Middleware/RequestSizeLimit/Internal.hs --- old/wai-extra-3.1.0/Network/Wai/Middleware/RequestSizeLimit/Internal.hs 1970-01-01 01:00:00.000000000 +0100 +++ new/wai-extra-3.1.1/Network/Wai/Middleware/RequestSizeLimit/Internal.hs 2020-10-05 20:20:57.000000000 +0200 @@ -0,0 +1,57 @@ +-- | Internal constructors and helper functions. Note that no guarantees are given for stability of these interfaces. +module Network.Wai.Middleware.RequestSizeLimit.Internal + ( RequestSizeLimitSettings(..) + , setMaxLengthForRequest + , setOnLengthExceeded + ) where + +import Network.Wai +import Data.Word (Word64) + +-- | Settings to configure 'requestSizeLimitMiddleware'. +-- +-- This type (but not the constructor, or record fields) is exported from "Network.Wai.Middleware.RequestSizeLimit". +-- Since the constructor isn't exported, create a default value with 'defaultRequestSizeLimitSettings' first, +-- then set the values using 'setMaxLengthForRequest' and 'setOnLengthExceeded' (See the examples below). +-- +-- If you need to access the constructor directly, it's exported from "Network.Wai.Middleware.RequestSizeLimit.Internal". +-- +-- ==== __Examples__ +-- +-- ===== Conditionally setting the limit based on the request +-- > {-# LANGUAGE OverloadedStrings #-} +-- > import Network.Wai +-- > import Network.Wai.Middleware.RequestSizeLimit +-- > +-- > let megabyte = 1024 * 1024 +-- > let sizeForReq req = if pathInfo req == ["upload", "image"] then pure $ Just $ megabyte * 20 else pure $ Just $ megabyte * 2 +-- > let finalSettings = setMaxLengthForRequest sizeForReq defaultRequestSizeLimitSettings +-- +-- ===== JSON response +-- > {-# LANGUAGE OverloadedStrings #-} +-- > import Network.Wai +-- > import Network.Wai.Middleware.RequestSizeLimit +-- > import Network.HTTP.Types.Status (requestEntityTooLarge413) +-- > import Data.Aeson +-- > import Data.Text (Text) +-- > +-- > let jsonResponse = \_maxLen _app _req sendResponse -> sendResponse $ responseLBS requestEntityTooLarge413 [("Content-Type", "application/json")] (encode $ object ["error" .= ("request size too large" :: Text)]) +-- > let finalSettings = setOnLengthExceeded jsonResponse defaultRequestSizeLimitSettings +-- +-- @since 3.1.1 +data RequestSizeLimitSettings = RequestSizeLimitSettings + { maxLengthForRequest :: Request -> IO (Maybe Word64) -- ^ Function to determine the maximum request size in bytes for the request. Return 'Nothing' for no limit. Since 3.1.1 + , onLengthExceeded :: Word64 -> Middleware -- ^ Callback function when maximum length is exceeded. The 'Word64' argument is the limit computed by 'maxLengthForRequest'. Since 3.1.1 + } + +-- | Function to determine the maximum request size in bytes for the request. Return 'Nothing' for no limit. +-- +-- @since 3.1.1 +setMaxLengthForRequest :: (Request -> IO (Maybe Word64)) -> RequestSizeLimitSettings -> RequestSizeLimitSettings +setMaxLengthForRequest fn settings = settings { maxLengthForRequest = fn } + +-- | Callback function when maximum length is exceeded. The 'Word64' argument is the limit computed by 'setMaxLengthForRequest'. +-- +-- @since 3.1.1 +setOnLengthExceeded :: (Word64 -> Middleware) -> RequestSizeLimitSettings -> RequestSizeLimitSettings +setOnLengthExceeded fn settings = settings { onLengthExceeded = fn } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wai-extra-3.1.0/Network/Wai/Middleware/RequestSizeLimit.hs new/wai-extra-3.1.1/Network/Wai/Middleware/RequestSizeLimit.hs --- old/wai-extra-3.1.0/Network/Wai/Middleware/RequestSizeLimit.hs 1970-01-01 01:00:00.000000000 +0100 +++ new/wai-extra-3.1.1/Network/Wai/Middleware/RequestSizeLimit.hs 2020-10-05 20:20:57.000000000 +0200 @@ -0,0 +1,73 @@ +-- | The functions in this module allow you to limit the total size of incoming request bodies. +-- +-- Limiting incoming request body size helps protect your server against denial-of-service (DOS) attacks, +-- in which an attacker sends huge bodies to your server. +module Network.Wai.Middleware.RequestSizeLimit + ( + -- * Middleware + requestSizeLimitMiddleware + -- * Constructing 'RequestSizeLimitSettings' + , defaultRequestSizeLimitSettings + -- * 'RequestSizeLimitSettings' and accessors + , RequestSizeLimitSettings + , setMaxLengthForRequest + , setOnLengthExceeded + ) where + +import Network.Wai +import Network.Wai.Request +import qualified Data.ByteString.Lazy as BSL +import Data.Word (Word64) +import Network.HTTP.Types.Status (requestEntityTooLarge413) +import qualified Data.ByteString.Lazy.Char8 as LS8 +import Control.Exception (try, catch) +import Data.Monoid ((<>)) +import Network.Wai.Middleware.RequestSizeLimit.Internal (RequestSizeLimitSettings(..), setMaxLengthForRequest, setOnLengthExceeded) + +-- | Create a 'RequestSizeLimitSettings' with these settings: +-- +-- * 2MB size limit for all requests +-- * When the limit is exceeded, return a plain text response describing the error, with a 413 status code. +-- +-- @since 3.1.1 +defaultRequestSizeLimitSettings :: RequestSizeLimitSettings +defaultRequestSizeLimitSettings = RequestSizeLimitSettings + { maxLengthForRequest = \_req -> pure $ Just $ 2 * 1024 * 1024 + , onLengthExceeded = \maxLen _app req sendResponse -> sendResponse (tooLargeResponse maxLen (requestBodyLength req)) + } + +-- | Middleware to limit request bodies to a certain size. +-- +-- This uses 'requestSizeCheck' under the hood; see that function for details. +-- +-- @since 3.1.1 +requestSizeLimitMiddleware :: RequestSizeLimitSettings -> Middleware +requestSizeLimitMiddleware settings app req sendResponse = do + maybeMaxLen <- (maxLengthForRequest settings) req + + case maybeMaxLen of + Nothing -> app req sendResponse + Just maxLen -> do + eitherSizeExceptionOrNewReq <- try (requestSizeCheck maxLen req) + case eitherSizeExceptionOrNewReq of + -- In the case of a known-length request, RequestSizeException will be thrown immediately + Left (RequestSizeException _maxLen) -> handleLengthExceeded maxLen + -- In the case of a chunked request (unknown length), RequestSizeException will be thrown during the processing of a body + Right newReq -> app newReq sendResponse `catch` \(RequestSizeException _maxLen) -> handleLengthExceeded maxLen + + where + handleLengthExceeded maxLen = (onLengthExceeded settings) maxLen app req sendResponse + +tooLargeResponse :: Word64 -> RequestBodyLength -> Response +tooLargeResponse maxLen bodyLen = responseLBS + requestEntityTooLarge413 + [("Content-Type", "text/plain")] + (BSL.concat + [ "Request body too large to be processed. The maximum size is " + , (LS8.pack (show maxLen)) + , " bytes; your request body was " + , case bodyLen of + KnownLength knownLen -> (LS8.pack (show knownLen)) <> " bytes." + ChunkedBody -> "split into chunks, whose total size is unknown, but exceeded the limit." + , " . If you're the developer of this site, you can configure the maximum length with `requestSizeLimitMiddleware`." + ]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/wai-extra-3.1.0/wai-extra.cabal new/wai-extra-3.1.1/wai-extra.cabal --- old/wai-extra-3.1.0/wai-extra.cabal 2020-09-21 12:43:49.000000000 +0200 +++ new/wai-extra-3.1.1/wai-extra.cabal 2020-10-05 20:20:57.000000000 +0200 @@ -1,5 +1,5 @@ Name: wai-extra -Version: 3.1.0 +Version: 3.1.1 Synopsis: Provides some basic WAI handlers and middleware. description: Provides basic WAI handler and middleware functionality: @@ -157,6 +157,8 @@ Network.Wai.Test.Internal Network.Wai.EventSource Network.Wai.EventSource.EventStream + Network.Wai.Middleware.RequestSizeLimit + Network.Wai.Middleware.RequestSizeLimit.Internal other-modules: Network.Wai.Middleware.RequestLogger.Internal default-language: Haskell2010 ghc-options: -Wall @@ -206,6 +208,7 @@ , time , case-insensitive , http2 + , aeson ghc-options: -Wall default-language: Haskell2010