Quick start ======================= Writing your API service comprises of two steps * Writing a contract (schematic representation of your API) * Providing a server implementation Contract -------- A contract is the list of end-points in your API service and the definition of each API endpoint. We define what goes in as **request** (Query params, form params, headers etc) and what comes out as the **response** of each API endpoint. As an example, consider a API service that lets you create, update, delete and fetch users. First step is to create a datatype for our API service. Lets call it :code:`MyApiService` To define your contract using the framework, you need to * Declare a data type for your API service. :: data MyApiService * Declare your routes as types. :: type User = Static "user" type UserId = "user" :/ Int * Write a :wahackage:`WebApi ` instance which declares the endpoints. :: instance WebApi MyApiService where -- Route type Apis MyApiService = '[ Route '[GET, POST] User , Route '[GET, PUT, DELETE] UserId ] * Write :wahackage:`ApiContract ` instances describing what goes in an **request** and what comes out as **response** from each API endpoint. Let's write our first :wahackage:`ApiContract ` instance for :code:`POST /user`. :: -- Our user type data UserData = UserData { age :: Int , address :: Text , name :: Text } deriving (Show, Eq, Generic) data UserToken = UserToken { userId :: Text , token :: Text } deriving (Show, Eq, Generic) -- Takes a User type in form params and returns UserToken. instance ApiContract MyApiService POST User where type FormParam POST User = UserData type ApiOut POST User = UserToken In our code snippet above, the end-point :code:`POST /user` takes user's information (**name, age** and **address**) as **post params** and gives out the user's **token** and **userId** An equivalent curl syntax would be: :: `curl -H "Content-Type: application/x-www-form-urlencoded" -d 'age=30&address=nazareth&name=Brian' http://api.peoplefrontofjudia.com/users ` * Finally to complete our contract, we have to write instances for json, param serialization & deserialization for :code:`UserData` and :code:`UserToken` types. A definition needn't be provided since `GHC.Generics `_ provides a generic implementation. :: instance FromJSON UserData instance ToJSON UserData instance FromParam 'FormParam UserData {--We dont need a FromParam instance since UserToken according to our example is not sent us form params or query params -} instance FromJSON UserToken instance ToJSON UserToken This completes the contract part of the API. Server implementation -------------- * First step is to create a type for the implementation and define :wahackage:`WebApiServer ` instance for it. :: data MyApiServiceImpl = MyApiServiceImpl instance WebApiServer MyApiServiceImpl where type HandlerM MyApiServiceImpl = IO type ApiInterface MyApiServiceImpl = MyApiService `HandlerM `_ is the base monad in which the :wahackage:`handler ` will run. We also state that :code:`MyApiServiceImpl` is the implementation for the contract :code:`MyApiServiceApi`. By keeping the implementation separate from the contract, it is possible for a contract to have multiple implementations. * Now let's create the :wahackage:`ApiHandler ` for one of our end-point :code:`POST /user` :: instance ApiHandler MyApiServiceImpl POST User where handler _ req = do let _userInfo = formParam req respond (UserToken "Foo" "Bar") The last thing that is left is to create a `WAI `_ application from all the aforementioned information. For that we use :wahackage:`serverApp ` . :: myApiApp :: Wai.Application myApiApp = serverApp serverSettings MyApiServiceImpl main :: IO () main = run 8000 myApiApp That's it - now :code:`myApiApp` could be run like any other `WAI `_ application. There's more you could do with **WebApi** apart from building API services. You can also :doc:`build haskell clients` for existing API services by defining just the contract, build full-stack webapps that serve html & javascript and :doc:`generate mock servers. `