happstack-server 7.6.1 → 7.7.0
raw patch · 5 files changed
+44/−15 lines, 5 filesdep ~base64-bytestringPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base64-bytestring
API changes (from Hackage documentation)
+ Happstack.Server.Cookie: SameSiteLax :: SameSite
+ Happstack.Server.Cookie: SameSiteNoValue :: SameSite
+ Happstack.Server.Cookie: SameSiteNone :: SameSite
+ Happstack.Server.Cookie: SameSiteStrict :: SameSite
+ Happstack.Server.Cookie: [sameSite] :: Cookie -> SameSite
+ Happstack.Server.Cookie: data SameSite
+ Happstack.Server.Internal.Cookie: SameSiteLax :: SameSite
+ Happstack.Server.Internal.Cookie: SameSiteNoValue :: SameSite
+ Happstack.Server.Internal.Cookie: SameSiteNone :: SameSite
+ Happstack.Server.Internal.Cookie: SameSiteStrict :: SameSite
+ Happstack.Server.Internal.Cookie: [sameSite] :: Cookie -> SameSite
+ Happstack.Server.Internal.Cookie: data SameSite
+ Happstack.Server.Internal.Cookie: instance Data.Data.Data Happstack.Server.Internal.Cookie.SameSite
+ Happstack.Server.Internal.Cookie: instance GHC.Classes.Eq Happstack.Server.Internal.Cookie.SameSite
+ Happstack.Server.Internal.Cookie: instance GHC.Classes.Ord Happstack.Server.Internal.Cookie.SameSite
+ Happstack.Server.Internal.Cookie: instance GHC.Read.Read Happstack.Server.Internal.Cookie.SameSite
+ Happstack.Server.Internal.Cookie: instance GHC.Show.Show Happstack.Server.Internal.Cookie.SameSite
- Happstack.Server.Cookie: Cookie :: String -> String -> String -> String -> String -> Bool -> Bool -> Cookie
+ Happstack.Server.Cookie: Cookie :: String -> String -> String -> String -> String -> Bool -> Bool -> SameSite -> Cookie
- Happstack.Server.Internal.Cookie: Cookie :: String -> String -> String -> String -> String -> Bool -> Bool -> Cookie
+ Happstack.Server.Internal.Cookie: Cookie :: String -> String -> String -> String -> String -> Bool -> Bool -> SameSite -> Cookie
Files
- README.md +1/−1
- happstack-server.cabal +2/−2
- src/Happstack/Server/Cookie.hs +2/−1
- src/Happstack/Server/Internal/Cookie.hs +33/−5
- tests/Happstack/Server/Tests.hs +6/−6
README.md view
@@ -1,4 +1,4 @@-# happstack-server [][hackage] [](https://travis-ci.org/Happstack/happstack-server)+# happstack-server [][hackage] [](https://travis-ci.com/Happstack/happstack-server) [hackage]: https://hackage.haskell.org/package/happstack-server
happstack-server.cabal view
@@ -1,5 +1,5 @@ Name: happstack-server-Version: 7.6.1+Version: 7.7.0 Synopsis: Web related tools and services. Description: Happstack Server provides an HTTP server and a rich set of functions for routing requests, handling query parameters, generating responses, working with cookies, serving files, and more. For in-depth documentation see the Happstack Crash Course <http://happstack.com/docs/crashcourse/index.html> License: BSD3@@ -68,7 +68,7 @@ else build-depends: network < 2.6 Build-Depends: base >= 4 && < 5,- base64-bytestring >= 1.0 && < 1.2,+ base64-bytestring >= 1.0 && < 1.3, blaze-html >= 0.5 && < 0.10, bytestring, containers,
src/Happstack/Server/Cookie.hs view
@@ -3,6 +3,7 @@ module Happstack.Server.Cookie ( Cookie(..) , CookieLife(..)+ , SameSite(..) , mkCookie , addCookie , addCookies@@ -12,7 +13,7 @@ import Control.Monad.Trans (MonadIO(..)) import Happstack.Server.Internal.Monads (FilterMonad, composeFilter)-import Happstack.Server.Internal.Cookie (Cookie(..), CookieLife(..), calcLife, mkCookie, mkCookieHeader)+import Happstack.Server.Internal.Cookie (Cookie(..), CookieLife(..), SameSite(..), calcLife, mkCookie, mkCookieHeader) import Happstack.Server.Types (Response, addHeader) -- | Add the 'Cookie' to 'Response'.
src/Happstack/Server/Internal/Cookie.hs view
@@ -4,6 +4,7 @@ module Happstack.Server.Internal.Cookie ( Cookie(..) , CookieLife(..)+ , SameSite(..) , calcLife , mkCookie , mkCookieHeader@@ -44,6 +45,7 @@ , cookieValue :: String , secure :: Bool , httpOnly :: Bool+ , sameSite :: SameSite } deriving(Show,Eq,Read,Typeable,Data) -- | Specify the lifetime of a cookie.@@ -60,6 +62,31 @@ | Expired -- ^ cookie already expired deriving (Eq, Ord, Read, Show, Typeable) +-- | Options for specifying third party cookie behaviour.+--+-- Note that most or all web clients require the cookie to be secure if "none" is+-- specified.+data SameSite+ = SameSiteLax+ -- ^ The cookie is sent in first party contexts as well as linked requests initiated+ -- from other contexts.+ | SameSiteStrict+ -- ^ The cookie is sent in first party contexts only.+ | SameSiteNone+ -- ^ The cookie is sent in first as well as third party contexts if the cookie is+ -- secure.+ | SameSiteNoValue+ -- ^ The default; used if you do not wish a SameSite attribute present at all.+ deriving (Eq, Ord, Typeable, Data, Show, Read)++displaySameSite :: SameSite -> String+displaySameSite ss =+ case ss of+ SameSiteLax -> "SameSite=Lax"+ SameSiteStrict -> "SameSite=Strict"+ SameSiteNone -> "SameSite=None"+ SameSiteNoValue -> ""+ -- convert 'CookieLife' to the argument needed for calling 'mkCookieHeader' calcLife :: CookieLife -> IO (Maybe (Int, UTCTime)) calcLife Session = return Nothing@@ -74,13 +101,14 @@ -- | Creates a cookie with a default version of 1, empty domain, a--- path of "/", secure == False and httpOnly == False+-- path of "/", secure == False, httpOnly == False and+-- sameSite == SameSiteNoValue -- -- see also: 'addCookie' mkCookie :: String -- ^ cookie name -> String -- ^ cookie value -> Cookie-mkCookie key val = Cookie "1" "/" "" key val False False+mkCookie key val = Cookie "1" "/" "" key val False False SameSiteNoValue -- | Set a Cookie in the Result. -- The values are escaped as per RFC 2109, but some browsers may@@ -117,8 +145,8 @@ (cookieName cookie++"="++s cookieValue):[ (k++v) | (k,v) <- l, "" /= v ] ++ (if secure cookie then ["Secure"] else []) ++ (if httpOnly cookie then ["HttpOnly"] else [])--+ ++ (if sameSite cookie /= SameSiteNoValue+ then [displaySameSite . sameSite $ cookie] else []) -- | Not an supported api. Takes a cookie header and returns -- either a String error message or an array of parsed cookies@@ -142,7 +170,7 @@ val<-value path<-option "" $ try (cookieSep >> cookie_path) domain<-option "" $ try (cookieSep >> cookie_domain)- return $ Cookie ver path domain (low name) val False False+ return $ Cookie ver path domain (low name) val False False SameSiteNoValue cookie_version = cookie_special "$Version" cookie_path = cookie_special "$Path" cookie_domain = cookie_special "$Domain"
tests/Happstack/Server/Tests.hs view
@@ -41,24 +41,24 @@ "cookieParserTest" ~: [parseCookies "$Version=1;Cookie1=value1;$Path=\"/testpath\";$Domain=example.com;cookie2=value2" @?= (Right [- Cookie "1" "/testpath" "example.com" "cookie1" "value1" False False- , Cookie "1" "" "" "cookie2" "value2" False False+ Cookie "1" "/testpath" "example.com" "cookie1" "value1" False False SameSiteNoValue+ , Cookie "1" "" "" "cookie2" "value2" False False SameSiteNoValue ]) ,parseCookies " \t $Version = \"1\" ; cookie1 = \"randomcrap!@#%^&*()-_+={}[]:;'<>,.?/\\|\" , $Path=/ " @?= (Right [- Cookie "1" "/" "" "cookie1" "randomcrap!@#%^&*()-_+={}[]:;'<>,.?/|" False False+ Cookie "1" "/" "" "cookie1" "randomcrap!@#%^&*()-_+={}[]:;'<>,.?/|" False False SameSiteNoValue ]) ,parseCookies " cookie1 = value1 " @?= (Right [- Cookie "" "" "" "cookie1" "value1" False False+ Cookie "" "" "" "cookie1" "value1" False False SameSiteNoValue ]) ,parseCookies " $Version=\"1\";buggygooglecookie = valuewith=whereitshouldnotbe " @?= (Right [- Cookie "1" "" "" "buggygooglecookie" "valuewith=whereitshouldnotbe" False False+ Cookie "1" "" "" "buggygooglecookie" "valuewith=whereitshouldnotbe" False False SameSiteNoValue ]) , parseCookies "foo=\"\\\"bar\\\"\"" @?= (Right [- Cookie "" "" "" "foo" "\"bar\"" False False+ Cookie "" "" "" "foo" "\"bar\"" False False SameSiteNoValue ]) ]