GithubHelp home page GithubHelp logo

agrafix / spock Goto Github PK

View Code? Open in Web Editor NEW
677.0 20.0 59.0 918 KB

Another Haskell web framework for rapid development

Home Page: https://www.spock.li

Haskell 99.73% Shell 0.27%
haskell spock web framework functional http server api webframework

spock's Introduction

Build status Hackage Hackage Spock-Core

Intro

Another Haskell web framework for rapid development. To get started with Spock, check our tutorial or take a look at our example project funblog!

Mailing list

Please join our mailing list at [email protected]

Features

Another Haskell web framework for rapid development: This toolbox provides everything you need to get a quick start into web hacking with haskell:

  • fast typesafe routing
  • middleware
  • json
  • sessions
  • cookies
  • database helper
  • csrf-protection
  • typesafe contexts

Important Links

Talks

Candy

Extensions

The following Spock extensions exist:

Works well with Spock

SSL / HTTPS

If you'd like to use your application via HTTPS, there are two options:

  • Use nginx/haproxy/... as reverse proxy in front of the Spock application.
  • Convert the Spock application to a wai-application using the spockAsApp. Then use the warp-tls package to run it.

Notes

Since version 0.11.0.0 Spock drops simple routing in favor of typesafe routing and drops safe actions in favor of the "usual" way of csrf protection with a token.

Since version 0.7.0.0 Spock supports typesafe routing. If you wish to continue using the untyped version of Spock you can Use Web.Spock.Simple. The implementation of the routing is implemented in a separate haskell package called reroute.

Since version 0.5.0.0 Spock is no longer built on top of scotty. The design and interface is still influenced by scotty, but the internal implementation differs from scotty's.

Thanks to

Hacking

Pull requests are welcome! Please consider creating an issue beforehand, so we can discuss what you would like to do. Code should be written in a consistent style throughout the project. Avoid whitespace that is sensible to conflicts. (E.g. alignment of = signs in functions definitions)

Note that by sending a pull request you agree that your contribution can be released under the BSD3 License as part of the Spock package or related packages.

Misc

Officially Supported GHC Versions

  • 8.10.7
  • 8.8.4

License

Released under the BSD3 license. (c) 2013 - 2021 Alexander Thiemann

spock's People

Contributors

aaronang avatar agrafix avatar akirak avatar benbals avatar cdepillabout avatar cschneid avatar dylex avatar echaozh avatar glutamate avatar hanjoosten avatar intolerable avatar jberryman avatar lloucas-imvu avatar loisch avatar lpil avatar m-chrzan avatar morganthomas avatar nmk avatar paldepind avatar rabisg avatar skogsbaer avatar sol avatar soupi avatar timjb avatar tvh avatar ulfsauer0815 avatar vaibhavsagar avatar zialus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spock's Issues

Connection pooling with `resource-pool` and `spockT`

I'm using the spockT function to support a custom monad transformer stack but am having some issues with connection pooling as provided by the resource-pool package. Specifically, I have a PostgreSQLT transformer which wraps postgresql-simple and some functions for interacting with it:

createPostgreSQLConnectionPool :: ... -> IO (Pool Connection)
runPostgreSQLT :: Pool Connection -> PostgreSQLT m a -> m a

The main function for my API looks something like:

main 
  = do
      ...
      pool <- createPostgreSQLConnectionPool ...
      ...
      runSpock config $ spockT (runPostgreSQLT pool) $ do
        -- Define the Spock application, etc.
        ...

While this appears to work fine in terms of connections being created, exceptions being recognised and triggering appropriate destruction, the "reaper thread" that resource-pool provides is not working. After doing some digging, I can see the thread starting but never running past its initial threadDelay. I believe that after spockT and runSpock get going, there's no yield or opportunity for the thread to do its thing again.

Is there any way I can remedy this? Perhaps you're aware of this and this is why Spock provides support for pooling and the like "natively" -- because bolting it on like this is difficult/unachievable? I'd be keen to hear any options, since I'd rather not have the endpoint definitions manage connection acquisition/release themselves when the transformer can capture this behaviour automatically. Thanks in advance for any feedback.

Can't get CSRF working

I'm trying to compile the example from the documentation but all the time have errors. The last one looks like this:

Expected type: Int -> ActionCtxT () (WebStateM conn0 sess0 st0) ()
Actual type: hvect-0.2.0.0:Data.HVect.HVectElim
'[Int](ActionCtxT %28%29 IO %28%29)

I'm not saying that Spock works wrong, but at least something should be done with the documentation. Also one comprehensive example would be very nice!

Spock fails its test suite

