packages feed

scotty-resource 0.2.0.2 → 0.3.0.1

raw patch · 3 files changed

+148/−27 lines, 3 filesdep ~basedep ~containersdep ~http-typesnew-uploaderPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, containers, http-types, scotty, text, transformers, wai

API changes (from Hackage documentation)

- Web.Scotty.Resource.Trans: instance GHC.Base.Applicative (Web.Scotty.Resource.Trans.WebResource e m)
- Web.Scotty.Resource.Trans: instance GHC.Base.Functor (Web.Scotty.Resource.Trans.WebResource e m)
- Web.Scotty.Resource.Trans: instance GHC.Base.Monad (Web.Scotty.Resource.Trans.WebResource e m)
- Web.Scotty.Resource.Trans: instance GHC.Base.Monoid (Web.Scotty.Resource.Trans.WebResource e m a)
+ Web.Scotty.Resource.Trans: instance GHC.Internal.Base.Applicative (Web.Scotty.Resource.Trans.WebResource e m)
+ Web.Scotty.Resource.Trans: instance GHC.Internal.Base.Functor (Web.Scotty.Resource.Trans.WebResource e m)
+ Web.Scotty.Resource.Trans: instance GHC.Internal.Base.Monad (Web.Scotty.Resource.Trans.WebResource e m)
+ Web.Scotty.Resource.Trans: instance GHC.Internal.Base.Semigroup (Web.Scotty.Resource.Trans.WebResource e m a)
- Web.Scotty.Resource.Trans: data WebResource e m a
+ Web.Scotty.Resource.Trans: data WebResource e (m :: Type -> Type) a
- Web.Scotty.Resource.Trans: delete :: ActionT e m () -> WebResource e m ()
+ Web.Scotty.Resource.Trans: delete :: forall e (m :: Type -> Type). ActionT e m () -> WebResource e m ()
- Web.Scotty.Resource.Trans: get :: ActionT e m () -> WebResource e m ()
+ Web.Scotty.Resource.Trans: get :: forall e (m :: Type -> Type). ActionT e m () -> WebResource e m ()
- Web.Scotty.Resource.Trans: head :: ActionT e m () -> WebResource e m ()
+ Web.Scotty.Resource.Trans: head :: forall e (m :: Type -> Type). ActionT e m () -> WebResource e m ()
- Web.Scotty.Resource.Trans: method :: Method -> ActionT e m () -> WebResource e m ()
+ Web.Scotty.Resource.Trans: method :: forall e (m :: Type -> Type). Method -> ActionT e m () -> WebResource e m ()
- Web.Scotty.Resource.Trans: options :: ActionT e m () -> WebResource e m ()
+ Web.Scotty.Resource.Trans: options :: forall e (m :: Type -> Type). ActionT e m () -> WebResource e m ()
- Web.Scotty.Resource.Trans: patch :: ActionT e m () -> WebResource e m ()
+ Web.Scotty.Resource.Trans: patch :: forall e (m :: Type -> Type). ActionT e m () -> WebResource e m ()
- Web.Scotty.Resource.Trans: post :: ActionT e m () -> WebResource e m ()
+ Web.Scotty.Resource.Trans: post :: forall e (m :: Type -> Type). ActionT e m () -> WebResource e m ()
- Web.Scotty.Resource.Trans: put :: ActionT e m () -> WebResource e m ()
+ Web.Scotty.Resource.Trans: put :: forall e (m :: Type -> Type). ActionT e m () -> WebResource e m ()
- Web.Scotty.Resource.Trans: resource :: (MonadIO m, ScottyError e) => RoutePattern -> WebResource e m () -> ScottyT e m ()
+ Web.Scotty.Resource.Trans: resource :: forall (m :: Type -> Type) e. (MonadIO m, ScottyError e) => RoutePattern -> WebResource e m () -> ScottyT e m ()

Files

+ README.md view
@@ -0,0 +1,115 @@+# 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+```+
scotty-resource.cabal view
@@ -1,39 +1,47 @@--- Initial scotty-resource.cabal generated by cabal init.  For further --- documentation, see http://haskell.org/cabal/users-guide/-+cabal-version:       3.0 name:                scotty-resource-version:             0.2.0.2+version:             0.3.0.1 synopsis:            A Better way of modeling web resources. description:                               Allows users of the Scotty web framework to model                      resources more like the HTTP standard models them.-homepage:            https://github.com/taphu/scotty-resource+homepage:            https://github.com/owensmurray/scotty-resource license:             Apache-2.0 license-file:        LICENSE author:              Rick Owens-maintainer:          rick@owenssoftware.com-copyright:           2016 - Rick Owens+maintainer:          rick@owensmurray.com+copyright:           2025 Rick Owens category:            Web build-type:          Simple--- extra-source-files:  -cabal-version:       >=1.10+extra-source-files:+  README.md+  LICENSE +common dependencies+  build-depends:+    , base         >= 4.11.1.0 && < 4.21+    , containers   >= 0.5.7.0  && < 0.7+    , http-types   >= 0.8.6    && < 0.13+    , scotty       >= 0.11.0   && < 0.20+    , text         >= 1.2.3.0  && < 1.3+    , transformers >= 0.5.5.0  && < 0.7+    , wai          >= 3.0.3.0  && < 3.3++common warnings+  ghc-options:+    -Wmissing-export-lists+    -Wredundant-constraints+    -Wall+ library+  import: dependencies, warnings   exposed-modules:          Web.Scotty.Resource.Trans-  -- other-modules:       +  -- other-modules:   other-extensions:         OverloadedStrings-  build-depends:-    base         >= 4.8      && < 4.11,-    containers   >= 0.1.0.0  && < 0.6,-    http-types   >= 0.8.2    && < 0.13,-    scotty       >= 0.10     && < 0.12,-    text         >= 0.11.3.1 && < 1.3,-    transformers >= 0.3.0.0  && < 0.6,-    wai          >= 3.0.0    && < 3.3-  hs-source-dirs: src-  default-language: Haskell2010+  hs-source-dirs:      src+  default-language:    Haskell2010  source-repository head   type:     git
src/Web/Scotty/Resource/Trans.hs view
@@ -56,8 +56,8 @@   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`+  `Monad`, but, you know, whatever. The `Semigroup` typeclass more correctly+  represents what a `WebResource` really is. The `Monad` and `Semigroup`   typeclasses are used to compose instances of `WebResource`.    Here is another more complex example, with multiple resources.@@ -122,7 +122,6 @@ import Control.Monad.IO.Class (MonadIO) import Data.List (intersperse) import Data.Maybe (fromMaybe)-import Data.Monoid ((<>)) import Data.Set (fromList, toList) import Data.Text.Encoding (decodeUtf8) import Data.Text.Lazy (fromStrict)@@ -162,7 +161,7 @@  {- |   An opaque representation of an http resource. Use `get`, `post`, etc. to-  create one of these. Use the `Monad` or `Monoid` instances to compose them.+  create one of these. Use the `Monad` or `Semigroup` instances to compose them. -} data WebResource e m a = W [(Method, ActionT e m ())] a instance Functor (WebResource e m) where@@ -175,9 +174,8 @@   W methods a >>= f =     let W newMethods b = f a     in W (methods <> newMethods) b-instance Monoid (WebResource e m a) where-  mempty = W mempty undefined-  mappend (W a _) (W b _) = W (a <> b) undefined+instance Semigroup (WebResource e m a) where+  W a _ <> W b c = W (a <> b) c   {- |