• Stars
    star
    995
  • Rank 44,215 (Top 0.9 %)
  • Language
    Go
  • License
    Other
  • Created about 11 years ago
  • Updated almost 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A Go framework for building JSON web services inspired by Dropwizard

Tiger Tonic

Build Status

A Go framework for building JSON web services inspired by Dropwizard. If HTML is your game, this will hurt a little.

Like the Go language itself, Tiger Tonic strives to keep features orthogonal. It defers what it can to the Go standard library and a few other packages.

Documentation

Articles and talks

Reference

http://godoc.org/github.com/rcrowley/go-tigertonic

Community

Synopsis

tigertonic.TrieServeMux

HTTP routing in the Go standard library is pretty anemic. Enter tigertonic.TrieServeMux. It accepts an HTTP method, a URL pattern, and an http.Handler or an http.HandlerFunc. Components in the URL pattern wrapped in curly braces - { and } - are wildcards: their values (which don't cross slashes) are added to the URL as u.Query().Get("name").

HandleNamespace is like Handle but additionally strips the namespace from the URL, making API versioning, multitenant services, and relative links easier to manage. This is roughly equivalent to http.ServeMux's behavior.

tigertonic.HostServeMux

Use tigertonic.HostServeMux to serve multiple domain names from the same net.Listener.

tigertonic.Marshaled

Wrap a function in tigertonic.Marshaled to turn it into an http.Handler. The function signature must be something like this or tigertonic.Marshaled will panic:

func myHandler(*url.URL, http.Header, *MyRequest) (int, http.Header, *MyResponse, error)

Request bodies will be unmarshaled into a MyRequest struct and response bodies will be marshaled from MyResponse structs.

Should you need to respond with an error, the tigertonic.HTTPEquivError interface is implemented by tigertonic.BadRequest (and so on for every other HTTP response status) that can be wrapped around any error:

func myHandler(*url.URL, http.Header, *MyRequest) (int, http.Header, *MyResponse, error) {
    return 0, nil, nil, tigertonic.BadRequest{errors.New("Bad Request")}
}

Alternatively, you can return a valid status as the first output parameter and an error as the last; that status will be used in the error response.

If the return type of a tigertonic.Marshaled handler interface implements the io.Reader interface the stream will be written directly to the requestor. A Content-Type header is required to be specified in the response headers and the Accept header for these particular requests can be anything.

Additionally, if the return type of the tigertonic.Marshaled handler implements the io.Closer interface the stream will be automatically closed after it is flushed to the requestor.

tigertonic.Logged, tigertonic.JSONLogged, and tigertonic.ApacheLogged

Wrap an http.Handler in tigertonic.Logged to have the request and response headers and bodies logged to standard output. The second argument is an optional func(string) string called as requests and responses are logged to give the caller the opportunity to redact sensitive information from log entries.

Wrap an http.Handler in tigertonic.JSONLogged to have the request and response headers and bodies logged to standard output as JSON suitable for sending to ElasticSearch, Flume, Logstash, and so on. The JSON will be prefixed with @json: . The second argument is an optional func(string) string called as requests and responses are logged to give the caller the opportunity to redact sensitive information from log entries.

Wrap an http.Handler in tigertonic.ApacheLogged to have the request and response logged in the more traditional Apache combined log format.

tigertonic.Counted and tigertonic.Timed

Wrap an http.Handler in tigertonic.Counted or tigertonic.Timed to have the request counted or timed with go-metrics.

tigertonic.CountedByStatus and tigertonic.CountedByStatusXX

Wrap an http.Handler in tigertonic.CountedByStatus or tigertonic.CountedByStatusXX to have the response counted with go-metrics with a metrics.Counter for each HTTP status code or family of status codes (1xx, 2xx, and so on).

tigertonic.First

Call tigertonic.First with a variadic slice of http.Handlers. It will call ServeHTTP on each in succession until the first one that calls w.WriteHeader.

tigertonic.If

tigertonic.If expresses the most common use of tigertonic.First more naturally. Call tigertonic.If with a func(*http.Request) (http.Header, error) and an http.Handler. It will conditionally call the handler unless the function returns an error. In that case, the error is used to create a response.

tigertonic.PostProcessed and tigertonic.TeeResponseWriter

tigertonic.PostProcessed uses a tigertonic.TeeResponseWriter to record the response and call a func(*http.Request, *http.Response) after the response is written to the client to allow post-processing requests and responses.

tigertonic.HTTPBasicAuth

Wrap an http.Handler in tigertonic.HTTPBasicAuth, providing a map[string]string of authorized usernames to passwords, to require the request include a valid Authorization header.

tigertonic.CORSHandler and tigertonic.CORSBuilder

Wrap an http.Handler in tigertonic.CORSHandler (using CORSBuilder.Build()) to inject CORS-related headers. Currently only Origin-related headers (used for cross-origin browser requests) are supported.

tigertonic.Configure

Call tigertonic.Configure to read and unmarshal a JSON configuration file into a configuration structure of your own design. This is mere convenience and what you do with it after is up to you.

tigertonic.WithContext and tigertonic.Context

Wrap an http.Handler and a zero value of any non-interface type in tigertonic.WithContext to enable per-request context. Each request may call tigertonic.Context with the *http.Request in progress to get a pointer to the context which is of the type passed to tigertonic.WithContext.

tigertonic.Version

Respond with a version string that may be set at compile-time.

Usage

Install dependencies:

sh bootstrap.sh

Then define your service. The working example may be a more convenient place to start.

Requests that have bodies have types. JSON is deserialized by adding tigertonic.Marshaled to your routes.

type MyRequest struct {
	ID     string      `json:"id"`
	Stuff  interface{} `json:"stuff"`
}

Responses, too, have types. JSON is serialized by adding tigertonic.Marshaled to your routes.

type MyResponse struct {
	ID     string      `json:"id"`
	Stuff  interface{} `json:"stuff"`
}

Routes are just functions with a particular signature. You control the request and response types.

func myHandler(u *url.URL, h http.Header, *MyRequest) (int, http.Header, *MyResponse, error) {
    return http.StatusOK, nil, &MyResponse{"ID", "STUFF"}, nil
}

Wire it all up in main.main!

mux := tigertonic.NewTrieServeMux()
mux.Handle("POST", "/stuff", tigertonic.Timed(tigertonic.Marshaled(myHandler), "myHandler", nil))
tigertonic.NewServer(":8000", tigertonic.Logged(mux, nil)).ListenAndServe()

Ready for more? See the full example which includes all of these handlers plus an example of how to use tigertonic.Server to stop gracefully. Build it with go build, run it with ./example, and test it out:

curl -H"Host: example.com" -sv "http://127.0.0.1:8000/1.0/stuff/ID"
curl -H"Host: example.com" -X"POST" -d'{"id":"ID","stuff":"STUFF"}' -sv "http://127.0.0.1:8000/1.0/stuff"
curl -H"Host: example.com" -X"POST" -d'{"id":"ID","stuff":"STUFF"}' -sv "http://127.0.0.1:8000/1.0/stuff/ID"
curl -H"Host: example.com" -sv "http://127.0.0.1:8000/1.0/forbidden"

WTF?

Dropwizard was named after http://gunshowcomic.com/316 so Tiger Tonic was named after http://gunshowcomic.com/338.

If Tiger Tonic isn't your cup of tea, perhaps one of these fine tools suits you:

More Repositories

1

go-metrics

Go port of Coda Hale's Metrics library
Go
3,421
star
2

goagain

Zero-downtime restarts in Go
Go
2,080
star
3

certified

Generate and manage an internal CA for your company
HTML
416
star
4

freight

A modern take on the Debian archive.
Shell
401
star
5

slack

Run a command; post it and its standard input, output, and error to Slack
Shell
109
star
6

json.sh

Pure-shell JSON parser
Shell
94
star
7

mustache.sh

Mustache in POSIX shell
Shell
81
star
8

gitpaid

The programmer's time tracker
Shell
64
star
9

django-twitterauth

Use Twitter for authentication in Django
Python
56
star
10

go-librato

Go client for Librato Metrics
Go
52
star
11

puppet-pip

DON'T USE THIS, USE PUPPET 2.7
Ruby
33
star
12

debra

build Debian packages
Shell
30
star
13

bashpress

Command-line blog engine
PHP
26
star
14

clint

Ruby command line argument parser
Ruby
19
star
15

opendns-fetchstats

Automatically fetch your OpenDNS Top Domains data
Visual Basic
18
star
16

rcrowley

My home directory and
JavaScript
18
star
17

puppet-related_nodes

An alternative to Puppet's exported resources
Ruby
16
star
18

pagerunit

A simple Nagios alternative made to look like unit tests.
Python
9
star
19

curvr

Automatic approximation of typical Photoshop actions
C++
8
star
20

archiso

Branch of https://projects.archlinux.org/archiso.git that supports unattended installation
Shell
6
star
21

manskeleton

build skeleton man paths
6
star
22

gas

Gas is a tiny prefork WSGI server and app for streaming static files through grep-, awk- and sed-like generators.
Python
6
star
23

dopploadr

A Flickr Uploadr extension for geotagging photos with Dopplr trips.
JavaScript
6
star
24

extending-puppet

Example code from my Extending Puppet talk
Ruby
6
star
25

puppet-python

5
star
26

fpf

Effing package format!
Shell
5
star
27

upstartable-nginx

Shell
5
star
28

go-shellac

Very experimental experiment into a declarative, strongly-typed API for executing shell commands from Go
Go
5
star
29

wheresmycar

Scrapes SF GIS to send alerts when I need to move my car for street cleaning
PHP
5
star
30

thrudb

Modifications to the Thrudb storage engine built on Thrift.
C++
4
star
31

sometimes

a PHP templating system
PHP
4
star
32

powncefs

A Fuse filesystem for your friends' files on Pownce
Python
4
star
33

hapimoney

Django implementation of HapiMoney
Python
3
star
34

puppet-crunkd

3
star
35

puppet-ruby

3
star
36

spoon

Spoon feeds HTML5 into Atom.
Python
3
star
37

go-bson

Not just a mirror of http://labix.org/gobson
Go
3
star
38

talk-django-puppet

Deploying Django with Puppet
JavaScript
3
star
39

puppet-sourceinstall

3
star
40

ssh-freeagent

Shell
3
star
41

nomblr

Python
3
star
42

puppet-virtualbox

Shell
3
star
43

httperf_modified

httperf with percentiles
Shell
3
star
44

talk-developing-operability

JavaScript
2
star
45

mixinstall

Manage read-only "mixed projects" within your own
2
star
46

countd

DON'T USE THIS. It's an old experiment and I wanted to free up some space in my GitHub account.
Python
2
star
47

lazy_redis

Maybe this is not a terrible idea?
Ruby
2
star
48

puppet-interfaces

Legacy repository for reclaiming some lost bug fixes
Ruby
2
star
49

talk-blueprint

JavaScript
2
star
50

slack-gmail-screener

Get mentioned in Slack when you receive email from noteworthy senders; don't be bothered with the rest
Python
2
star
51

talk-extending-puppet

JavaScript
2
star
52

krecipec

Ruby
2
star
53

python-givvy

Python bindings to the Givvy API
2
star
54

errforce

Utilities for working effectively with Go errors and UNIX errnos
Go
1
star
55

fsevents

Mirror of Yossef Mendelssohn's probably defunct fsevents gem
Ruby
1
star
56

puppet-iptables

Puppet
1
star
57

talk-securing-and-extending-puppet

Securing and Extending Puppet talk
JavaScript
1
star
58

talk-why-is-config-mgmt-ruby

JavaScript
1
star
59

rcrowley.github.com

1
star
60

puppet-php

1
star
61

talk-dep-mgmt-with-puppet

Dependency Management with Puppet lightning talk
JavaScript
1
star
62

gimmeservers

Python
1
star