When building with the NixOS automated builder, we see failures like:

  test/Web/Spock/FrameworkSpecHelper.hs:108:
  1) Web.Spock.Safe.SafeRouting.Headers supports custom headers
       uncaught exception: ErrorCall (toEnum{MultiHeader}: tag (-12565) is outside of enumeration's range (0,12))

  test/Web/Spock/FrameworkSpecHelper.hs:116:
  2) Web.Spock.Safe.SafeRouting.Headers supports multi headers
       uncaught exception: ErrorCall (toEnum{MultiHeader}: tag (-12565) is outside of enumeration's range (0,12))

  test/Web/Spock/FrameworkSpecHelper.hs:108:
  3) Web.Spock.Simple.SimpleRouting.Headers supports custom headers
       uncaught exception: ErrorCall (toEnum{MultiHeader}: tag (-12565) is outside of enumeration's range (0,12))

  test/Web/Spock/FrameworkSpecHelper.hs:116:
  4) Web.Spock.Simple.SimpleRouting.Headers supports multi headers
       uncaught exception: ErrorCall (toEnum{MultiHeader}: tag (-12565) is outside of enumeration's range (0,12))

You can also check the full build log.

Connect to a database

I'm trying to connect to a RethinkDB database, but I don't understand how to do it with Spock.

I created a PoolOrConn like this :

dbConn :: PoolOrConn R.RethinkDBHandle
dbConn =
  PCConn (ConnBuilder
          (R.connect "localhost" 28015 Nothing)
          R.close
          (PoolCfg 5 5 60)
         )

I typed my actions like this one :

insertMessageAction :: SpockAction R.RethinkDBHandle session state ()

Since I use a websocket app (named wsapp), my main function looks like this :

main :: IO ()
main = do
  app <- spockAsApp $ spockT _g $ appMiddleware >> appRoutes
  Warp.runSettings
        (Warp.setPort 3000 Warp.defaultSettings)
        (WaiWS.websocketsOr WS.defaultConnectionOptions wsapp app)

It looks I have to put something in he _g hole. Probably it has to do with monad transformers, which sadly I don't fully understand yet.

Could you provide some help?

What is the suggested way of using sessions in a production Spock web application?

I was using 'readShowSessionPersist' while developement. But now I am thinking about making the app live, I would like to know how to integrate production quality session management to my App.

I saw can see the spc_load function here, but it seems that it expects to return the contents of every live sessions, which does not appear to be very efficient to me.

What am I missing?

Pluggable session stores

Currently all sessions are stored in memory. This is a good default for most use cases, but for advanced configurations with load balancers it would be useful to hold sessions in a Redis store for example.

  • Keep #50 in mind

Aeson 0.6.2.1 causes "jsonBody" to fail

Correct json will return Left "incomplete input". Related to haskell/aeson#142

As a workaround I upgraded Aeson to 0.7.0.0 and am using "A.eitherDecodeStrict", which is the underlying function that jsonBody uses.

How tough would it be to upgrade the version of Aeson? I could try to take a crack at a pull request

Error compiling - "Wrong category of family instance"

I'm hitting an issue trying to compile Spock 0.7.5.1

src/Web/Spock/Internal/Types.hs:116:5:
    Wrong category of family instance; declaration was for a type synonym
    In the newtype instance declaration for ‘StM’
    In the instance declaration for
      ‘MonadBaseControl IO (WebStateM conn sess st)’
cabal: Error: some packages failed to install:
Spock-0.7.5.1 failed during the building phase. The exception was:
ExitFailure 1

Rewrite ActionT to be a Continuation Monad

Rewrite ActionT to be a continuation monad to get rid of the "hacky" exception method to about the handler after sending resources. Also make it clear in the docs that after sending something the action is aborted.

Future Development(s)

I wish this project could eventually become something like luminous in clojure. Do we have all the parts yet for haskell development to work like this?

http://www.luminusweb.net/

Is that the direction you have in mind for this project, or is it more likely to just be kept small, as something like sinatra?

I should mention - the microlibraries in the clojure(/script) ecosystem that allow us to end up with a full stack are outlined here:

http://www.luminusweb.net/docs/useful_libraries.md

subcomponent with var

It'd be nice to be able to be able to nest routes with variables:

subcomponent var $ \(id' :: Int) -> do
  get "/" $ f id'
  get "/abc" $ g id'

Probably it's already possible, but I don't understand how.

Adding Wai Specs with a DB connection

This is more of an example request, but I've been having trouble using spockApp to create a WAI application to use in testing. My routes run database actions and because of this I can't just do:

spockApp id app

as you have in the docs. Any tips on getting this to work?

Thanks!

Persist sessions across runs

When a server terminates all sessions are lost. Maybe the server should periodically write sessions to disk and reread then before launching.

Problem with cookies

Having a blast with Spock but I've run into a problem that I can't figure out.

When setting cookies this works well:

do setCookie "username" username 3600

But when I add a html response afterwards (or another 'setCookie') the cookie is never set:

do setCookie "username" username 3600
   html "yup"

Any idea why this is?

Clarify spock vs spockT

There's some confusion between spock and spockT (see #57). This should be improved:

  • move spockT into a *.Trans module and encourage the usage of spock
  • make spock more prominent in documentation and tutorials, explain the difference
  • ???

Any other ideas @jbpotonnier @wiria @cgag (or anyone else)?

modifySession should allow a return value

The modifySession signature should be changed to

modifySession :: (sess -> (sess, a)) -> SpockAction conn sess st a

We should also make a remark about atomic operations in the documentation

stackage integration

Would be cool if you make spock work with stackage, by adding the package to their officially supported list. It's way more convenient for managing dependencies for most use cases.

Check it out here:

https://www.stackage.org/

Thanks!
Dan

Enable client side routing

The goal of this task is to have a Spock-ghcjs library where we can use in the browser, similar to page.js. reroute already builds with ghcjs.

What to do:

  • identify if there's anything in Spock-core that could be useful in the browser and move that to a shared package
  • reimplement a familiar Spock interface using reroute and the functions from the shared package
  • setup unit testing infrastructure and write some tests
  • build a small demo application (optional)

Compilation failure on ghc 7.4.1

I was trying to build Spock on Ubuntu 12.0.4 LTS. I used the ghc that comes with haskell-platform 2012.1

Building Spock-0.4.3.5...
Preprocessing library Spock-0.4.3.5...
[1 of 6] Compiling Web.Spock.Types  ( src/Web/Spock/Types.hs, dist/dist-sandbox-d49fceaf/build/Web/Spock/Types.o )
[2 of 6] Compiling Web.Spock.Cookie ( src/Web/Spock/Cookie.hs, dist/dist-sandbox-d49fceaf/build/Web/Spock/Cookie.o )

src/Web/Spock/Cookie.hs:17:1:
    Illegal irreducible constraint SpockError e
    (Use -XConstraintKinds to permit this)
    In the type signature for `getCookie':
      getCookie :: (SpockError e, MonadIO m) =>
                   T.Text -> ActionT e m (Maybe T.Text)

src/Web/Spock/Cookie.hs:32:1:
    Illegal irreducible constraint SpockError e
    (Use -XConstraintKinds to permit this)
    In the type signature for `setCookie':
      setCookie :: (SpockError e, MonadIO m) =>
                   T.Text -> T.Text -> NominalDiffTime -> ActionT e m ()

src/Web/Spock/Cookie.hs:39:1:
    Illegal irreducible constraint SpockError e
    (Use -XConstraintKinds to permit this)
    In the type signature for setCookie':
      setCookie' :: (SpockError e, MonadIO m) =>
                    T.Text -> T.Text -> UTCTime -> ActionT e m ()

Deleting a cookie

Hi,
How would I delete a cookie? Setting an empty cookie didn't work for me.

setCookie "myCookie" "" 100

doesn't work.

Compile error with 7.10.2 against 0.7.9.0.

I'm not sure if this is a 7.10.2 issue or a dependency bounds issue, the same project works built against 7.8.4:

Downloading ansi-terminal-0.6.2.1...
Downloading appar-0.1.4...
Configuring base-orphans-0.3.2...
Configuring base64-bytestring-1.0.0.1...
Configuring byteable-0.1.1...
Configuring data-default-class-0.0.1...
Configuring dlist-0.7.1.1...
Configuring mmorph-1.0.4...
Configuring nats-1...
Configuring mtl-2.2.1...
Downloading auto-update-0.1.2.1...
Building mmorph-1.0.4...
Building base-orphans-0.3.2...
Building data-default-class-0.0.1...
Building nats-1...
Building dlist-0.7.1.1...
Building byteable-0.1.1...
Building mtl-2.2.1...
Building base64-bytestring-1.0.0.1...
Downloading base16-bytestring-0.1.1.6...
Downloading byteorder-1.0.4...
Configuring network-2.6.1.0...
Installed nats-1
Installed data-default-class-0.0.1
Configuring old-locale-1.0.0.7...
Configuring prelude-extras-0.4...
Installed base-orphans-0.3.2
Configuring random-1.1...
Installed byteable-0.1.1
Building old-locale-1.0.0.7...
Building prelude-extras-0.4...
Configuring primitive-0.6...
Installed mmorph-1.0.4
Building random-1.1...
Downloading bytestring-builder-0.10.6.0.0...
Configuring stm-2.4.4...
Installed dlist-0.7.1.1
Downloading easy-file-0.2.1...
Configuring syb-0.4.4...
Installed base64-bytestring-1.0.0.1
Downloading network-info-0.2.0.6...
Building primitive-0.6...
Downloading parallel-3.2.0.6...
Downloading reflection-1.5.2.1...
Building stm-2.4.4...
Downloading safe-0.3.9...
Downloading stringsearch-0.3.6.6...
Building syb-0.4.4...
Downloading unix-compat-0.4.1.4...
Configuring tagged-0.8.0.1...
Installed old-locale-1.0.0.7
Downloading word8-0.1.2...
Configuring text-1.2.1.0...
Downloading data-default-instances-base-0.0.1...
Installed mtl-2.2.1
Downloading data-default-instances-containers-0.0.1...
Building tagged-0.8.0.1...
Configuring transformers-compat-0.4.0.4...
Installed prelude-extras-0.4
Downloading data-default-instances-dlist-0.0.1...
Downloading data-default-instances-old-locale-0.0.1...
Building text-1.2.1.0...
Downloading regex-base-0.93.2...
Downloading wiring-0.3.0...
Building transformers-compat-0.4.0.4...
Configuring zlib-0.6.1.1...
Installed stm-2.4.4
Building network-2.6.1.0...
Configuring appar-0.1.4...
Installed transformers-compat-0.4.0.4
Building zlib-0.6.1.1...
Building appar-0.1.4...
Configuring auto-update-0.1.2.1...
Installed primitive-0.6
Configuring ansi-terminal-0.6.2.1...
Installed tagged-0.8.0.1
Installed syb-0.4.4
Configuring cryptohash-0.11.6...
Building auto-update-0.1.2.1...
Building ansi-terminal-0.6.2.1...
Configuring base16-bytestring-0.1.1.6...
Installed appar-0.1.4
Building cryptohash-0.11.6...
Configuring byteorder-1.0.4...
Installed random-1.1
Building base16-bytestring-0.1.1.6...
Configuring bytestring-builder-0.10.6.0.0...
Installed auto-update-0.1.2.1
Building byteorder-1.0.4...
Building bytestring-builder-0.10.6.0.0...
Configuring easy-file-0.2.1...
Installed base16-bytestring-0.1.1.6
Configuring network-info-0.2.0.6...
Installed bytestring-builder-0.10.6.0.0
Configuring reflection-1.5.2.1...
Installed byteorder-1.0.4
Building easy-file-0.2.1...
Building network-info-0.2.0.6...
Building reflection-1.5.2.1...
Configuring parallel-3.2.0.6...
Installed easy-file-0.2.1
Configuring safe-0.3.9...
Installed ansi-terminal-0.6.2.1
Configuring old-time-1.1.0.3...
Installed reflection-1.5.2.1
Building parallel-3.2.0.6...
Configuring stringsearch-0.3.6.6...
Installed network-info-0.2.0.6
Building safe-0.3.9...
Building stringsearch-0.3.6.6...
Configuring word8-0.1.2...
Installed zlib-0.6.1.1
Configuring data-default-instances-base-0.0.1...
Installed parallel-3.2.0.6
Building word8-0.1.2...
Configuring data-default-instances-containers-0.0.1...
Installed safe-0.3.9
Building old-time-1.1.0.3...
Building data-default-instances-base-0.0.1...
Building data-default-instances-containers-0.0.1...
Configuring data-default-instances-old-locale-0.0.1...
Installed word8-0.1.2
Configuring data-default-instances-dlist-0.0.1...
Installed network-2.6.1.0
Downloading iproute-1.4.0...
Downloading simple-sendfile-0.2.20...
Configuring unix-compat-0.4.1.4...
Installed data-default-instances-base-0.0.1
Building data-default-instances-old-locale-0.0.1...
Configuring regex-base-0.93.2...
Installed data-default-instances-containers-0.0.1
Building data-default-instances-dlist-0.0.1...
Building unix-compat-0.4.1.4...
Configuring wiring-0.3.0...
Installed data-default-instances-old-locale-0.0.1
Building regex-base-0.93.2...
Configuring StateVar-1.1.0.0...
Installed cryptohash-0.11.6
Configuring transformers-base-0.4.4...
Installed data-default-instances-dlist-0.0.1
Downloading data-default-0.5.3...
Building wiring-0.3.0...
Building StateVar-1.1.0.0...
Building transformers-base-0.4.4...
Configuring exceptions-0.8.0.2...
Installed unix-compat-0.4.1.4
Configuring vector-0.10.12.3...
Installed StateVar-1.1.0.0
Building exceptions-0.8.0.2...
Configuring distributive-0.4.4...
Installed transformers-base-0.4.4
Installed regex-base-0.93.2
Downloading regex-posix-0.95.2...
Configuring tf-random-0.5...
Building vector-0.10.12.3...
Building tf-random-0.5...
Configuring simple-sendfile-0.2.20...
Installed old-time-1.1.0.3
Downloading unix-time-0.3.5...
Building simple-sendfile-0.2.20...
Configuring data-default-0.5.3...
Installed wiring-0.3.0
Configuring monad-control-1.0.0.4...
Installed exceptions-0.8.0.2
Building data-default-0.5.3...
Building monad-control-1.0.0.4...
Configuring iproute-1.4.0...
Installed simple-sendfile-0.2.20
Configuring regex-posix-0.95.2...
Installed stringsearch-0.3.6.6
Configuring unix-time-0.3.5...
Installed data-default-0.5.3
Building iproute-1.4.0...
Building regex-posix-0.95.2...
Installed tf-random-0.5
Configuring QuickCheck-2.8.1...
Installed monad-control-1.0.0.4
Configuring lifted-base-0.2.3.6...
Building QuickCheck-2.8.1...
Building lifted-base-0.2.3.6...
Building distributive-0.4.4...
Building unix-time-0.3.5...
Installed distributive-0.4.4
Installed lifted-base-0.2.3.6
Configuring resourcet-1.1.5...
Building resourcet-1.1.5...
Installed unix-time-0.3.5
Installed iproute-1.4.0
Installed regex-posix-0.95.2
Downloading regex-compat-0.95.1...
Configuring regex-compat-0.95.1...
Building regex-compat-0.95.1...
Installed resourcet-1.1.5
Configuring conduit-1.2.4.2...
Building conduit-1.2.4.2...
Installed regex-compat-0.95.1
Installed conduit-1.2.4.2
Installed QuickCheck-2.8.1
Installed text-1.2.1.0
Configuring blaze-builder-0.4.0.1...
Downloading clay-0.10.1...
Downloading digestive-functors-0.8.0.0...
Configuring hashable-1.2.3.2...
Configuring mime-types-0.1.0.6...
Configuring parsec-3.1.9...
Building hashable-1.2.3.2...
Building parsec-3.1.9...
Building mime-types-0.1.0.6...
Building blaze-builder-0.4.0.1...
Downloading fast-logger-2.3.1...
Configuring clay-0.10.1...
Configuring digestive-functors-0.8.0.0...
Downloading path-pieces-0.2.0...
Configuring path-pieces-0.2.0...
Downloading xml-types-0.3.4...
Building clay-0.10.1...
Building digestive-functors-0.8.0.0...
Building path-pieces-0.2.0...
Installed hashable-1.2.3.2
Configuring fast-logger-2.3.1...
Downloading uuid-types-1.0.1...
Building fast-logger-2.3.1...
Configuring xml-types-0.3.4...
Installed blaze-builder-0.4.0.1
Downloading blaze-markup-0.7.0.2...
Installed path-pieces-0.2.0
Configuring case-insensitive-1.2.0.4...
Building xml-types-0.3.4...
Building case-insensitive-1.2.0.4...
Configuring scientific-0.3.3.8...
Installed fast-logger-2.3.1
Configuring uuid-types-1.0.1...
Installed digestive-functors-0.8.0.0
Building scientific-0.3.3.8...
Configuring unordered-containers-0.2.5.1...
Installed case-insensitive-1.2.0.4
Building uuid-types-1.0.1...
Configuring cookie-0.4.1.5...
Installed vector-0.10.12.3
Downloading resource-pool-0.2.3.2...
Building unordered-containers-0.2.5.1...
Building cookie-0.4.1.5...
Configuring streaming-commons-0.1.12.1...
Installed mime-types-0.1.0.6
Installed cookie-0.4.1.5
Configuring blaze-markup-0.7.0.2...
Building streaming-commons-0.1.12.1...
Configuring http-types-0.8.6...
Installed parsec-3.1.9
Building blaze-markup-0.7.0.2...
Configuring resource-pool-0.2.3.2...
Installed uuid-types-1.0.1
Downloading uuid-1.3.10...
Building http-types-0.8.6...
Building resource-pool-0.2.3.2...
Installed scientific-0.3.3.8
Configuring network-uri-2.6.0.3...
Configuring uuid-1.3.10...
Installed xml-types-0.3.4
Building network-uri-2.6.0.3...
Building uuid-1.3.10...
Configuring attoparsec-0.13.0.0...
Installed resource-pool-0.2.3.2
Building attoparsec-0.13.0.0...
Installed http-types-0.8.6
Installed uuid-1.3.10
Installed clay-0.10.1
Installed blaze-markup-0.7.0.2
Downloading blaze-html-0.8.0.2...
Installed unordered-containers-0.2.5.1
Downloading graph-core-0.2.2.0...
Configuring semigroups-0.16.2.2...
Installed streaming-commons-0.1.12.1
Downloading vault-0.3.0.4...
Configuring blaze-html-0.8.0.2...
Configuring graph-core-0.2.2.0...
Building semigroups-0.16.2.2...
Configuring vault-0.3.0.4...
Building blaze-html-0.8.0.2...
Building graph-core-0.2.2.0...
Building vault-0.3.0.4...
Installed network-uri-2.6.0.3
Configuring http-client-0.4.11.2...
Building http-client-0.4.11.2...
Installed vault-0.3.0.4
Downloading wai-3.0.2.3...
Installed graph-core-0.2.2.0
Downloading reroute-0.2.3.0...
Configuring wai-3.0.2.3...
Configuring reroute-0.2.3.0...
Building wai-3.0.2.3...
Building reroute-0.2.3.0...
Installed wai-3.0.2.3
Downloading wai-logger-2.2.4...
Configuring wai-logger-2.2.4...
Building wai-logger-2.2.4...
Installed semigroups-0.16.2.2
Configuring bifunctors-5...
Configuring void-0.7...
Building void-0.7...
Building bifunctors-5...
Installed wai-logger-2.2.4
Installed void-0.7
Configuring contravariant-1.3.1.1...
Downloading wai-extra-3.0.7.1...
Configuring wai-extra-3.0.7.1...
Building contravariant-1.3.1.1...
Installed reroute-0.2.3.0
Building wai-extra-3.0.7.1...
Installed contravariant-1.3.1.1
Configuring comonad-4.2.6...
Installed http-client-0.4.11.2
Installed bifunctors-5
Installed blaze-html-0.8.0.2
Downloading digestive-functors-blaze-0.6.0.6...
Building comonad-4.2.6...
Configuring digestive-functors-blaze-0.6.0.6...
Building digestive-functors-blaze-0.6.0.6...
Installed attoparsec-0.13.0.0
Downloading aeson-0.9.0.1...
Downloading conduit-extra-1.1.8...
Installed wai-extra-3.0.7.1
Installed digestive-functors-blaze-0.6.0.6
Downloading http-date-0.0.6.1...
Configuring conduit-extra-1.1.8...
Installed comonad-4.2.6
Configuring profunctors-5.1.1...
Configuring semigroupoids-5.0.0.1...
Building conduit-extra-1.1.8...
Building profunctors-5.1.1...
Configuring http-date-0.0.6.1...
Configuring aeson-0.9.0.1...
Building http-date-0.0.6.1...
Building aeson-0.9.0.1...
Building semigroupoids-5.0.0.1...
Installed http-date-0.0.6.1
Downloading warp-3.0.13.1...
Configuring warp-3.0.13.1...
Installed profunctors-5.1.1
Building warp-3.0.13.1...
Installed conduit-extra-1.1.8
Downloading xml-conduit-1.3.0...
Configuring xml-conduit-1.3.0...
Building xml-conduit-1.3.0...
Installed semigroupoids-5.0.0.1
Configuring free-4.12.1...
Building free-4.12.1...
Installed warp-3.0.13.1
Installed xml-conduit-1.3.0
Installed free-4.12.1
Downloading adjunctions-4.2.1...
Configuring adjunctions-4.2.1...
Building adjunctions-4.2.1...
Installed adjunctions-4.2.1
Downloading kan-extensions-4.2.2...
Configuring kan-extensions-4.2.2...
Installed aeson-0.9.0.1
Downloading Spock-0.7.9.0...
Building kan-extensions-4.2.2...
Configuring Spock-0.7.9.0...
Building Spock-0.7.9.0...
Installed kan-extensions-4.2.2
Downloading lens-4.11...
Failed to install Spock-0.7.9.0
Build log ( /home/sean/workspace/oneaday/.cabal-sandbox/logs/Spock-0.7.9.0.log ):
Configuring Spock-0.7.9.0...
Building Spock-0.7.9.0...
Preprocessing library Spock-0.7.9.0...
[ 1 of 10] Compiling Web.Spock.Internal.Wire ( src/Web/Spock/Internal/Wire.hs, dist/dist-sandbox-3e6995ac/build/Web/Spock/Internal/Wire.o )
[ 2 of 10] Compiling Web.Spock.Internal.Util ( src/Web/Spock/Internal/Util.hs, dist/dist-sandbox-3e6995ac/build/Web/Spock/Internal/Util.o )
[ 3 of 10] Compiling Web.Spock.Internal.CoreAction ( src/Web/Spock/Internal/CoreAction.hs, dist/dist-sandbox-3e6995ac/build/Web/Spock/Internal/CoreAction.o )
[ 4 of 10] Compiling Web.Spock.Internal.Types ( src/Web/Spock/Internal/Types.hs, dist/dist-sandbox-3e6995ac/build/Web/Spock/Internal/Types.o )

src/Web/Spock/Internal/Types.hs:143:80:
    Couldn't match expected type ‘ReaderT
                                    (WebState conn sess st) (ResourceT IO) a1
                                  -> IO a1’
                with actual type ‘forall a2.
                                  ReaderT (WebState conn sess st) (ResourceT IO) a2
                                  -> IO (StM (ReaderT (WebState conn sess st) (ResourceT IO)) a2)’
    Relevant bindings include
      runInBase :: forall a.
                   ReaderT (WebState conn sess st) (ResourceT IO) a
                   -> IO (StM (ReaderT (WebState conn sess st) (ResourceT IO)) a)
        (bound at src/Web/Spock/Internal/Types.hs:143:50)
      f :: RunInBase (WebStateM conn sess st) IO -> IO a
        (bound at src/Web/Spock/Internal/Types.hs:143:18)
      liftBaseWith :: (RunInBase (WebStateM conn sess st) IO -> IO a)
                      -> WebStateM conn sess st a
        (bound at src/Web/Spock/Internal/Types.hs:143:5)
    In the first argument of ‘(.)’, namely ‘runInBase’
    In the second argument of ‘(.)’, namely ‘runInBase . runWebStateM’

TLS support

Hi,
I was wondering if there is TLS support in spock already/planned? Some of the websites built with spock (by agrafix) have https but I could not find anything in the spock package itself.
Thanks!

No cookies Function

So I have a way to get a specific cookie by name, but none to get all cookies. I'd expect it to either return a (Map Text Text) or a [(Text Text)]. I was attempting to convert a service we have written in Flask which serializes all cookies and does some other stuff with them. Without this functionality, I'm not able to convert the service.

Remove untyped routing

To simplify things we will be removing the untyped routing approach in the next release. It does not provide any benefits over the type safe routing. If you have any objections please post here!

Reusable API Definitions

One would like to define APIs once, and then implement the API using Spock on the server but also have a possiblity to call the API in a typesafe way from the client.

  • What about headers?

Example API definition (GHC / GHCJS)

module ApiDef where

data LoginReq
   = LoginReq
   { lr_username :: !T.Text
   , lr_password :: !T.Text
   } deriving (Show, Eq, Generic, NFData, Typeable, ToJSON, FromJSON)

data LoginResp
   = LoginOkay
   | LoginFailed
   deriving (Show, Eq, Generic, NFData, Typeable, ToJSON, FromJSON)

loginUser :: Endpoint '[] ('Just LoginReq) LoginResp
loginUser = MethodPost Proxy ("v2" <//> "user" <//> "auth")

Server (GHC):

import ApiDef
import Web.Spock

api :: Application ()
api =
    defEndpoint loginUser loginHandler

loginHandler :: LoginReq -> Action LoginResp
loginHandler r =
    do auth <- runDB $ \conn -> authUser conn (lr_username r) (lr_password r)
       case auth of
         Just user ->
             do modifySession $ \sess -> sess { s_user = Just (u_id user) }
                pure LoginOkay
         Nothing ->
             pure LoginFailed

Client (GHCJS):

import ApiDef
import Web.Spock.Client

do Just res <- callEndpoint loginUser (LoginReq user pass)
     -- ...

Submit to TechEmpower benchmarks

I saw some benchmarks against a few other Haskell frameworks, but it might be a good idea to submit something to the TechEmpower benchmarks, both to compare Spock against non-Haskell frameworks and also to get Spock more visibility.

Custom http verb for routes (NOTIFY)

I am trying to interface with a upnp callback protocol and it seems to be making a NOTIFY request.
How can i capture this route.
It seems there is no way to use a route outside of the StdMethod type.

Thanks

Simple example handling a POST

Hi,
been playing around with spock for the past two weeks for an internal PoC project for some RESTful api services.

I can't seem to find an easy example for a POST with its urlencoded body.

I basically need to handle curl -XPOST localhost:3000/examples/form -d "name=Jonas" -d "age=35"

Any hint or suggestion on where to look for a working example or documentation page?

Thanks!

Release 0.11

  • Update Spock-digestive
  • Update Spock-worker
  • Update the funblog example project to use the current Spock head
  • Migrate/Test some projects to Spock 0.11 to make sure the API remained stable
  • Write/Gather example applications that demonstrate new features
  • Write a Blogpost
  • Upload
  • Announce

Wildcard route matching

It should be possible to match against a request that starts with a prefix, for example:

wildcard GET "app" $ doStuff

should match all routes that start with /app/....

Questions:

  • What should we do with the rest of the url? Should we pass it to the handler?

Original:

I would need to catch a whole subtree to run an action. To catch the whole "/app/...", I tried this:

subcomponent "app" $ hookAny GET $ const servePage

However, that doesn't seem to work as expected - instead of 404, I get the servePage result when any non-handled page is requested - even outside of "/app". Is this an error or is it expected to behave this way? What is the proper way to do this?

Installing on ghc 7.10.1 fails

I get this result:

cabal install spock
Resolving dependencies...
Configuring Spock-0.7.7.0...
Building Spock-0.7.7.0...
Failed to install Spock-0.7.7.0
Build log ( /Users/raguay/.cabal/logs/Spock-0.7.7.0.log ):
Configuring Spock-0.7.7.0...
Building Spock-0.7.7.0...
Preprocessing library Spock-0.7.7.0...
[ 1 of 10] Compiling Web.Spock.Internal.Wire ( src/Web/Spock/Internal/Wire.hs, dist/build/Web/Spock/Internal/Wire.o )

src/Web/Spock/Internal/Wire.hs:16:1: Warning:
Module ‘Control.Monad.Error’ is deprecated:
Use Control.Monad.Except instead

src/Web/Spock/Internal/Wire.hs:83:10: Warning:
In the use of type constructor or class ‘Error’
(imported from Control.Monad.Error, but defined in Control.Monad.Trans.Error):
Deprecated: "Use Control.Monad.Trans.Except instead"

src/Web/Spock/Internal/Wire.hs:83:10: Warning:
In the use of type constructor or class ‘Error’
(imported from Control.Monad.Error, but defined in Control.Monad.Trans.Error):
Deprecated: "Use Control.Monad.Trans.Except instead"

src/Web/Spock/Internal/Wire.hs:88:31: Warning:
In the use of type constructor or class ‘ErrorT’
(imported from Control.Monad.Error, but defined in Control.Monad.Trans.Error):
Deprecated: "Use Control.Monad.Trans.Except instead"

src/Web/Spock/Internal/Wire.hs:188:21: Warning:
In the use of ‘runErrorT’
(imported from Control.Monad.Error, but defined in Control.Monad.Trans.Error):
Deprecated: "Use Control.Monad.Trans.Except instead"
[ 2 of 10] Compiling Web.Spock.Internal.Util ( src/Web/Spock/Internal/Util.hs, dist/build/Web/Spock/Internal/Util.o )
[ 3 of 10] Compiling Web.Spock.Internal.CoreAction ( src/Web/Spock/Internal/CoreAction.hs, dist/build/Web/Spock/Internal/CoreAction.o )

src/Web/Spock/Internal/CoreAction.hs:204:39:
Ambiguous occurrence ‘defaultTimeLocale’
It could refer to either ‘Data.Time.defaultTimeLocale’,
imported from ‘Data.Time’ at src/Web/Spock/Internal/CoreAction.hs:26:1-16
(and originally defined in ‘time-1.5.0.1:Data.Time.Format.Locale’)
or ‘System.Locale.defaultTimeLocale’,
imported from ‘System.Locale’ at src/Web/Spock/Internal/CoreAction.hs:30:1-20
cabal: Error: some packages failed to install:
Spock-0.7.7.0 failed during the building phase. The exception was:
ExitFailure 1

I am running ghc 7.10.1 on a Macbook Air OS X 10.10.3.

How does files/UploadedFile work

Hi,

I am wondering how files and UploadedFile work, especially, where the files "/tmp/webenXXXX.buf" is stored in the filesystem.
I was trying to decipher the src in Spock but it I don't have a lot of knowledge of WAI. Can someone explain/point me to the right doc or src if no doc is available?

Thanks!

param not finding params

      post "/login" $ do
        params >>= liftIO . putStrLn . show
        username <- param' "username"
        ...

For a certain request, this prints [("username","asdf")] to the console, but param' yields a 500 ("Missing parameter username"). This seems incorrect?

crash in clearAllSessions and impossible to disconnect users

Hi,
I'm using Spock on Windows and it crashes when I call clearAllSessions at line 144 of SessionManager.hs.

Also I don't manage to disconnect a user with sessionRegenerateId. Subsequent calls to withBasicAuthData still arrive with the previous username and password. When I delete the cookies on the browser side, withBasicAuthData then comes with Nothing as its argument.

Thanks,
Vincent

More domain-specific contexts?

Hi Spock team,

I'm really enjoying the context features that have been added in 0.9.*, but am finding the use of Data.HVect as the implementation (at least in its raw state) a bit jarring. I appreciate the desire for code re-use, but was wondering if you would consider implementing/accepting PRs to improve the situation or simply implement these features within Spock itself? Two possible approaches I see are:

  • Wrap what is (in my opinion) the common use case of fmap findFirst getContext (i.e. retrieve the context and then extract some type-identified piece of it) so that consumers (writers of prehooks could be catered for too but it's perhaps less important) don't need to know about HVects and type-level '(:) etc. but could instead write something like:
--  Spock defines:
class InContext cxt a where
  fromContext :: MonadIO m => ActionCtxT cxt m a                                    

instance (cxt ~ HVect cts, ListContains n a cts)                   
      =>  InContext cxt a where                                                   

  fromContext                                                         
    = findFirst <$> getContext   

--  Consumers can now write:
f :: InContext cxt Foo => ActionCtxT cxt m a
f
  = do
      foo <- fromContext
      g foo
      ...

g :: Foo -> ActionCtxT cxt m a
...
  • Go the whole hog and reimplement ListContains, HVect etc. to be more Spock-specific -- e.g. InContext and Context could be neater names and might be defined e.g. ala the monad-classes package:
proxy :: Proxy k                                                                   
proxy = undefined                                                                      

data Context (as :: [*]) where                                                     
  EmptyContext :: Context '[]                                                      
  StackedContext :: a -> Context as -> Context (a ': as)                           

type family IndexOf (a :: k) (as :: [k]) :: Nat where                              
  IndexOf a (a ': as) = 'Zero                                                      
  IndexOf a (b ': as) = 'Succ (IndexOf a as)                                       

class InContextN (n :: Nat) cxt a where                                         
  fromContextN :: MonadIO m => proxy n -> ActionCtxT cxt m a                    

instance (cxt ~ (a ': as)) => InContextN 'Zero cxt a where                      
  --  Base case of what is currently getContext
  fromContextN _                                                                
    = undefined              

instance (InContextN n cxt a, scxt ~ (b ': cxt))                                
      =>  InContextN ('Succ n) scxt a where                                     

  --  Recursive case of what is currently getContext       
  fromContextN _                                                                
    = undefined                                     

type InContext cxt a                                                            
  = InContextN (IndexOf a cxt) cxt a

fromContext :: forall a cxt m.(InContext cxt a, MonadIO m)                      
            => ActionCtxT cxt m a                                               

fromContext                                                                     
  = fromContextN (proxy :: Proxy (IndexOf a cxt)) 

These ideas might both be terrible and are of cause based on just my opinions, but I'd be interested to hear the team's thoughts. For the record, I'm using the first solution in my current project and it's working fairly nicely.

Mailing list, newsgroup, or bulletin board forum for Spock?

I find Spock a very elegant and well designed framework that leverages Haskell very well. As someone fairly new to the Haskell language---and to web programming in general---I have lots of questions. Is there a mailing list, a news group, or forum to discuss Spock? Or can one be created for it?

There's so much to learn and discover, and I think I can get faster if there were more support for newcomers.

Why is Spock faster than Scotty?

Hi,
Are there any core design choices that make Spock faster than Scotty? Is there something special I should look for when I try to start grokking the source?

Thanks for your help!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.