Go-json-rest

A quick and easy way to setup a RESTful JSON API

Go-Json-Rest

A quick and easy way to setup a RESTful JSON API

Go-Json-Rest is a thin layer on top of net/http that helps building RESTful JSON APIs easily. It provides fast and scalable request routing using a Trie based implementation, helpers to deal with JSON requests and responses, and middlewares for functionalities like CORS, Auth, Gzip, Status ...

Implemented as a net/http Handler. This standard interface allows combinations with other Handlers.

Test package to help writing tests for your API.

Monitoring statistics inspired by Memcached.

Install

This package is "go-gettable", just do:

go get github.com/ant0ine/go-json-rest/rest

Vendoring

The recommended way of using this library in your project is to use the "vendoring" method,
where this library code is copied in your repository at a specific revision.
This page is a good summary of package management in Go.

Applications

Common use cases, found in many applications.

API and static files

Combine Go-Json-Rest with other handlers.

api.MakeHandler() is a valid http.Handler, and can be combined with other handlers.
In this example the api handler is used under the /api/ prefix, while a FileServer is instantiated under the /static/ prefix.

ForceSSL

Demonstrate how to use the ForceSSL Middleware to force HTTPS on requests to a go-json-rest API.

For the purposes of this demo, we are using HTTP for all requests and checking the X-Forwarded-Proto header to see if it is set to HTTPS (many routers set this to show what type of connection the client is using, such as Heroku). To do a true HTTPS test, make sure and use http.ListenAndServeTLS with a valid certificate and key file.

Additional documentation for the ForceSSL middleware can be found here.

Non JSON payload

Exceptional use of non JSON payloads.

The ResponseWriter implementation provided by go-json-rest is designed
to build JSON responses. In order to serve different kind of content,
it is recommended to either:
a) use another server and configure CORS
(see the cors/ example)
b) combine the api.MakeHandler() with another http.Handler
(see api-and-static/ example)

That been said, exceptionally, it can be convenient to return a
different content type on a JSON endpoint. In this case, setting the
Content-Type and using the type assertion to access the Write method
is enough. As shown in this example.

Graceful Shutdown

This example uses https://github.com/tylerb/graceful to try to be nice with the clients waiting for responses during a server shutdown (or restart).
The HTTP response takes 10 seconds to be completed, printing a message on the wire every second.
10 seconds is also the timeout set for the graceful shutdown.
You can play with these numbers to show that the server waits for the responses to complete.

Deprecating the ResourceHandler

V3 is about deprecating the ResourceHandler in favor of a new API that exposes the Middlewares. As a consequence, all the Middlewares are now public, and the new Api object helps putting them together as a stack. Some default stack configurations are offered. The router is now an App that sits on top of the stack of Middlewares. Which means that the router is no longer required to use Go-Json-Rest.

Migration guide from v2 to v3

V3 introduces an API change (see Semver). But it was possible to maintain backward compatibility, and so, ResourceHandler still works.
ResourceHandler does the same thing as in V2, but it is now considered as deprecated, and will be removed in a few months. In the meantime, it logs a
deprecation warning.

How to map the ResourceHandler options to the new stack of middlewares ?

EnableGzip bool: Just include GzipMiddleware in the stack of middlewares.

DisableJsonIndent bool: Just don't include JsonIndentMiddleware in the stack of middlewares.

EnableStatusService bool: Include StatusMiddleware in the stack and keep a reference to it to access GetStatus().

EnableResponseStackTrace bool: Same exact option but moved to RecoverMiddleware.

EnableRelaxedContentType bool: Just don't include ContentTypeCheckerMiddleware.

OuterMiddlewares []Middleware: You are now building the full stack, OuterMiddlewares are the first in the list.

PreRoutingMiddlewares []Middleware: You are now building the full stack, OuterMiddlewares are the last in the list.

Logger *log.Logger: Same option but moved to AccessLogApacheMiddleware and AccessLogJsonMiddleware.

LoggerFormat AccessLogFormat: Same exact option but moved to AccessLogApacheMiddleware.

DisableLogger bool: Just don't include any access log middleware.

ErrorLogger *log.Logger: Same exact option but moved to RecoverMiddleware.

XPoweredBy string: Same exact option but moved to PoweredByMiddleware.

DisableXPoweredBy bool: Just don't include PoweredByMiddleware.

Version 2 release notes

Middlewares, the notion of middleware is now formally defined. They can be setup as global pre-routing Middlewares wrapping all the endpoints, or on a per endpoint basis.
In fact the internal code of go-json-rest is itself implemented with Middlewares, they are just hidden behind configuration boolean flags to make these very common options even easier to use.

A new ResponseWriter. This is now an interface, and allows Middlewares to wrap the writer. The provided writer implements, in addition of rest.ResponseWriter, http.Flusher, http.CloseNotifier, http.Hijacker, and http.ResponseWriter. A lot more Go-ish, and very similar to net/http.

The AuthBasic and CORS Middlewares have been added. More to come in the future.

Faster, more tasks are performed at init time, and less for each request.

The import path has changed to github.com/ant0ine/go-json-rest/rest

rest.ResponseWriter is now an interface

This change allows the ResponseWriter to be wrapped, like the one of the net/http package.
This is much more powerful, and allows the creation of Middlewares that wrap the writer. The gzip option, for instance, uses this to encode the payload (see gzip.go).

This:

func (w *rest.ResponseWriter, req *rest.Request) {
...
}

has to be changed to this:

func (wrest.ResponseWriter, req *rest.Request) {
...
}

SetRoutes now takes pointers to Route

Instead of copying Route structures everywhere, pointers are now used. This is more elegant, more efficient, and will allow more sophisticated Route manipulations in the future (like reverse route resolution).

The notion of Middleware is now formally defined

Code using PreRoutingMiddleware will have to be adapted to provide a list of Middleware objects.
See the Basic Auth example.

Flush(), CloseNotify() and Write() are not directly exposed anymore

They used to be public methods of the ResponseWriter. The implementation is still there but a type assertion of the corresponding interface is now necessary.
Regarding these features, a rest.ResponseWriter now behaves exactly as the http.ResponseWriter implementation provided by net/http.