Rack::Schema
Validate your application's responses against JSON Schemas.
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:
# 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
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). 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:
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:
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:
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?
- 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.