Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only rescue errors explicitly #239

Merged
merged 2 commits into from
Dec 23, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Change Log
All notable changes to this project will be documented in this file.
Please keep to the changelog format described on [keepachangelog.com](http://keepachangelog.com).
This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Added
- Added a changelog

### Changed
- Made validation failures raise a `JSON::Schema::SchemaParseError` and data
loading failures a `JSON::Schema::JsonLoadError`
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ The Ruby JSON Schema library is meant to be a community effort, and as such, the

All individuals that have a pull request merged will receive collaborator access to the repository. Due to the restrictions on RubyGems authentication, permissions to release a gem must be requested along with the email desired to be associated with the release credentials.

Accepting changes to the JSON Schema library shall be made through the use of pull requests on GitHub. A pull request must receive at least two (2) "+1" comments from current contributors to the JSON Schema library before being accepted and merged. If a breaking issue and fix exists, please feel free to contact the project maintainer at [email protected] or @hoxworth for faster resolution.
Accepting changes to the JSON Schema library shall be made through the use of pull requests on GitHub. A pull request must receive at least two (2) "+1" comments from current contributors, and include a relevant changelog entry, before being accepted and merged. If a breaking issue and fix exists, please feel free to contact the project maintainer at [email protected] or @hoxworth for faster resolution.

Releases follow semantic versioning and may be made at a maintainer's discretion.
3 changes: 2 additions & 1 deletion lib/json-schema/attributes/formats/date.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ def self.validate(current_schema, data, fragments, processor, validator, options
if REGEXP.match(data)
begin
Date.parse(data)
rescue Exception
rescue ArgumentError => e
raise e unless e.message == 'invalid date'
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
end
else
Expand Down
14 changes: 6 additions & 8 deletions lib/json-schema/attributes/formats/date_time.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,16 @@ def self.validate(current_schema, data, fragments, processor, validator, options

begin
Date.parse(parts[0])
rescue Exception
rescue ArgumentError => e
raise e unless e.message == 'invalid date'
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
return
end

begin
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[1].to_i > 23
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[2].to_i > 59
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[3].to_i > 59
rescue Exception
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
end
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m.length < 4
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[1].to_i > 23
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[2].to_i > 59
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors]) and return if m[3].to_i > 59
else
validation_error(processor, error_message, fragments, current_schema, self, options[:record_errors])
end
Expand Down
2 changes: 1 addition & 1 deletion lib/json-schema/attributes/not.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def self.validate(current_schema, data, fragments, processor, validator, options
message = "The property '#{build_fragment(fragments)}' of type #{data.class} matched the disallowed schema"
failed = false
end
rescue
rescue ValidationError
# Yay, we failed validation.
end

Expand Down
6 changes: 6 additions & 0 deletions lib/json-schema/errors/json_load_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module JSON
class Schema
class JsonLoadError < StandardError
end
end
end
8 changes: 8 additions & 0 deletions lib/json-schema/errors/schema_parse_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require 'json/common'

module JSON
class Schema
class SchemaParseError < JSON::ParserError
end
end
end
4 changes: 2 additions & 2 deletions lib/json-schema/schema/reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ def initialize(options = {})
# @param location [#to_s] The location from which to read the schema
# @return [JSON::Schema]
# @raise [JSON::Schema::ReadRefused] if +accept_uri+ or +accept_file+
# indicated the schema should not be readed
# @raise [JSON::ParserError] if the schema was not a valid JSON object
# indicated the schema could not be read
# @raise [JSON::Schema::ParseError] if the schema was not a valid JSON object
def read(location)
uri = Addressable::URI.parse(location.to_s)
body = if uri.scheme.nil? || uri.scheme == 'file'
Expand Down
2 changes: 2 additions & 0 deletions lib/json-schema/util/uri.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module JSON
module Util
module URI
SUPPORTED_PROTOCOLS = %w(http https ftp tftp sftp ssh svn+ssh telnet nntp gopher wais ldap prospero)

def self.normalized_uri(uri)
uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI)
# Check for absolute path
Expand Down
64 changes: 41 additions & 23 deletions lib/json-schema/validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

require 'json-schema/schema/reader'
require 'json-schema/errors/schema_error'
require 'json-schema/errors/schema_parse_error'
require 'json-schema/errors/json_load_error'
require 'json-schema/errors/json_parse_error'

module JSON
Expand Down Expand Up @@ -54,17 +56,13 @@ def initialize(schema_data, data, opts={})

# validate the schema, if requested
if @options[:validate_schema]
begin
if @base_schema.schema["$schema"]
base_validator = JSON::Validator.validator_for_name(@base_schema.schema["$schema"])
end
metaschema = base_validator ? base_validator.metaschema : validator.metaschema
# Don't clear the cache during metaschema validation!
meta_validator = JSON::Validator.new(metaschema, @base_schema.schema, {:clear_cache => false})
meta_validator.validate
rescue JSON::Schema::ValidationError, JSON::Schema::SchemaError
raise $!
if @base_schema.schema["$schema"]
base_validator = JSON::Validator.validator_for_name(@base_schema.schema["$schema"])
end
metaschema = base_validator ? base_validator.metaschema : validator.metaschema
# Don't clear the cache during metaschema validation!
meta_validator = JSON::Validator.new(metaschema, @base_schema.schema, {:clear_cache => false})
meta_validator.validate
end

# If the :fragment option is set, try and validate against the fragment
Expand Down Expand Up @@ -415,15 +413,27 @@ def json_backend=(backend)

def parse(s)
if defined?(MultiJson)
MultiJson.respond_to?(:adapter) ? MultiJson.load(s) : MultiJson.decode(s)
begin
MultiJson.respond_to?(:adapter) ? MultiJson.load(s) : MultiJson.decode(s)
rescue MultiJson::ParseError => e
raise JSON::Schema::JsonParseError.new(e.message)
end
else
case @@json_backend.to_s
when 'json'
JSON.parse(s, :quirks_mode => true)
begin
JSON.parse(s, :quirks_mode => true)
rescue JSON::ParserError => e
raise JSON::Schema::JsonParseError.new(e.message)
end
when 'yajl'
json = StringIO.new(s)
parser = Yajl::Parser.new
parser.parse(json) or raise JSON::Schema::JsonParseError.new("The JSON could not be parsed by yajl")
begin
json = StringIO.new(s)
parser = Yajl::Parser.new
parser.parse(json) or raise JSON::Schema::JsonParseError.new("The JSON could not be parsed by yajl")
rescue Yajl::ParseError => e
raise JSON::Schema::JsonParseError.new(e.message)
end
else
raise JSON::Schema::JsonParseError.new("No supported JSON parsers found. The following parsers are suported:\n * yajl-ruby\n * json")
end
Expand Down Expand Up @@ -520,7 +530,7 @@ def initialize_schema(schema)
schema = schema.to_array_schema
end
Validator.add_schema(schema)
rescue
rescue JSON::Schema::JsonParseError
# Build a uri for it
schema_uri = Util::URI.normalized_uri(schema)
if !self.class.schema_loaded?(schema_uri)
Expand Down Expand Up @@ -551,7 +561,7 @@ def initialize_schema(schema)
end
Validator.add_schema(schema)
else
raise "Invalid schema - must be either a string or a hash"
raise SchemaParseError, "Invalid schema - must be either a string or a hash"
end

schema
Expand All @@ -567,12 +577,12 @@ def initialize_data(data)
elsif data.is_a?(String)
begin
data = JSON::Validator.parse(data)
rescue
rescue JSON::Schema::JsonParseError
begin
json_uri = Util::URI.normalized_uri(data)
data = JSON::Validator.parse(custom_open(json_uri))
rescue
# Silently discard the error - the data will not change
rescue JSON::Schema::JsonLoadError
# Silently discard the error - use the data as-is
end
end
end
Expand All @@ -582,10 +592,18 @@ def initialize_data(data)

def custom_open(uri)
uri = Util::URI.normalized_uri(uri) if uri.is_a?(String)
if uri.absolute? && uri.scheme != 'file'
open(uri.to_s).read
if uri.absolute? && Util::URI::SUPPORTED_PROTOCOLS.include?(uri.scheme)
begin
open(uri.to_s).read
rescue OpenURI::HTTPError, Timeout::Error => e
raise JSON::Schema::JsonLoadError, e.message
end
else
File.read(Addressable::URI.unescape(uri.path))
begin
File.read(Addressable::URI.unescape(uri.path))
rescue SystemCallError => e
raise JSON::Schema::JsonLoadError, e.message
end
end
end
end
Expand Down
10 changes: 0 additions & 10 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,4 @@ def refute_valid(schema, data, options = {})
errors = JSON::Validator.fully_validate(schema, data, options)
refute_equal([], errors, "#{data.inspect} should be invalid for schema:\n#{schema.inspect}")
end

def parser_error
if defined?(::Yajl)
Yajl::ParseError
elsif defined?(::MultiJson)
MultiJson::ParseError
else
JSON::ParserError
end
end
end
22 changes: 14 additions & 8 deletions test/test_initialize_data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ def test_parse_character_string

assert(JSON::Validator.validate(schema, data, :parse_data => false))

assert_raises(parser_error) do
assert_raises(JSON::Schema::JsonParseError) do
JSON::Validator.validate(schema, data, :json => true)
end

assert_raises(Errno::ENOENT) { JSON::Validator.validate(schema, data, :uri => true) }
assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) }
end

