Skip to content

tclem/twirp-haskell

Folders and files

NameName
Last commit message
Last commit date

Latest commit

80cbacf · Jan 6, 2023
Jan 6, 2023
Sep 27, 2019
Jan 4, 2023
Oct 1, 2019
Nov 23, 2020
Nov 23, 2020
Sep 26, 2020
Feb 7, 2019
Nov 23, 2020
Feb 14, 2019
Jan 4, 2023
Feb 7, 2019
Nov 6, 2019
Nov 23, 2020
Nov 23, 2020
Jan 4, 2023

Repository files navigation

twirp-haskell

Very, very alpha implementation of Twirp service generation for Haskell.

This project provides a number of things:

  1. A protoc plugin for generating a Haskell Twirp service (based on Servant) for Services defined in a proto file.
  2. A haskell library, twirp for quickly serving up the generated application.

It requires the use of proto-lens to generate haskell datatypes from proto messages.

An example, end-to-end application is included in app.

Requirements

  1. Install protoc (e.g., brew install protoc)
  2. Install the required protoc plugins:
    • cabal install proto-lens-protoc
    • go get github.com/tclem/twirp-haskell/protoc-gen-twirp_haskell
    • go get github.com/tclem/proto-lens-jsonpb/protoc-gen-jsonpb_haskell

Usage

Use the protoc plugin to generate a twirp service and associated protobuf types from a proto file.

protoc -I=. --proto_path=./proto \
  --plugin=protoc-gen-haskell=`which proto-lens-protoc`
  --haskell_out=./app \
  --jsonpb_haskell_out=./app \
  --plugin=protoc-gen-twirp_haskell=./script/run-twirp_haskell
  --twirp_haskell_out=./app/Twirp/Example/Haberdasher \
  haberdasher.proto

The result is a couple of files that describe your service. First, here are the types that define a Servant API:

-- Code generated by protoc-gen-twirp_haskell 0.1.0, DO NOT EDIT.
{-# LANGUAGE TypeOperators #-}
module Twirp.Example.Haberdasher.Haberdasher where

import Servant
import Twirp

import Proto.Haberdasher

--  This is an example set of twirp services.

type HaberdasherAPI
  =    "twirp" :> "twirp.example.haberdasher.Haberdasher" :> HaberdasherService
  :<|> "twirp" :> "twirp.example.haberdasher.Health" :> HealthService

--  Haberdasher service makes hats for clients.
type HaberdasherService
  --  MakeHat produces a hat of mysterious, randomly-selected color!
  =    "MakeHat" :> ReqBody [Protobuf, JSON] Size :> Post '[Protobuf, JSON] Hat
  --  Get paid
  :<|> "GetBill" :> ReqBody [Protobuf, JSON] Hat :> Post '[Protobuf, JSON] Bill

--  Health check service
type HealthService
  =    "Check" :> ReqBody [Protobuf, JSON] Ping :> Post '[Protobuf, JSON] Pong

The datatypes are defined in Proto.Haberdasher.

Plugging this into an existing warp/wai server is straightforward. See app/Main.hs for the full details:

type RequestID = String

type API
  = Header "X-Request-Id" RequestID
  :> HaberdasherAPI

main :: IO ()
main = run 8003 app

app :: Application
app = twirpErrorResponses apiApp

apiApp :: Application
apiApp = serve (Proxy :: Proxy API) server

server :: Server API
server _requestID = (makeHat :<|> getBill) :<|> checkHealth