packages feed

servant-server 0.7.1 → 0.8

raw patch · 7 files changed

+104/−97 lines, 7 filesdep ~basedep ~filepathdep ~mtl

Dependency ranges changed: base, filepath, mtl, servant, transformers-compat, wai-app-static

Files

example/greet.hs view
@@ -34,7 +34,7 @@   :<|> "greet" :> ReqBody '[JSON] Greet :> Post '[JSON] Greet         -- DELETE /greet/:greetid-  :<|> "greet" :> Capture "greetid" Text :> Delete '[JSON] ()+  :<|> "greet" :> Capture "greetid" Text :> Delete '[JSON] NoContent  testApi :: Proxy TestApi testApi = Proxy@@ -54,7 +54,7 @@          postGreetH greet = return greet -        deleteGreetH _ = return ()+        deleteGreetH _ = return NoContent  -- Turn the server into a WAI app. 'serve' is provided by servant, -- more precisely by the Servant.Server module.
servant-server.cabal view
@@ -1,5 +1,5 @@ name:                servant-server-version:             0.7.1+version:             0.8 synopsis:            A family of combinators for defining webservices APIs and serving them description:   A family of combinators for defining webservices APIs and serving them@@ -45,31 +45,31 @@     Servant.Server.Internal.ServantErr     Servant.Utils.StaticFiles   build-depends:-        base               >= 4.7  && < 5-      , base-compat        >= 0.9+        base               >= 4.7  && < 4.10+      , base-compat        >= 0.9  && < 0.10       , aeson              >= 0.7  && < 0.12       , attoparsec         >= 0.12 && < 0.14-      , base64-bytestring  == 1.0.*+      , base64-bytestring  >= 1.0  && < 1.1       , bytestring         >= 0.10 && < 0.11       , containers         >= 0.5  && < 0.6       , http-api-data      >= 0.1  && < 0.3       , http-types         >= 0.8  && < 0.10       , network-uri        >= 2.6  && < 2.7-      , mtl                >= 2    && < 3+      , mtl                >= 2    && < 2.3       , network            >= 2.6  && < 2.7       , safe               >= 0.3  && < 0.4-      , servant            == 0.7.*+      , servant            == 0.8.*       , split              >= 0.2  && < 0.3       , string-conversions >= 0.3  && < 0.5       , system-filepath    >= 0.4  && < 0.5-      , filepath           >= 1+      , filepath           >= 1    && < 1.5       , text               >= 1.2  && < 1.3       , transformers       >= 0.3  && < 0.6-      , transformers-compat>= 0.4+      , transformers-compat>= 0.4  && < 0.6       , wai                >= 3.0  && < 3.3-      , wai-app-static     >= 3.0  && < 3.2+      , wai-app-static     >= 3.1  && < 3.2       , warp               >= 3.0  && < 3.3-      , word8              == 0.1.*+      , word8              >= 0.1  && < 0.2    hs-source-dirs: src   default-language: Haskell2010
src/Servant/Server.hs view
@@ -95,6 +95,9 @@   , err504   , err505 +  -- * Re-exports+  , Application+   ) where  import           Data.Proxy                    (Proxy)@@ -127,11 +130,11 @@ -- > main :: IO () -- > main = Network.Wai.Handler.Warp.run 8080 app ---serve :: (HasServer layout '[]) => Proxy layout -> Server layout -> Application+serve :: (HasServer api '[]) => Proxy api -> Server api -> Application serve p = serveWithContext p EmptyContext -serveWithContext :: (HasServer layout context)-    => Proxy layout -> Context context -> Server layout -> Application+serveWithContext :: (HasServer api context)+    => Proxy api -> Context context -> Server api -> Application serveWithContext p context server =   toApplication (runRouter (route p context (emptyDelayed (Route server)))) @@ -144,7 +147,7 @@ -- For the following API -- -- > type API =--- >        "a" :> "d" :> Get '[JSON] ()+-- >        "a" :> "d" :> Get '[JSON] NoContent -- >   :<|> "b" :> Capture "x" Int :> Get '[JSON] Bool -- >   :<|> "c" :> Put '[JSON] Bool -- >   :<|> "a" :> "e" :> Get '[JSON] Int@@ -186,12 +189,12 @@ -- that one takes precedence. If both parts fail, the \"better\" error -- code will be returned. ---layout :: (HasServer layout '[]) => Proxy layout -> Text+layout :: (HasServer api '[]) => Proxy api -> Text layout p = layoutWithContext p EmptyContext  -- | Variant of 'layout' that takes an additional 'Context'.-layoutWithContext :: (HasServer layout context)-    => Proxy layout -> Context context -> Text+layoutWithContext :: (HasServer api context)+    => Proxy api -> Context context -> Text layoutWithContext p context =   routerLayout (route p context (emptyDelayed (FailFatal err501))) 
src/Servant/Server/Internal.hs view
@@ -68,16 +68,16 @@ import           Servant.Server.Internal.ServantErr  -class HasServer layout context where-  type ServerT layout (m :: * -> *) :: *+class HasServer api context where+  type ServerT api (m :: * -> *) :: *    route ::-       Proxy layout+       Proxy api     -> Context context-    -> Delayed env (Server layout)+    -> Delayed env (Server api)     -> Router env -type Server layout = ServerT layout Handler+type Server api = ServerT api Handler  -- * Instances @@ -118,15 +118,15 @@ -- > server = getBook -- >   where getBook :: Text -> Handler Book -- >         getBook isbn = ...-instance (KnownSymbol capture, FromHttpApiData a, HasServer sublayout context)-      => HasServer (Capture capture a :> sublayout) context where+instance (KnownSymbol capture, FromHttpApiData a, HasServer api context)+      => HasServer (Capture capture a :> api) context where -  type ServerT (Capture capture a :> sublayout) m =-     a -> ServerT sublayout m+  type ServerT (Capture capture a :> api) m =+     a -> ServerT api m    route Proxy context d =     CaptureRouter $-        route (Proxy :: Proxy sublayout)+        route (Proxy :: Proxy api)               context               (addCapture d $ \ txt -> case parseUrlPieceMaybe txt :: Maybe a of                  Nothing -> delayedFail err400@@ -236,15 +236,15 @@ -- > server = viewReferer -- >   where viewReferer :: Referer -> Handler referer -- >         viewReferer referer = return referer-instance (KnownSymbol sym, FromHttpApiData a, HasServer sublayout context)-      => HasServer (Header sym a :> sublayout) context where+instance (KnownSymbol sym, FromHttpApiData a, HasServer api context)+      => HasServer (Header sym a :> api) context where -  type ServerT (Header sym a :> sublayout) m =-    Maybe a -> ServerT sublayout m+  type ServerT (Header sym a :> api) m =+    Maybe a -> ServerT api m    route Proxy context subserver =     let mheader req = parseHeaderMaybe =<< lookup str (requestHeaders req)-    in  route (Proxy :: Proxy sublayout) context (passToServer subserver mheader)+    in  route (Proxy :: Proxy api) context (passToServer subserver mheader)     where str = fromString $ symbolVal (Proxy :: Proxy sym)  -- | If you use @'QueryParam' "author" Text@ in one of the endpoints for your API,@@ -268,11 +268,11 @@ -- >   where getBooksBy :: Maybe Text -> Handler [Book] -- >         getBooksBy Nothing       = ...return all books... -- >         getBooksBy (Just author) = ...return books by the given author...-instance (KnownSymbol sym, FromHttpApiData a, HasServer sublayout context)-      => HasServer (QueryParam sym a :> sublayout) context where+instance (KnownSymbol sym, FromHttpApiData a, HasServer api context)+      => HasServer (QueryParam sym a :> api) context where -  type ServerT (QueryParam sym a :> sublayout) m =-    Maybe a -> ServerT sublayout m+  type ServerT (QueryParam sym a :> api) m =+    Maybe a -> ServerT api m    route Proxy context subserver =     let querytext r = parseQueryText $ rawQueryString r@@ -282,7 +282,7 @@             Just Nothing  -> Nothing -- param present with no value -> Nothing             Just (Just v) -> parseQueryParamMaybe v -- if present, we try to convert to                                         -- the right type-    in route (Proxy :: Proxy sublayout) context (passToServer subserver param)+    in route (Proxy :: Proxy api) context (passToServer subserver param)     where paramname = cs $ symbolVal (Proxy :: Proxy sym)  -- | If you use @'QueryParams' "authors" Text@ in one of the endpoints for your API,@@ -304,11 +304,11 @@ -- > server = getBooksBy -- >   where getBooksBy :: [Text] -> Handler [Book] -- >         getBooksBy authors = ...return all books by these authors...-instance (KnownSymbol sym, FromHttpApiData a, HasServer sublayout context)-      => HasServer (QueryParams sym a :> sublayout) context where+instance (KnownSymbol sym, FromHttpApiData a, HasServer api context)+      => HasServer (QueryParams sym a :> api) context where -  type ServerT (QueryParams sym a :> sublayout) m =-    [a] -> ServerT sublayout m+  type ServerT (QueryParams sym a :> api) m =+    [a] -> ServerT api m    route Proxy context subserver =     let querytext r = parseQueryText $ rawQueryString r@@ -317,7 +317,7 @@         -- corresponding values         parameters r = filter looksLikeParam (querytext r)         values r = mapMaybe (convert . snd) (parameters r)-    in  route (Proxy :: Proxy sublayout) context (passToServer subserver values)+    in  route (Proxy :: Proxy api) context (passToServer subserver values)     where paramname = cs $ symbolVal (Proxy :: Proxy sym)           looksLikeParam (name, _) = name == paramname || name == (paramname <> "[]")           convert Nothing = Nothing@@ -335,11 +335,11 @@ -- > server = getBooks -- >   where getBooks :: Bool -> Handler [Book] -- >         getBooks onlyPublished = ...return all books, or only the ones that are already published, depending on the argument...-instance (KnownSymbol sym, HasServer sublayout context)-      => HasServer (QueryFlag sym :> sublayout) context where+instance (KnownSymbol sym, HasServer api context)+      => HasServer (QueryFlag sym :> api) context where -  type ServerT (QueryFlag sym :> sublayout) m =-    Bool -> ServerT sublayout m+  type ServerT (QueryFlag sym :> api) m =+    Bool -> ServerT api m    route Proxy context subserver =     let querytext r = parseQueryText $ rawQueryString r@@ -347,7 +347,7 @@           Just Nothing  -> True  -- param is there, with no value           Just (Just v) -> examine v -- param with a value           Nothing       -> False -- param not in the query string-    in  route (Proxy :: Proxy sublayout) context (passToServer subserver param)+    in  route (Proxy :: Proxy api) context (passToServer subserver param)     where paramname = cs $ symbolVal (Proxy :: Proxy sym)           examine v | v == "true" || v == "1" || v == "" = True                     | otherwise = False@@ -392,14 +392,14 @@ -- > server = postBook -- >   where postBook :: Book -> Handler Book -- >         postBook book = ...insert into your db...-instance ( AllCTUnrender list a, HasServer sublayout context-         ) => HasServer (ReqBody list a :> sublayout) context where+instance ( AllCTUnrender list a, HasServer api context+         ) => HasServer (ReqBody list a :> api) context where -  type ServerT (ReqBody list a :> sublayout) m =-    a -> ServerT sublayout m+  type ServerT (ReqBody list a :> api) m =+    a -> ServerT api m    route Proxy context subserver =-    route (Proxy :: Proxy sublayout) context (addBodyCheck subserver bodyCheck)+    route (Proxy :: Proxy api) context (addBodyCheck subserver bodyCheck)     where       bodyCheck = withRequest $ \ request -> do         -- See HTTP RFC 2616, section 7.2.1@@ -416,15 +416,15 @@           Just (Right v) -> return v  -- | Make sure the incoming request starts with @"/path"@, strip it and--- pass the rest of the request path to @sublayout@.-instance (KnownSymbol path, HasServer sublayout context) => HasServer (path :> sublayout) context where+-- pass the rest of the request path to @api@.+instance (KnownSymbol path, HasServer api context) => HasServer (path :> api) context where -  type ServerT (path :> sublayout) m = ServerT sublayout m+  type ServerT (path :> api) m = ServerT api m    route Proxy context subserver =     pathRouter       (cs (symbolVal proxyPath))-      (route (Proxy :: Proxy sublayout) context subserver)+      (route (Proxy :: Proxy api) context subserver)     where proxyPath = Proxy :: Proxy path  instance HasServer api context => HasServer (RemoteHost :> api) context where
src/Servant/Server/Internal/ServantErr.hs view
@@ -31,7 +31,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err300 { errBody = "I can't choose." }+-- > failingHandler = throwError $ err300 { errBody = "I can't choose." } -- err300 :: ServantErr err300 = ServantErr { errHTTPCode = 300@@ -45,7 +45,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr err301+-- > failingHandler = throwError err301 -- err301 :: ServantErr err301 = ServantErr { errHTTPCode = 301@@ -59,7 +59,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr err302+-- > failingHandler = throwError err302 -- err302 :: ServantErr err302 = ServantErr { errHTTPCode = 302@@ -73,7 +73,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr err303+-- > failingHandler = throwError err303 -- err303 :: ServantErr err303 = ServantErr { errHTTPCode = 303@@ -87,7 +87,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr err304+-- > failingHandler = throwError err304 -- err304 :: ServantErr err304 = ServantErr { errHTTPCode = 304@@ -101,7 +101,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr err305+-- > failingHandler = throwError err305 -- err305 :: ServantErr err305 = ServantErr { errHTTPCode = 305@@ -115,7 +115,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr err307+-- > failingHandler = throwError err307 -- err307 :: ServantErr err307 = ServantErr { errHTTPCode = 307@@ -129,7 +129,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err400 { errBody = "Your request makes no sense to me." }+-- > failingHandler = throwError $ err400 { errBody = "Your request makes no sense to me." } -- err400 :: ServantErr err400 = ServantErr { errHTTPCode = 400@@ -143,7 +143,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err401 { errBody = "Your credentials are invalid." }+-- > failingHandler = throwError $ err401 { errBody = "Your credentials are invalid." } -- err401 :: ServantErr err401 = ServantErr { errHTTPCode = 401@@ -157,7 +157,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err402 { errBody = "You have 0 credits. Please give me $$$." }+-- > failingHandler = throwError $ err402 { errBody = "You have 0 credits. Please give me $$$." } -- err402 :: ServantErr err402 = ServantErr { errHTTPCode = 402@@ -171,7 +171,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err403 { errBody = "Please login first." }+-- > failingHandler = throwError $ err403 { errBody = "Please login first." } -- err403 :: ServantErr err403 = ServantErr { errHTTPCode = 403@@ -185,7 +185,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err404 { errBody = "(╯°□°)╯︵ ┻━┻)." }+-- > failingHandler = throwError $ err404 { errBody = "(╯°□°)╯︵ ┻━┻)." } -- err404 :: ServantErr err404 = ServantErr { errHTTPCode = 404@@ -199,7 +199,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err405 { errBody = "Your account privileges does not allow for this.  Please pay $$$." }+-- > failingHandler = throwError $ err405 { errBody = "Your account privileges does not allow for this.  Please pay $$$." } -- err405 :: ServantErr err405 = ServantErr { errHTTPCode = 405@@ -213,7 +213,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr err406+-- > failingHandler = throwError err406 -- err406 :: ServantErr err406 = ServantErr { errHTTPCode = 406@@ -227,7 +227,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr err407+-- > failingHandler = throwError err407 -- err407 :: ServantErr err407 = ServantErr { errHTTPCode = 407@@ -241,7 +241,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err409 { errBody = "Transaction conflicts with 59879cb56c7c159231eeacdd503d755f7e835f74" }+-- > failingHandler = throwError $ err409 { errBody = "Transaction conflicts with 59879cb56c7c159231eeacdd503d755f7e835f74" } -- err409 :: ServantErr err409 = ServantErr { errHTTPCode = 409@@ -255,7 +255,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err410 { errBody = "I know it was here at some point, but.. I blame bad luck." }+-- > failingHandler = throwError $ err410 { errBody = "I know it was here at some point, but.. I blame bad luck." } -- err410 :: ServantErr err410 = ServantErr { errHTTPCode = 410@@ -269,7 +269,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr err411+-- > failingHandler = throwError err411 -- err411 :: ServantErr err411 = ServantErr { errHTTPCode = 411@@ -283,7 +283,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err412 { errBody = "Precondition fail: x < 42 && y > 57" }+-- > failingHandler = throwError $ err412 { errBody = "Precondition fail: x < 42 && y > 57" } -- err412 :: ServantErr err412 = ServantErr { errHTTPCode = 412@@ -297,7 +297,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err413 { errBody = "Request exceeded 64k." }+-- > failingHandler = throwError $ err413 { errBody = "Request exceeded 64k." } -- err413 :: ServantErr err413 = ServantErr { errHTTPCode = 413@@ -311,7 +311,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err414 { errBody = "Maximum length is 64." }+-- > failingHandler = throwError $ err414 { errBody = "Maximum length is 64." } -- err414 :: ServantErr err414 = ServantErr { errHTTPCode = 414@@ -325,7 +325,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err415 { errBody = "Supported media types:  gif, png" }+-- > failingHandler = throwError $ err415 { errBody = "Supported media types:  gif, png" } -- err415 :: ServantErr err415 = ServantErr { errHTTPCode = 415@@ -339,7 +339,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err416 { errBody = "Valid range is [0, 424242]." }+-- > failingHandler = throwError $ err416 { errBody = "Valid range is [0, 424242]." } -- err416 :: ServantErr err416 = ServantErr { errHTTPCode = 416@@ -353,7 +353,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err417 { errBody = "I found a quux in the request.  This isn't going to work." }+-- > failingHandler = throwError $ err417 { errBody = "I found a quux in the request.  This isn't going to work." } -- err417 :: ServantErr err417 = ServantErr { errHTTPCode = 417@@ -367,7 +367,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err500 { errBody = "Exception in module A.B.C:55.  Have a great day!" }+-- > failingHandler = throwError $ err500 { errBody = "Exception in module A.B.C:55.  Have a great day!" } -- err500 :: ServantErr err500 = ServantErr { errHTTPCode = 500@@ -381,7 +381,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err501 { errBody = "/v1/foo is not supported with quux in the request." }+-- > failingHandler = throwError $ err501 { errBody = "/v1/foo is not supported with quux in the request." } -- err501 :: ServantErr err501 = ServantErr { errHTTPCode = 501@@ -395,7 +395,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err502 { errBody = "Tried gateway foo, bar, and baz.  None responded." }+-- > failingHandler = throwError $ err502 { errBody = "Tried gateway foo, bar, and baz.  None responded." } -- err502 :: ServantErr err502 = ServantErr { errHTTPCode = 502@@ -409,7 +409,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err503 { errBody = "We're rewriting in PHP." }+-- > failingHandler = throwError $ err503 { errBody = "We're rewriting in PHP." } -- err503 :: ServantErr err503 = ServantErr { errHTTPCode = 503@@ -423,7 +423,7 @@ -- Example: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err504 { errBody = "Backend foobar did not respond in 5 seconds." }+-- > failingHandler = throwError $ err504 { errBody = "Backend foobar did not respond in 5 seconds." } -- err504 :: ServantErr err504 = ServantErr { errHTTPCode = 504@@ -437,7 +437,7 @@ -- Example usage: -- -- > failingHandler :: Handler ()--- > failingHandler = throwErr $ err505 { errBody = "I support HTTP/4.0 only." }+-- > failingHandler = throwError $ err505 { errBody = "I support HTTP/4.0 only." } -- err505 :: ServantErr err505 = ServantErr { errHTTPCode = 505
test/Servant/Server/RouterSpec.hs view
@@ -8,7 +8,7 @@ import           Data.Proxy                     (Proxy(..)) import           Data.Text                      (unpack) import           Network.HTTP.Types             (Status (..))-import           Network.Wai                    (Application, responseBuilder)+import           Network.Wai                    (responseBuilder) import           Network.Wai.Internal           (Response (ResponseBuilder)) import           Test.Hspec import           Test.Hspec.Wai                 (get, shouldRespondWith, with)@@ -74,7 +74,7 @@ makeTrivialRouter p =   route p EmptyContext (emptyDelayed (FailFatal err501)) -type End = Get '[JSON] ()+type End = Get '[JSON] NoContent  -- The latter version looks more efficient, -- but the former should be compiled to the
test/Servant/ServerSpec.hs view
@@ -340,19 +340,23 @@ -- * headerSpec {{{ ------------------------------------------------------------------------------ -type HeaderApi a = Header "MyHeader" a :> Delete '[JSON] ()+type HeaderApi a = Header "MyHeader" a :> Delete '[JSON] NoContent headerApi :: Proxy (HeaderApi a) headerApi = Proxy  headerSpec :: Spec headerSpec = describe "Servant.API.Header" $ do -    let expectsInt :: Maybe Int -> Handler ()-        expectsInt (Just x) = when (x /= 5) $ error "Expected 5"+    let expectsInt :: Maybe Int -> Handler NoContent+        expectsInt (Just x) = do+          when (x /= 5) $ error "Expected 5"+          return NoContent         expectsInt Nothing  = error "Expected an int" -    let expectsString :: Maybe String -> Handler ()-        expectsString (Just x) = when (x /= "more from you") $ error "Expected more from you"+    let expectsString :: Maybe String -> Handler NoContent+        expectsString (Just x) = do+          when (x /= "more from you") $ error "Expected more from you"+          return NoContent         expectsString Nothing  = error "Expected a string"      with (return (serve headerApi expectsInt)) $ do@@ -410,7 +414,7 @@   :<|> "foo" :> Get '[PlainText] T.Text   :<|> "bar" :> Post '[JSON] Animal   :<|> "bar" :> Put '[JSON] Animal-  :<|> "bar" :> Delete '[JSON] ()+  :<|> "bar" :> Delete '[JSON] NoContent  alternativeApi :: Proxy AlternativeApi alternativeApi = Proxy@@ -422,7 +426,7 @@   :<|> return "a string"   :<|> return jerry   :<|> return jerry-  :<|> return ()+  :<|> return NoContent  alternativeSpec :: Spec alternativeSpec = do