firefly-example (empty) → 0.1.0.0
raw patch · 5 files changed
+205/−0 lines, 5 filesdep +aesondep +basedep +blaze-htmlsetup-changed
Dependencies added: aeson, base, blaze-html, firefly, mtl, text, wai
Files
- LICENSE +30/−0
- README.md +104/−0
- Setup.hs +2/−0
- app/Main.hs +38/−0
- firefly-example.cabal +31/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Chris Penner (c) 2017++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Chris Penner nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,104 @@+# Firefly++- [Example App](./firefly-example/app/Main.hs)+- [Hackage Docs](http://hackage.haskell.org/package/firefly-0.1.0.0/docs/Web-Firefly.html)++Firefly is dead simple http framework written in Haskell.++It strives for simplicity in implementation (and in use).+It's great for people learning Haskell, fiddling with Monads,+or who just need a really simple server for something.++Here's the minimal app:++```haskell+{-# language OverloadedStrings #-}+import Web.Firefly+import qualified Data.Text as T++main :: IO ()+main = run 3000 app++app :: App ()+app = do+ route "/hello" (return "hello" :: Handler T.Text)+```++Just that easy!++Check out the [Example App](./firefly-example/app/Main.hs) for more!++Specify your routes using regex patterns, the first one which matches will run.++`Handler` is a monad with access to the incoming request. You can access parts+of it using helpers, then return a response.++Here are some valid response types and their inferred Content-Type++- `Data.Text.Text`: `text/plain` +- `Data.Aeson.Value`: `application/json` +- `Blaze.Html.Html`: `text/html`++There are more in `Web.Firefly.Response`.++You can specify your status code using `(body, Status)` where body is any of+the above types and Status is an Integer status code.++Or, add headers too with `(body, Status, HeaderMap)` where `HeaderMap` is a map+of names to values.++## Examples++Let's write some more interesting handlers:++```haskell+hello :: App T.Text+hello = do+ -- | Get the 'name' query param from the url, if it doesn't exist use 'Stranger'+ name <- getQuery "name"+ -- If we just return some Text the response will be status 200 with a Content-Type of "text/plain"+ return $ "Hello " <> fromMaybe "Stranger" name+```++Here's an example of responding with JSON:++```haskell+import Data.Aeson (ToJSON, FromJSON)+import GHC.Generics (Generic)+import qualified Data.Text as T+import qualified Network.Wai as W+import Web.Firefly++data User = User+ { username::T.Text+ , age::Int+ } deriving (Generic, ToJSON, FromJSON) -- Derive JSON instances++-- A reguler 'ol user+steve :: User+steve = User{username="Steve", age=26}++-- | Get a user by username+getUser :: App W.Response+getUser = do+ uname <- getQuery "username"+ return $ case uname of+ -- The Json constructor signals to serialize the value and respond as "application/json"+ Just "steve" -> toResponse $ Json steve + Just name -> toResponse ("Couldn't find user: " `mappend` name, notFound404)+ Nothing -> toResponse ("Please provide a 'username' parameter" :: T.Text, badRequest400)+```++## Should I/Shouldn't I use Firefly?++You should use Firefly if:++- You're intimidated by monads and want to learn more!+- You want to write a hobby project+- You like understanding the stack you're working with (The whole lib is ~300 lines without docs/imports)++Don't use Firefly if:++- You'll have thousands of users+- You want the most performant server possible+- You want to have lots of helper libs available
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ app/Main.hs view
@@ -0,0 +1,38 @@+{-# language OverloadedStrings #-}+{-# language DeriveAnyClass #-}+{-# language DeriveGeneric #-}+module Main where++import Data.Aeson (ToJSON, FromJSON)+import GHC.Generics (Generic)+import qualified Data.Text as T+import qualified Network.Wai as W+import Web.Firefly++-- | The Main app; this runs our app on port 3000 with logger middleware+main :: IO ()+main = run 3000 app++app :: App ()+app = do+ route "/users" getUser++data User = User+ { username::T.Text+ , age::Int+ } deriving (Generic, ToJSON, FromJSON) -- Derive JSON instances++-- A reguler 'ol user+steve :: User+steve = User{username="Steve", age=26}++-- | Get a user by username+getUser :: App W.Response+getUser = do+ uname <- getQuery "username"+ return $ case uname of+ -- | We can use 'toResponse' to convert differing response types+ -- to a common Wai Response.+ Just "steve" -> toResponse $ Json steve -- If you just provide a body the status defaults to 200+ Just name -> toResponse ("Couldn't find user: " `mappend` name, notFound404)+ Nothing -> toResponse ("Please provide a 'username' parameter" :: T.Text, badRequest400)
+ firefly-example.cabal view
@@ -0,0 +1,31 @@+name: firefly-example+version: 0.1.0.0+synopsis: A simple example using Firefly+-- description:+homepage: https://github.com/ChrisPenner/Firefly#readme+license: BSD3+license-file: LICENSE+author: Chris Penner+maintainer: christopher.penner@gmail.com+copyright: 2017 Chris Penner+category: Web+build-type: Simple+extra-source-files: README.md+cabal-version: >=1.10++executable firefly-example-exe+ hs-source-dirs: app+ main-is: Main.hs+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends: base >= 4.7 && < 5+ , firefly+ , text+ , aeson+ , blaze-html+ , mtl+ , wai+ default-language: Haskell2010++source-repository head+ type: git+ location: https://github.com/ChrisPenner/Firefly