class Rack::Schema

Constants

VERSION
ValidationError

Public Class Methods

new(app, options = {}, &handler) click to toggle source
# File lib/rack/schema.rb, line 10
def initialize(app, options = {}, &handler)
  @app = app

  @handler   = handler
  @handler ||= proc { |errors, env, (status, headers, body)|
    json = ''
    body.each { |s| json.concat s }
    raise ValidationError.new({ errors: errors, body: json }) if errors.any?
  }

  @options = {
    validate_schemas: true,
    swallow_links:    false
  }.merge(options)
end

Public Instance Methods

call(env) click to toggle source
# File lib/rack/schema.rb, line 26
def call(env)
  status, headers, body = @app.call(env)

  link_header  = LinkHeader.parse(headers['Link'])
  schema_links = link_header.links.select do |link|
    link.attrs['rel'] == 'describedby'
  end

  errors = validate(body, schema_links)
  swallow(headers, link_header) if swallow_links?
  response = [status, headers, body]
  @handler.call(errors, env, response) || response
end

Private Instance Methods

at_anchor(body, anchor) click to toggle source
# File lib/rack/schema.rb, line 68
def at_anchor(body, anchor)
  flat = ''
  body.each { |s| flat.concat s }

  return flat if anchor.nil? || anchor == '#' || anchor == '#/'

  fragments = anchor.sub(/\A#\//, '').split('/')
  fragments.reduce MultiJson.decode(flat) do |value, fragment|
    case value
    when Hash  then value.fetch(fragment, nil)
    when Array then value.fetch(fragment.to_i, nil)
    end
  end
end
swallow(headers, link_header) click to toggle source
# File lib/rack/schema.rb, line 59
def swallow(headers, link_header)
  link_header.links.reject! { |link| link.attrs['rel'] == 'describedby' }
  if link_header.links.any?
    headers['Link'] = link_header.to_s
  else
    headers.delete 'Link'
  end
end
validate(body, schema_links) click to toggle source
# File lib/rack/schema.rb, line 42
def validate(body, schema_links)
  schema_links.each_with_object [] do |link, acc|
    json = at_anchor(body, link.attrs['anchor'])

    errs = JSON::Validator.fully_validate link.href, json, {
      validate_schemas: @options[:validate_schemas],
      list: link.attrs.key?('collection')
    }

    acc.push [link.to_s, errs] if errs.any?
  end
end