Merge pull request #1417 from psibi/header-yesod
Add replaceOrAddHeader function to Yesod.Core.Handler module
This commit is contained in:
commit
e027652494
@ -1,3 +1,7 @@
|
|||||||
|
## 1.4.36
|
||||||
|
|
||||||
|
* Add `replaceOrAddHeader` function in Yesod.Core.Handler module. [1416](https://github.com/yesodweb/yesod/issues/1416)
|
||||||
|
|
||||||
## 1.4.35.1
|
## 1.4.35.1
|
||||||
|
|
||||||
* TH fix for GHC 8.2
|
* TH fix for GHC 8.2
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
{-# LANGUAGE RankNTypes #-}
|
{-# LANGUAGE RankNTypes #-}
|
||||||
{-# LANGUAGE DeriveDataTypeable #-}
|
{-# LANGUAGE DeriveDataTypeable #-}
|
||||||
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
--
|
--
|
||||||
-- Module : Yesod.Handler
|
-- Module : Yesod.Handler
|
||||||
@ -114,6 +115,7 @@ module Yesod.Core.Handler
|
|||||||
, deleteCookie
|
, deleteCookie
|
||||||
, addHeader
|
, addHeader
|
||||||
, setHeader
|
, setHeader
|
||||||
|
, replaceOrAddHeader
|
||||||
, setLanguage
|
, setLanguage
|
||||||
-- ** Content caching and expiration
|
-- ** Content caching and expiration
|
||||||
, cacheSeconds
|
, cacheSeconds
|
||||||
@ -206,7 +208,7 @@ import Control.Monad.Trans.Class (lift)
|
|||||||
|
|
||||||
import Data.Aeson (ToJSON(..))
|
import Data.Aeson (ToJSON(..))
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Data.Text.Encoding (decodeUtf8With, encodeUtf8)
|
import Data.Text.Encoding (decodeUtf8With, encodeUtf8, decodeUtf8)
|
||||||
import Data.Text.Encoding.Error (lenientDecode)
|
import Data.Text.Encoding.Error (lenientDecode)
|
||||||
import qualified Data.Text.Lazy as TL
|
import qualified Data.Text.Lazy as TL
|
||||||
import Text.Blaze.Html.Renderer.Utf8 (renderHtml)
|
import Text.Blaze.Html.Renderer.Utf8 (renderHtml)
|
||||||
@ -787,6 +789,40 @@ setHeader :: MonadHandler m => Text -> Text -> m ()
|
|||||||
setHeader = addHeader
|
setHeader = addHeader
|
||||||
{-# DEPRECATED setHeader "Please use addHeader instead" #-}
|
{-# DEPRECATED setHeader "Please use addHeader instead" #-}
|
||||||
|
|
||||||
|
-- | Replace an existing header with a new value or add a new header
|
||||||
|
-- if not present.
|
||||||
|
--
|
||||||
|
-- Note that, while the data type used here is 'Text', you must provide only
|
||||||
|
-- ASCII value to be HTTP compliant.
|
||||||
|
--
|
||||||
|
-- @since 1.4.36
|
||||||
|
replaceOrAddHeader :: MonadHandler m => Text -> Text -> m ()
|
||||||
|
replaceOrAddHeader a b =
|
||||||
|
modify $ \g -> g {ghsHeaders = replaceHeader (ghsHeaders g)}
|
||||||
|
where
|
||||||
|
repHeader = Header (encodeUtf8 a) (encodeUtf8 b)
|
||||||
|
|
||||||
|
sameHeaderName :: Header -> Header -> Bool
|
||||||
|
sameHeaderName (Header n1 _) (Header n2 _) = T.toLower (decodeUtf8 n1) == T.toLower (decodeUtf8 n2)
|
||||||
|
sameHeaderName _ _ = False
|
||||||
|
|
||||||
|
replaceIndividualHeader :: [Header] -> [Header]
|
||||||
|
replaceIndividualHeader [] = [repHeader]
|
||||||
|
replaceIndividualHeader xs = aux xs []
|
||||||
|
where
|
||||||
|
aux [] acc = acc ++ [repHeader]
|
||||||
|
aux (x:xs') acc =
|
||||||
|
if sameHeaderName repHeader x
|
||||||
|
then acc ++
|
||||||
|
[repHeader] ++
|
||||||
|
(filter (\header -> not (sameHeaderName header repHeader)) xs')
|
||||||
|
else aux xs' (acc ++ [x])
|
||||||
|
|
||||||
|
replaceHeader :: Endo [Header] -> Endo [Header]
|
||||||
|
replaceHeader endo =
|
||||||
|
let allHeaders :: [Header] = appEndo endo []
|
||||||
|
in Endo (\rest -> replaceIndividualHeader allHeaders ++ rest)
|
||||||
|
|
||||||
-- | Set the Cache-Control header to indicate this response should be cached
|
-- | Set the Cache-Control header to indicate this response should be cached
|
||||||
-- for the given number of seconds.
|
-- for the given number of seconds.
|
||||||
cacheSeconds :: MonadHandler m => Int -> m ()
|
cacheSeconds :: MonadHandler m => Int -> m ()
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import YesodCoreTest.Exceptions
|
|||||||
import YesodCoreTest.Widget
|
import YesodCoreTest.Widget
|
||||||
import YesodCoreTest.Media
|
import YesodCoreTest.Media
|
||||||
import YesodCoreTest.Links
|
import YesodCoreTest.Links
|
||||||
|
import YesodCoreTest.Header
|
||||||
import YesodCoreTest.NoOverloadedStrings
|
import YesodCoreTest.NoOverloadedStrings
|
||||||
import YesodCoreTest.InternalRequest
|
import YesodCoreTest.InternalRequest
|
||||||
import YesodCoreTest.ErrorHandling
|
import YesodCoreTest.ErrorHandling
|
||||||
@ -27,6 +28,7 @@ import Test.Hspec
|
|||||||
|
|
||||||
specs :: Spec
|
specs :: Spec
|
||||||
specs = do
|
specs = do
|
||||||
|
headerTest
|
||||||
cleanPathTest
|
cleanPathTest
|
||||||
exceptionsTest
|
exceptionsTest
|
||||||
widgetTest
|
widgetTest
|
||||||
|
|||||||
77
yesod-core/test/YesodCoreTest/Header.hs
Normal file
77
yesod-core/test/YesodCoreTest/Header.hs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
{-# LANGUAGE OverloadedStrings, TemplateHaskell, QuasiQuotes,
|
||||||
|
TypeFamilies, MultiParamTypeClasses, ViewPatterns #-}
|
||||||
|
|
||||||
|
module YesodCoreTest.Header
|
||||||
|
( headerTest
|
||||||
|
, Widget
|
||||||
|
, resourcesApp
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Data.Text (Text)
|
||||||
|
import Network.HTTP.Types (decodePathSegments)
|
||||||
|
import Network.Wai
|
||||||
|
import Network.Wai.Test
|
||||||
|
import Test.Hspec
|
||||||
|
import Yesod.Core
|
||||||
|
|
||||||
|
data App =
|
||||||
|
App
|
||||||
|
|
||||||
|
mkYesod
|
||||||
|
"App"
|
||||||
|
[parseRoutes|
|
||||||
|
/header1 Header1R GET
|
||||||
|
/header2 Header2R GET
|
||||||
|
/header3 Header3R GET
|
||||||
|
|]
|
||||||
|
|
||||||
|
instance Yesod App
|
||||||
|
|
||||||
|
getHeader1R :: Handler RepPlain
|
||||||
|
getHeader1R = do
|
||||||
|
addHeader "hello" "world"
|
||||||
|
return $ RepPlain $ toContent ("header test" :: Text)
|
||||||
|
|
||||||
|
getHeader2R :: Handler RepPlain
|
||||||
|
getHeader2R = do
|
||||||
|
addHeader "hello" "world"
|
||||||
|
replaceOrAddHeader "hello" "sibi"
|
||||||
|
return $ RepPlain $ toContent ("header test" :: Text)
|
||||||
|
|
||||||
|
getHeader3R :: Handler RepPlain
|
||||||
|
getHeader3R = do
|
||||||
|
addHeader "hello" "world"
|
||||||
|
addHeader "michael" "snoyman"
|
||||||
|
addHeader "yesod" "framework"
|
||||||
|
replaceOrAddHeader "yesod" "book"
|
||||||
|
return $ RepPlain $ toContent ("header test" :: Text)
|
||||||
|
|
||||||
|
runner :: Session () -> IO ()
|
||||||
|
runner f = toWaiApp App >>= runSession f
|
||||||
|
|
||||||
|
addHeaderTest :: IO ()
|
||||||
|
addHeaderTest =
|
||||||
|
runner $ do
|
||||||
|
res <- request defaultRequest {pathInfo = decodePathSegments "/header1"}
|
||||||
|
assertHeader "hello" "world" res
|
||||||
|
|
||||||
|
multipleHeaderTest :: IO ()
|
||||||
|
multipleHeaderTest =
|
||||||
|
runner $ do
|
||||||
|
res <- request defaultRequest {pathInfo = decodePathSegments "/header2"}
|
||||||
|
assertHeader "hello" "sibi" res
|
||||||
|
|
||||||
|
header3Test :: IO ()
|
||||||
|
header3Test = do
|
||||||
|
runner $ do
|
||||||
|
res <- request defaultRequest {pathInfo = decodePathSegments "/header3"}
|
||||||
|
assertHeader "hello" "world" res
|
||||||
|
assertHeader "michael" "snoyman" res
|
||||||
|
assertHeader "yesod" "book" res
|
||||||
|
|
||||||
|
headerTest :: Spec
|
||||||
|
headerTest =
|
||||||
|
describe "Test.Header" $ do
|
||||||
|
it "addHeader" addHeaderTest
|
||||||
|
it "multiple header" multipleHeaderTest
|
||||||
|
it "persist headers" header3Test
|
||||||
@ -1,5 +1,5 @@
|
|||||||
name: yesod-core
|
name: yesod-core
|
||||||
version: 1.4.35.1
|
version: 1.4.36
|
||||||
license: MIT
|
license: MIT
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
author: Michael Snoyman <michael@snoyman.com>
|
author: Michael Snoyman <michael@snoyman.com>
|
||||||
@ -150,6 +150,7 @@ test-suite tests
|
|||||||
YesodCoreTest.Auth
|
YesodCoreTest.Auth
|
||||||
YesodCoreTest.Cache
|
YesodCoreTest.Cache
|
||||||
YesodCoreTest.CleanPath
|
YesodCoreTest.CleanPath
|
||||||
|
YesodCoreTest.Header
|
||||||
YesodCoreTest.Csrf
|
YesodCoreTest.Csrf
|
||||||
YesodCoreTest.ErrorHandling
|
YesodCoreTest.ErrorHandling
|
||||||
YesodCoreTest.Exceptions
|
YesodCoreTest.Exceptions
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user