diff --git a/src/Servant.hs b/src/Servant.hs index 07245e8b..69fb50a2 100644 --- a/src/Servant.hs +++ b/src/Servant.hs @@ -7,10 +7,9 @@ module Servant ( module Servant.Server, -- | For accessing servant APIs as API clients. module Servant.Client, - module Servant.Common.BaseUrl, -- | For generating documentation for servant APIs. module Servant.Docs, - -- | Helper module + -- | Using your types in request paths and query string parameters module Servant.Common.Text, -- | Utilities on top of the servant core module Servant.Utils.ApiQuasiQuoting, @@ -23,7 +22,6 @@ module Servant ( import Data.Proxy import Servant.API import Servant.Client -import Servant.Common.BaseUrl import Servant.Common.Text import Servant.Docs import Servant.Server diff --git a/src/Servant/API.hs b/src/Servant/API.hs index 21670a6e..76b4fbcc 100644 --- a/src/Servant/API.hs +++ b/src/Servant/API.hs @@ -25,8 +25,9 @@ module Servant.API ( module Servant.API.Put, -- * Untyped endpoints - -- | Plugging in a wai 'Network.Wai.Application' + -- | Plugging in a wai 'Network.Wai.Application', serving directories module Servant.API.Raw, + module Servant.Utils.StaticFiles, -- * Utilities -- | QuasiQuotes for endpoints @@ -47,3 +48,4 @@ import Servant.API.ReqBody import Servant.API.Sub import Servant.Utils.ApiQuasiQuoting (sitemap) import Servant.Utils.Links (mkLink) +import Servant.Utils.StaticFiles diff --git a/src/Servant/API/Delete.hs b/src/Servant/API/Delete.hs index a312345f..22743c42 100644 --- a/src/Servant/API/Delete.hs +++ b/src/Servant/API/Delete.hs @@ -11,7 +11,6 @@ import Data.Typeable import Network.HTTP.Types import Network.Wai import Servant.Client -import Servant.Common.BaseUrl import Servant.Common.Req import Servant.Docs import Servant.Server diff --git a/src/Servant/API/Get.hs b/src/Servant/API/Get.hs index 5f5b7237..c4817611 100644 --- a/src/Servant/API/Get.hs +++ b/src/Servant/API/Get.hs @@ -12,7 +12,6 @@ import Data.Typeable import Network.HTTP.Types import Network.Wai import Servant.Client -import Servant.Common.BaseUrl import Servant.Common.Req import Servant.Docs import Servant.Server diff --git a/src/Servant/API/Post.hs b/src/Servant/API/Post.hs index 10473c40..9dab6d46 100644 --- a/src/Servant/API/Post.hs +++ b/src/Servant/API/Post.hs @@ -12,7 +12,6 @@ import Data.Typeable import Network.HTTP.Types import Network.Wai import Servant.Client -import Servant.Common.BaseUrl import Servant.Common.Req import Servant.Docs import Servant.Server diff --git a/src/Servant/API/Put.hs b/src/Servant/API/Put.hs index 904dd5ef..ea6bde8e 100644 --- a/src/Servant/API/Put.hs +++ b/src/Servant/API/Put.hs @@ -12,7 +12,6 @@ import Data.Typeable import Network.HTTP.Types import Network.Wai import Servant.Client -import Servant.Common.BaseUrl import Servant.Common.Req import Servant.Docs import Servant.Server diff --git a/src/Servant/API/Raw.hs b/src/Servant/API/Raw.hs index 69afb687..93cb27d2 100644 --- a/src/Servant/API/Raw.hs +++ b/src/Servant/API/Raw.hs @@ -9,7 +9,6 @@ import Data.Proxy import Network.HTTP.Types import Network.Wai import Servant.Client -import Servant.Common.BaseUrl import Servant.Common.Req import Servant.Docs hiding (Method) import Servant.Server diff --git a/src/Servant/Client.hs b/src/Servant/Client.hs index 599a77cc..d7386e4b 100644 --- a/src/Servant/Client.hs +++ b/src/Servant/Client.hs @@ -1,17 +1,39 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE OverloadedStrings #-} -module Servant.Client where +-- | This module provides 'client' which can automatically generate +-- querying functions for each endpoint just from the type representing your +-- API. +module Servant.Client + ( client + , HasClient(..) + , module Servant.Common.BaseUrl + ) where import Data.Proxy +import Servant.Common.BaseUrl import Servant.Common.Req -- * Accessing APIs as a Client -- | 'client' allows you to produce operations to query an API from a client. +-- +-- > type MyApi = "books" :> Get [Book] -- GET /books +-- > :<|> "books" :> ReqBody Book :> Post Book -- POST /books +-- > +-- > myApi :: Proxy MyApi +-- > myApi = Proxy +-- > +-- > getAllBooks :: BaseUrl -> EitherT String IO [Book] +-- > postNewBook :: Book -> BaseUrl -> EitherT String IO Book +-- > (getAllBooks :<|> postNewBook) = client myApi client :: HasClient layout => Proxy layout -> Client layout client p = clientWithRoute p defReq +-- | This class lets us define how each API combinator +-- influences the creation of an HTTP request. Use 'client' +-- directly, this class implements the client-side +-- behavior of each combinator but you don't have to worry about it. class HasClient layout where type Client layout :: * clientWithRoute :: Proxy layout -> Req -> Client layout diff --git a/src/Servant/Common/BaseUrl.hs b/src/Servant/Common/BaseUrl.hs index e453c855..eae87c42 100644 --- a/src/Servant/Common/BaseUrl.hs +++ b/src/Servant/Common/BaseUrl.hs @@ -1,9 +1,6 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE ViewPatterns #-} -module Servant.Common.BaseUrl - ( Scheme(..) - , BaseUrl (..) - ) where +module Servant.Common.BaseUrl where import Data.List import GHC.Generics diff --git a/src/Servant/Common/Text.hs b/src/Servant/Common/Text.hs index a26de651..facac1ec 100644 --- a/src/Servant/Common/Text.hs +++ b/src/Servant/Common/Text.hs @@ -1,7 +1,10 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeSynonymInstances #-} -module Servant.Common.Text where +module Servant.Common.Text + ( FromText(..) + , ToText(..) + ) where import Data.String.Conversions import Data.Int @@ -9,11 +12,11 @@ import Data.Text import Data.Text.Read import Data.Word --- | For getting values from url captures, get parameters +-- | For getting values from url captures and query string parameters class FromText a where fromText :: Text -> Maybe a --- | For putting values in paths, get parameters +-- | For putting values in paths and query string parameters class ToText a where toText :: a -> Text @@ -29,11 +32,18 @@ instance FromText String where instance ToText String where toText = cs +-- | +-- > fromText "true" = Just True +-- > fromText "false" = Just False +-- > fromText _ = Nothing instance FromText Bool where fromText "true" = Just True fromText "false" = Just False fromText _ = Nothing +-- | +-- > toText True = "true" +-- > toText False = "false" instance ToText Bool where toText True = "true" toText False = "false" diff --git a/src/Servant/Docs.hs b/src/Servant/Docs.hs index 215ed9a5..527fc1b8 100644 --- a/src/Servant/Docs.hs +++ b/src/Servant/Docs.hs @@ -4,14 +4,7 @@ {-# LANGUAGE TemplateHaskell #-} ------------------------------------------------------------------------------- --- | --- Module : Servant.Docs --- License : BSD-style --- Maintainer : alpmestan@gmail.com --- Stability : provisional --- Portability : TH, TypeFamilies, DeriveGeneric --- --- This module lets you get API docs for free. It lets generate +-- | This module lets you get API docs for free. It lets generate -- an 'API' from the type that represents your API using 'docs': -- -- @docs :: 'HasDocs' api => 'Proxy' api -> 'API'@ diff --git a/src/Servant/Server.hs b/src/Servant/Server.hs index fe1f42f0..3dc6f168 100644 --- a/src/Servant/Server.hs +++ b/src/Servant/Server.hs @@ -1,10 +1,8 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE OverloadedStrings #-} --- | This module lets you implement 'Server's for defined APIs. You will --- probably need 'serve' (and look at the 'HasServer' type family), but --- 'toApplication' and 'route' are rather internals. - +-- | This module lets you implement 'Server's for defined APIs. You'll +-- most likely just need 'serve'. module Servant.Server where import Data.Monoid @@ -15,6 +13,22 @@ import Network.Wai -- * Implementing Servers -- | 'serve' allows you to implement an API and produce a wai 'Application'. +-- +-- Example: +-- +-- > type MyApi = "books" :> Get [Book] -- GET /books +-- > :<|> "books" :> ReqBody Book :> Post Book -- POST /books +-- > +-- > server :: Server MyApi +-- > server = listAllBooks :<|> postBook +-- > where listAllBooks = ... +-- > postBook book = ... +-- > +-- > app :: Application +-- > app = serve myApi server +-- > +-- > main :: IO () +-- > main = Network.Wai.Handler.Warp.run 8080 app serve :: HasServer layout => Proxy layout -> Server layout -> Application serve p server = toApplication (route p server) diff --git a/src/Servant/Utils/StaticFiles.hs b/src/Servant/Utils/StaticFiles.hs index 4c46ba7d..018b2793 100644 --- a/src/Servant/Utils/StaticFiles.hs +++ b/src/Servant/Utils/StaticFiles.hs @@ -10,7 +10,7 @@ import Network.HTTP.Types import Network.Wai import Network.Wai.Application.Static -import Servant.API +import Servant.API.Raw import Servant.Docs import Servant.Server diff --git a/test/Servant/ClientSpec.hs b/test/Servant/ClientSpec.hs index 945e0379..6069f932 100644 --- a/test/Servant/ClientSpec.hs +++ b/test/Servant/ClientSpec.hs @@ -25,7 +25,6 @@ import Test.QuickCheck import Servant.API import Servant.Client import Servant.Server -import Servant.Common.BaseUrl import Servant.ServerSpec