firefly: A simple HTTP server framework

[ bsd3, library, web ] [ Propose Tags ] [ Report a vulnerability ]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1.0.0, 0.1.0.1, 0.1.1.0, 0.2.0.0, 0.2.1.0
Dependencies aeson (>=1.1), base (>=4.7 && <5), blaze-html (>=0.9), bytestring (>=0.10), case-insensitive (>=1.2), containers (>=0.5), cookie (>=0.4.2), http-types (>=0.9), mtl (>=2.2), regex-pcre (>=0.94), text (>=1.2), transformers (>=0.5), wai (>=3.2), warp (>=3.2) [details]
Tested with ghc ==8.2.1, ghc ==8.0.2
License BSD-3-Clause
Copyright 2017 Chris Penner
Author Chris Penner
Maintainer christopher.penner@gmail.com
Category Web
Home page https://github.com/ChrisPenner/firefly#readme
Source repo head: git clone https://github.com/ChrisPenner/firefly
Uploaded by ChrisPenner at 2017-12-03T21:46:33Z
Distributions NixOS:0.2.1.0
Downloads 3435 total (6 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2017-12-03 [all 1 reports]

Readme for firefly-0.2.1.0

[back to package description]

Firefly

Build Status

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 a simple app:

{-# language OverloadedStrings #-}
import Web.Firefly
import qualified Data.Text as T

main :: IO ()
main = run 3000 app

app :: App ()
app = do
  route "/hello" helloHandler

-- | Get the 'name' query param from the url, if it doesn't exist use 'Stranger'
helloHandler :: Handler T.Text
helloHandler = do
  name <- fromMaybe "Stranger" <$> getQuery "name"
  return $ "Hello " `T.append` name

Just that easy!

Check out the Example App 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:

Here's an example of responding with JSON:

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 
             -- We can use a tuple to pass a status alongside the response body
             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

Troubleshooting

pcre.h not found

Seeing something like this?

...stack/regex-pcre-0.94.4/Wrap.hsc:148:10: fatal error: 'pcre.h' file not found
    #include <pcre.h>
             ^~~~~~~~
    1 error generated.

Firefly uses regex; and requires certain c-libs to be installed. The easiest way to fix this is to install Nix:

Get Nix

or run:

curl https://nixos.org/nix/install | sh

Then add the following to your project's stack.yaml:

nix:
  enable: true
  packages:
    - libcxx
    - icu
    - gcc
    - ncurses
    - pcre
    - zlib