pd/rack-schema

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# Rack::Schema

[![Gem Version](https://badge.fury.io/rb/rack-schema.svg)](http://badge.fury.io/rb/rack-schema)
[![Build Status](https://travis-ci.org/pd/rack-schema.svg?branch=master)](https://travis-ci.org/pd/rack-schema)
[![Dependency Status](https://gemnasium.com/pd/rack-schema.svg)](https://gemnasium.com/pd/rack-schema)
[![Code Climate](https://codeclimate.com/github/pd/rack-schema.png)](https://codeclimate.com/github/pd/rack-schema)
[![Coverage Status](https://img.shields.io/coveralls/pd/rack-schema.svg)](https://coveralls.io/r/pd/rack-schema?branch=master)

Validate your application's responses against [JSON Schemas][json-schema].

## Installation

Add this line to your application's Gemfile:

    gem 'rack-schema'

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install rack-schema

## Usage
Mount `Rack::Schema` as middleware in one of the normal manners:

~~~~ruby
# using config.ru:
use Rack::Schema
run MyApp

# or application.rb:
config.middleware.use Rack::Schema
~~~~

Your application can now return an HTTP [Link header][link-header]
with a `rel` attribute value of `describedby`, and `Rack::Schema` will
automatically attempt to validate responses against the specified
schema (using the [json-schema gem][hoxworth]). An example `Link`
header:

    Link: <http://example.com/schemas/response>; rel="describedby"

If your schema applies only to a part of the JSON response, you can
use the `anchor` attribute to specify a JSON path to the relevant value:

    Link: <http://example.com/schemas/widget>; rel="describedby"; anchor="#/widget"

This is actually a mis-use of the `anchor` attribute, which would
typically be used to specify an anchor within the *linked* document,
rather than the document being described. JSON schemas already support
the use of the hash fragment on its URI, however, so I've
re-appropriated it. Suggestions for a more compliant tactic are
welcome.

If your response is actually a collection of objects that should all
validate against the same schema, use the `collection` attribute:

    # Assert that the response is an array, and each object within it is a valid widget.
    Link: <http://example.com/schemas/widget>; rel="describedby"; collection="collection"

    # Assert that the object at '#/widgets' is an array, and each object within it is a valid widget.
    Link: <http://example.com/schemas/widget>; rel="describedby"; anchor="#/widgets"; collection="collection"

If the `Link` header contains multiple applicable links, they will
all be used to validate the response:

    # Assert that '#/teams' is an array of valid teams, and '#/score' is a valid score.
    Link: <http://example.com/schemas/team>; rel="describedby"; anchor="#/teams"; collection="collection",
          <http://example.com/schemas/score>; rel="describedby"; anchor="#/score"

## Configuration

### Validate Schemas
By default, `rack-schema` will also instruct the validator to validate
your schema itself *as* a schema. To disable that behavior:

~~~~ruby
use Rack::Schema, validate_schemas: false
~~~~

### Swallow Links
If you are running the `rack-schema` response validator in a
production environment -- which you probably *shouldn't* be doing --
and you don't want to actually expose the `describedby` link header
entries to the world, you can tell `rack-schema` to remove them from
the responses after using them:

~~~~ruby
use Rack::Schema, swallow_links: true
~~~~

With `swallow_links` on, only the *describedby* links will be removed;
your pagination or similar links will not be disturbed.

### Error Handler
By default, `rack-schema` will raise a `ValidationError` if it encounters
any errors in your response JSON. If that's not your bag, you can define
a different error handler by providing a block:

~~~ruby
use Rack::Schema do |errors, env, (status, headers, body)|
  # Preferably, use a less useless error message.
  my_logger.warn("JSON response did not match schema!")
end
~~~


## Potential Features?

1. Validate incoming JSON bodies, but I just don't need that right now.
   And it's unclear how we'd determine what schemas to use, or what we'd
   do with the errors.

## See Also

1. [HTTP Link Header][link-header]
2. [json-schema gem][hoxworth]

[json-schema]: http://json-schema.org
[link-header]: http://tools.ietf.org/html/rfc5988#section-5
[hoxworth]: https://github.com/hoxworth/json-schema