# scotty-resource This module defines better resource routing for Scotty. Scotty is defined in terms of "routes", whereas HTTP is defined in terms of "resources". This package adds a "resource" abstraction to the scotty ecosystem. (note: All examples probably require -XOverloadedStrings) Scotty comes out of the box with a way to model "routes". The problem is that "routes" is not the abstraction used by the HTTP standard and it can sometimes be tricky to write a perfectly correct HTTP service using the routes model (where "correct" is judged against rfc-2616). The most blatant, (and who knows, maybe the only) example of this problem is shown by the scotty code: ```haskell import Web.Scotty.Trans (get, scottyT, text) ... scottyT 8080 id $ do get "/hello" $ do text "world" ``` If a client requests something like `DELETE /hello`, this scotty application will return `404 Not Found`, which conflicts with section 5.1.1 of rfc-2616. A better response would be `405 Method Not Allowed`, and it would include an automatically generated `Allow` response header. This library gives users a way to model "resources" which is closer to the abstractions used in the HTTP standard. We can re-write the above example like this: ```haskell import Web.Scotty.Trans (scottyT, text) import Web.Scotty.Resource.Trans (resource, get) ... scottyT 8080 id $ do resource "/hello" $ do get $ do text "world" ``` Given a request: ```http DELETE /hello HTTP/1.1 Host: localhost:8080 ``` The resource-based scotty application will produce something like: ```http HTTP/1.1 405 Method Not Allowed Allow: GET ``` Each resource is described by a `WebResource` value, which happens to be a `Monad`. The only reason `WebResource` implements `Monad` to fit in with the do-notation coding style of `ScottyT`. This is an abuse of `Monad`, but, you know, whatever. The `Monoid` typeclass more correctly represents what a `WebResource` really is. The `Monad` and `Monoid` typeclasses are used to compose instances of `WebResource`. Here is another more complex example, with multiple resources. ```haskell import Data.Aeson (decode) import Network.HTTP.Types (notFound404, badRequest400, noContent204) import Web.Scotty.Resource.Trans (resource, get, post) import Web.Scotty.Trans (scottyT, text, body, raw, status, param) import MyApplication (lookupPerson, storePerson) ... scottyT 8080 id $ do -- an "echo" resource resource "/echo" $ do get $ do text "hello world" post $ do -- echo the request body back to the user raw =<< body -- A resource that represents a kind of a RESTful database of people. -- This resource supports GET and PUT. resource "/people/:personId" $ do get $ do personId <- param "personId" maybePerson <- lookupPerson personId case maybePerson of Nothing -> status notFound404 Just person -> json person put $ do personId <- param "personId" maybePerson <- decode <$> body case maybePerson of Nothing -> do status badRequest400 text "Invalid person JSON" Just person -> storePerson personId person status noContent204 ```