# 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: ; 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: ; 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: ; rel="describedby"; collection="collection" # Assert that the object at '#/widgets' is an array, and each object within it is a valid widget. Link: ; 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: ; rel="describedby"; anchor="#/teams"; collection="collection", ; 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