Skip to content

A Go framework for building JSON web services inspired by Dropwizard

License

Notifications You must be signed in to change notification settings

treetopllc/go-tigertonic

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tiger Tonic

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: http://godoc.org/github.com/rcrowley/go-tigertonic

Development mailing list: https://groups.google.com/forum/#!forum/tigertonic-dev

Users mailing list: https://groups.google.com/forum/#!forum/tigertonic-users

IRC: #tigertonic on irc.freenode.net

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 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.

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.

tigertonic.Logged 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.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.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.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.

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("GET", "/stuff", tigertonic.Marshaled(tigertonic.Timed(myHandler, "myHandler", nil)))
tigertonic.NewServer(":8000", tigertonic.Logged(mux, nil)).ListenAndServe()

Ready for more? See the full example. 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:

About

A Go framework for building JSON web services inspired by Dropwizard

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published