def test_parse_integer_string
Expand All @@ -27,7 +27,7 @@ def test_parse_integer_string

assert(JSON::Validator.validate(schema, data, :json => true))

assert_raises(Errno::ENOENT) { JSON::Validator.validate(schema, data, :uri => true) }
assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) }
end

def test_parse_hash_string
Expand All @@ -40,7 +40,7 @@ def test_parse_hash_string

assert(JSON::Validator.validate(schema, data, :json => true))

assert_raises(Errno::ENOENT) { JSON::Validator.validate(schema, data, :uri => true) }
assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) }
end

def test_parse_json_string
Expand All @@ -53,7 +53,7 @@ def test_parse_json_string

assert(JSON::Validator.validate(schema, data, :json => true))

assert_raises(Errno::ENOENT) { JSON::Validator.validate(schema, data, :uri => true) }
assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) }
end

def test_parse_valid_uri_string
Expand All @@ -66,7 +66,7 @@ def test_parse_valid_uri_string

assert(JSON::Validator.validate(schema, data, :parse_data => false))

assert_raises(parser_error) do
assert_raises(JSON::Schema::JsonParseError) do
JSON::Validator.validate(schema, data, :json => true)
end

Expand All @@ -83,11 +83,17 @@ def test_parse_invalid_uri_string

assert(JSON::Validator.validate(schema, data, :parse_data => false))

assert_raises(parser_error) do
stub_request(:get, "foo.bar").to_return(:status => [500, "Internal Server Error"])

assert(JSON::Validator.validate(schema, data))

assert(JSON::Validator.validate(schema, data, :parse_data => false))

assert_raises(JSON::Schema::JsonParseError) do
JSON::Validator.validate(schema, data, :json => true)
end

assert_raises(Timeout::Error) { JSON::Validator.validate(schema, data, :uri => true) }
assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) }
end

def test_parse_integer
Expand Down
2 changes: 1 addition & 1 deletion test/test_schema_loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def test_parse_error

reader = JSON::Schema::Reader.new

assert_raises(parser_error) do
assert_raises(JSON::Schema::JsonParseError) do
reader.read(ADDRESS_SCHEMA_URI)
end
end
Expand Down