GithubHelp home page GithubHelp logo

hvr / magicbane Goto Github PK

View Code? Open in Web Editor NEW

This project forked from valpackett/magicbane

0.0 2.0 0.0 21 KB

A web framework that integrates Servant, ClassyPrelude, EKG, fast-logger, wai-cli…

License: The Unlicense

Haskell 100.00%

magicbane's Introduction

An object appears at your feet! The voice of Anhur rings out: "Use my gift wisely!" a - an athame named Magicbane.

magicbane Hackage Build Status unlicense

Magicbane is a Haskell framework for developing ops-friendly, high-performance, RESTful web services.

Okay, that's Dropwizard's tagline. But just like Dropwizard in the Java world, Magicbane combines the best available Haskell libraries to provide a complete web development experience that reduces bikeshedding, wheel reinvention and the number of import lines. Hopefully :)

In particular, Magicbane combines the following libraries:

  • classy-prelude for the Prelude.
  • Warp for HTTP.
  • Servant for REST. It lets you describe web APIs with expressive type system features and implement request handlers with simple functions. Actually somewhat similar to JAX-RS/Jersey, but instead of annotations we have types, because it's Haskell instead of Java. The main feature of Magicbane is an easy way to add stuff (okay, let's call it "modules") on top of Servant.
  • Aeson for JSON.
  • data-has for extending the app context with services (modules). That thing remotely resembles dependency injection. But it's really cool!
  • envy for configuration. Store config in environment variables!
  • fast-logger+monad-logger for logging. It works. It's fast. And it even lets you see what line of code produced a log message.
  • EKG+monad-metrics for metrics. monad-metrics lets you easily measure things in your application: just use label/counter/distribution/gauge/timed in your handlers. The EKG ecosystem has backends for InfluxDB, Carbon (Graphite), statsd, Prometheus and others… And a simple local web server for development.
  • refined for validation. Why use functions for input validation when you can use types? Magicbane integrates refined with Aeson, so you can write things like count ∷ Refined Positive Int in your data type definitions and inputs that don't satisfy the constraints will be rejected when input is processed.
  • http-client(-tls) for, well, making HTTP requests. Most high level HTTP client libraries are built on top of that. Magicbane provides a small composable interface based on http-conduit, which lets you e.g. stream the response body directly into an HTML parser.
  • http-link-header for the HTTP Link header, unsurprisingly.
  • wai-cli for starting Warp. Why write the same stuff in the main function for every new app when you can just use this one. It supports stuff people usually forget to implement there, like UNIX domain sockets, socket activation and graceful shutdown.

Not part of Magicbane, but recommended:

Magicbane was extracted from Sweetroll.

Usage

Here's a hello world service. Just a simple file you can launch with stack script! (Don't use stack script in production though, use proper stack builds, with optimizations and the threaded runtime.)

#!/usr/bin/env stack
{- stack runghc --package magicbane -}
{-# LANGUAGE NoImplicitPrelude, OverloadedStrings, UnicodeSyntax, DataKinds, TypeOperators, TemplateHaskell #-}
import Magicbane

type HelloRoute = "hello" :> QueryParam "to" Text :> Get '[PlainText] Text
type ExampleAPI = HelloRoute
exampleAPI = Proxy  Proxy ExampleAPI

hello  Maybe Text  BasicApp Text
hello x = do
  $logInfo$ "Saying hello to " ++ tshow x
  return $ "Hello " ++ (fromMaybe "anonymous" x) ++ "!"

main = do
  ctx  newBasicContext
  defWaiMain $ magicbaneApp exampleAPI EmptyContext ctx hello

This defines an API that consists of just one endpoint, /hello?to=someone, that does exactly what it says on the tin. Looks like a normal Servant app, but the handler is defined as a BasicApp action. What's that?

That's just an example context for simple apps:

type BasicContext = (ModHttpClient, ModLogger)
type BasicApp α = MagicbaneApp BasicContext α

Okay, what's MagicbaneApp?

newtype MagicbaneApp β α = MagicbaneApp {
  unMagicbaneApp  ReaderT β (ExceptT ServantErr IO) α }

It's Servant, wrapped in a ReaderT! Just a wrapper that provides a context. Combined with data-has, this makes it possible to have a beautifully extensible context.

Let's make our own context instead of using the basic one:

#!/usr/bin/env stack
{- stack runghc --package magicbane -}
{-# LANGUAGE NoImplicitPrelude, OverloadedStrings, UnicodeSyntax, DataKinds, TypeOperators, TemplateHaskell #-}
import Magicbane

type MyAppContext = (ModLogger, ModMetrics)
type MyApp = MagicbaneApp MyAppContext

type HelloRoute = "hello" :> QueryParam "to" Text :> Get '[PlainText] Text
type ExampleAPI = HelloRoute
exampleAPI = Proxy  Proxy ExampleAPI

hello  Maybe Text  MyApp Text
hello x = timed "hello" $ do
  $logInfo$ "Saying hello to " ++ tshow x
  return $ "Hello " ++ (fromMaybe "anonymous" x) ++ "!"

main = do
  (_, modLogg)  newLogger $ LogStderr defaultBufSize
  metrStore  serverMetricStore <$> forkMetricsServer "0.0.0.0" 8800
  metrWai  registerWaiMetrics metrStore
  modMetr  newMetricsWith metrStore
  let ctx = (modLogg, modMetr)
  defWaiMain $ magicbaneApp exampleAPI EmptyContext ctx hello

Now we have metrics and logging instead of HTTP client and logging!

See the examples directory for more examples.

Development

Use stack to build.

$ stack build

Contributing

Please feel free to submit pull requests!

By participating in this project you agree to follow the Contributor Code of Conduct.

License

This is free and unencumbered software released into the public domain.
For more information, please refer to the UNLICENSE file or unlicense.org.

(However, the dependencies are not all unlicense'd!)

magicbane's People

Contributors

valpackett avatar

Watchers

Herbert Valerio Riedel avatar James Cloos avatar

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.