Spock 0.7.4.0 → 0.7.5.0
raw patch · 8 files changed
+143/−46 lines, 8 filesdep +hspecdep −hspec2dep ~aesondep ~basedep ~base64-bytestringPVP ok
version bump matches the API change (PVP)
Dependencies added: hspec
Dependencies removed: hspec2
Dependency ranges changed: aeson, base, base64-bytestring, blaze-html, bytestring, case-insensitive, containers, digestive-functors, directory, hashable, hspec-wai, http-types, mtl, old-locale, random, resource-pool, resourcet, stm, text, time, transformers, transformers-base, unordered-containers, vault, wai, wai-extra, warp
API changes (from Hackage documentation)
+ Web.Spock.Internal.Util: PrefHTML :: ClientPreferredFormat
+ Web.Spock.Internal.Util: PrefJSON :: ClientPreferredFormat
+ Web.Spock.Internal.Util: PrefText :: ClientPreferredFormat
+ Web.Spock.Internal.Util: PrefUnknown :: ClientPreferredFormat
+ Web.Spock.Internal.Util: PrefXML :: ClientPreferredFormat
+ Web.Spock.Internal.Util: data ClientPreferredFormat
+ Web.Spock.Internal.Util: detectPreferredFormat :: Text -> ClientPreferredFormat
+ Web.Spock.Internal.Util: instance Eq ClientPreferredFormat
+ Web.Spock.Internal.Util: instance Show ClientPreferredFormat
+ Web.Spock.Internal.Util: mapReqHeaders :: (ResponseHeaders -> ResponseHeaders) -> Response -> Response
+ Web.Spock.Internal.Util: mimeMapping :: HashMap Text ClientPreferredFormat
+ Web.Spock.Shared: PrefHTML :: ClientPreferredFormat
+ Web.Spock.Shared: PrefJSON :: ClientPreferredFormat
+ Web.Spock.Shared: PrefText :: ClientPreferredFormat
+ Web.Spock.Shared: PrefUnknown :: ClientPreferredFormat
+ Web.Spock.Shared: PrefXML :: ClientPreferredFormat
+ Web.Spock.Shared: data ClientPreferredFormat
+ Web.Spock.Shared: preferredFormat :: MonadIO m => ActionT m ClientPreferredFormat
Files
- Spock.cabal +51/−43
- src/Web/Spock/Internal/CoreAction.hs +13/−2
- src/Web/Spock/Internal/Util.hs +37/−0
- src/Web/Spock/Shared.hs +4/−1
- test/Web/Spock/FrameworkSpecHelper.hs +2/−0
- test/Web/Spock/Internal/UtilSpec.hs +26/−0
- test/Web/Spock/SafeSpec.hs +5/−0
- test/Web/Spock/SimpleSpec.hs +5/−0
Spock.cabal view
@@ -1,5 +1,5 @@ name: Spock-version: 0.7.4.0+version: 0.7.5.0 synopsis: Another Haskell web framework for rapid development description: This toolbox provides everything you need to get a quick start into web hacking with haskell: fast routing, middleware, json, blaze, sessions, cookies, database helper, csrf-protection Homepage: https://github.com/agrafix/Spock@@ -15,61 +15,69 @@ library hs-source-dirs: src- exposed-modules: Web.Spock.Simple,- Web.Spock.Safe,- Web.Spock.Shared- other-modules: Web.Spock.Internal.SessionManager,- Web.Spock.Internal.Monad,- Web.Spock.Internal.Types,- Web.Spock.Internal.Digestive,+ exposed-modules: Web.Spock.Internal.Util,+ Web.Spock.Safe,+ Web.Spock.Shared,+ Web.Spock.Simple+ other-modules: Web.Spock.Internal.Core, Web.Spock.Internal.CoreAction,+ Web.Spock.Internal.Digestive,+ Web.Spock.Internal.Monad,+ Web.Spock.Internal.SessionManager,+ Web.Spock.Internal.Types, Web.Spock.Internal.Wire- build-depends: aeson >= 0.6.2.1 && <0.9,+ build-depends:+ aeson >= 0.6.2.1, base >= 4 && < 5,- base64-bytestring ==1.*,- blaze-html ==0.7.*,- bytestring ==0.10.*,- case-insensitive >=1.1 && <1.3,- containers ==0.5.*,- digestive-functors ==0.7.*,- directory ==1.2.*,- hashable ==1.2.*,- http-types ==0.8.*,- monad-control ==0.3.*,- mtl >=2.1 && <2.3,- old-locale ==1.*,+ base64-bytestring >=1.0,+ blaze-html >=0.7,+ bytestring >=0.10,+ case-insensitive >=1.1,+ containers >=0.5,+ digestive-functors >=0.7,+ directory >=1.2,+ hashable >=1.2,+ http-types >=0.8,+ monad-control >=0.3,+ mtl >=2.1,+ old-locale >=1.0, path-pieces >=0.1.4,- random ==1.*,- reroute >=0.2.1 && <0.3,- resource-pool ==0.2.*,- resourcet >= 0.4 && <1.2,- stm ==2.4.*,- text >= 0.11.3.1 && <1.3,- time >=1.4 && <1.6,- transformers >=0.3 && <0.5,- transformers-base ==0.4.*,- unordered-containers ==0.2.*,- vault ==0.3.*,- wai >=3.0 && <4.0,- wai-extra >=3.0 && <4.0,- warp >=3.0 && <4.0+ random >=1.0,+ reroute >=0.2.1,+ resource-pool >=0.2,+ resourcet >= 0.4,+ stm >=2.4,+ text >= 0.11.3.1,+ time >=1.4,+ transformers >=0.3,+ transformers-base >=0.4,+ unordered-containers >=0.2,+ vault >=0.3,+ wai >=3.0,+ wai-extra >=3.0,+ warp >=3.0 ghc-options: -Wall -fno-warn-orphans test-suite spocktests type: exitcode-stdio-1.0 hs-source-dirs: test main-is: Spec.hs- other-modules: Web.Spock.SimpleSpec,+ other-modules:+ Web.Spock.FrameworkSpecHelper,+ Web.Spock.Internal.UtilSpec, Web.Spock.SafeSpec,- Web.Spock.FrameworkSpecHelper- build-depends: hspec2 >=0.4 && <0.5,- hspec-wai >=0.5 && <0.6,- wai >=3.0 && <4.0,- base >= 4 && < 5,- text >= 0.11.3.1 && <1.3,- Spock+ Web.Spock.SimpleSpec+ build-depends:+ base,+ hspec,+ hspec-wai,+ http-types,+ Spock,+ text,+ wai+ ghc-options: -Wall -fno-warn-orphans source-repository head
src/Web/Spock/Internal/CoreAction.hs view
@@ -10,10 +10,12 @@ , setCookie, setCookie' , bytes, lazyBytes, text, html, file, json, blaze , requireBasicAuth+ , preferredFormat, ClientPreferredFormat(..) ) where import Web.Spock.Internal.Wire+import Web.Spock.Internal.Util import Control.Arrow (first) import Control.Monad@@ -60,6 +62,15 @@ parseCookies = map parseCookie . T.splitOn ";" . T.concat . T.words parseCookie = first T.init . T.breakOnEnd "=" +-- | Tries to dected the preferred format of the response using the Accept header+preferredFormat :: MonadIO m => ActionT m ClientPreferredFormat+preferredFormat =+ do mAccept <- header "accept"+ case mAccept of+ Nothing -> return PrefUnknown+ Just t ->+ return $ detectPreferredFormat t+ -- | Get the raw request body body :: MonadIO m => ActionT m BS.ByteString body =@@ -201,13 +212,13 @@ -- | Send text as a response body. Content-Type will be "text/plain" text :: MonadIO m => T.Text -> ActionT m a text val =- do setHeader "Content-Type" "text/plain"+ do setHeader "Content-Type" "text/plain; charset=utf-8" bytes $ T.encodeUtf8 val -- | Send a text as response body. Content-Type will be "text/html" html :: MonadIO m => T.Text -> ActionT m a html val =- do setHeader "Content-Type" "text/html"+ do setHeader "Content-Type" "text/html; charset=utf-8" bytes $ T.encodeUtf8 val -- | Send a file as response
src/Web/Spock/Internal/Util.hs view
@@ -1,7 +1,44 @@+{-# LANGUAGE OverloadedStrings #-} module Web.Spock.Internal.Util where import Network.HTTP.Types import Network.Wai.Internal+import qualified Data.Text as T+import qualified Data.HashMap.Strict as HM++data ClientPreferredFormat+ = PrefJSON+ | PrefXML+ | PrefHTML+ | PrefText+ | PrefUnknown+ deriving (Show, Eq)++mimeMapping :: HM.HashMap T.Text ClientPreferredFormat+mimeMapping =+ HM.fromList $+ [ ("application/json", PrefJSON)+ , ("text/javascript", PrefJSON)+ , ("text/json", PrefJSON)+ , ("application/javascript", PrefJSON)+ , ("application/xml", PrefXML)+ , ("text/xml", PrefXML)+ , ("text/plain", PrefText)+ , ("text/html", PrefHTML)+ , ("application/xhtml+xml", PrefHTML)+ ]++detectPreferredFormat :: T.Text -> ClientPreferredFormat+detectPreferredFormat t =+ let (mimeTypeStr, _) = T.breakOn ";" t+ mimeTypes = map (T.toLower . T.strip) $ T.splitOn "," mimeTypeStr+ firstMatch [] = PrefUnknown+ firstMatch (x:xs) =+ case HM.lookup x mimeMapping of+ Just pref -> pref+ Nothing -> firstMatch xs+ in firstMatch mimeTypes+ mapReqHeaders :: (ResponseHeaders -> ResponseHeaders) -> Response -> Response mapReqHeaders f resp =
@@ -11,7 +11,10 @@ (-- * Helpers for running Spock runSpock, spockAsApp -- * Handeling requests- , request, header, cookie, body, jsonBody, jsonBody', files, UploadedFile (..)+ , request, header, cookie+ , preferredFormat, ClientPreferredFormat(..)+ , body, jsonBody, jsonBody'+ , files, UploadedFile (..) , params, param, param' -- * Sending responses , setStatus, setHeader, redirect, jumpNext, setCookie, setCookie', bytes, lazyBytes
test/Web/Spock/FrameworkSpecHelper.hs view
@@ -32,6 +32,8 @@ get "/subcomponent/subcomponent2/bar" `shouldRespondWith` "bar" { matchStatus = 200 } it "allows the definition of a fallback handler" $ do get "/askldjas/aklsdj" `shouldRespondWith` "askldjas/aklsdj" { matchStatus = 200 }+ it "detected the preferred format" $+ do request "GET" "/preferred-format" [("Accept", "text/html,application/xml;q=0.9,image/webp,*/*;q=0.8")] "" `shouldRespondWith` "html" { matchStatus = 200 } where verbTest verb verbVerbose = (verb "/verb-test")
+ test/Web/Spock/Internal/UtilSpec.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE OverloadedStrings #-}+module Web.Spock.Internal.UtilSpec (spec) where++import Web.Spock.Internal.Util++import Test.Hspec++spec :: Spec+spec =+ describe "Utils" $+ do describe "detectPreferredFormat" $+ do it "should detect json-only requests" $+ do detectPreferredFormat "application/json, text/javascript, */*; q=0.01" `shouldBe` PrefJSON+ detectPreferredFormat "application/json;" `shouldBe` PrefJSON+ detectPreferredFormat "text/javascript;" `shouldBe` PrefJSON+ it "should detect browsers as html clients" $+ do detectPreferredFormat "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" `shouldBe` PrefHTML+ detectPreferredFormat "text/html;" `shouldBe` PrefHTML+ detectPreferredFormat "application/xhtml+xml;" `shouldBe` PrefHTML+ it "should detect xml-only requests" $+ do detectPreferredFormat "application/xml, text/xml, */*; q=0.01" `shouldBe` PrefXML+ detectPreferredFormat "application/xml;" `shouldBe` PrefXML+ detectPreferredFormat "text/xml;" `shouldBe` PrefXML+ it "should detect text-only requests" $+ do detectPreferredFormat "text/plain, */*; q=0.01" `shouldBe` PrefText+ detectPreferredFormat "text/plain;" `shouldBe` PrefText
test/Web/Spock/SafeSpec.hs view
@@ -25,6 +25,11 @@ do get "foo" $ text "foo" subcomponent "/subcomponent2" $ do get "bar" $ text "bar"+ get "preferred-format" $+ do fmt <- preferredFormat+ case fmt of+ PrefHTML -> text "html"+ x -> text (T.pack (show x)) hookAny GET $ text . T.intercalate "/" spec :: Spec
test/Web/Spock/SimpleSpec.hs view
@@ -26,6 +26,11 @@ do get "foo" $ text "foo" subcomponent "/subcomponent2" $ do get "bar" $ text "bar"+ get "/preferred-format" $+ do fmt <- preferredFormat+ case fmt of+ PrefHTML -> text "html"+ x -> text (T.pack (show x)) hookAny GET $ text . T.intercalate "/" spec :: Spec