Skip to content

Commit

Permalink
Ensure that fragment references are valid JSON Pointers
Browse files Browse the repository at this point in the history
  • Loading branch information
jonasschmidt committed Jul 26, 2016
1 parent 7719b00 commit 6dc594a
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 9 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -10,7 +10,7 @@ Add the project to your Mix dependencies in `mix.exs`:

```elixir
defp deps do
[{:ex_json_schema, "~> 0.5.0"}]
[{:ex_json_schema, "~> 0.5.1"}]
end
```

Expand Down
24 changes: 17 additions & 7 deletions lib/ex_json_schema/schema.ex
Expand Up @@ -25,6 +25,7 @@ defmodule ExJsonSchema.Schema do
def get_ref_schema(root = %Root{}, [:root | path] = ref) do
get_ref_schema_with_schema(root.schema, path, ref)
end

def get_ref_schema(root = %Root{}, [url | path] = ref) when is_binary(url) do
get_ref_schema_with_schema(root.refs[url], path, ref)
end
Expand Down Expand Up @@ -107,22 +108,28 @@ defmodule ExJsonSchema.Schema do

defp resolve_ref(root, ref) do
[url | fragments] = String.split(ref, "#")
{root, path} = root_and_path_for_url(root, fragments, url)
fragment = get_fragment(fragments, ref)
{root, path} = root_and_path_for_url(root, fragment, url)
assert_reference_valid(path, root, ref)
{root, path}
end

defp root_and_path_for_url(root, fragments, "") do
{root, [root.location | relative_path(fragments)]}
defp get_fragment([], _), do: nil
defp get_fragment([""], _), do: nil
defp get_fragment([fragment = "/" <> _], _), do: fragment
defp get_fragment(_, ref), do: raise InvalidSchemaError, message: "invalid reference #{ref}"

defp root_and_path_for_url(root, fragment, "") do
{root, [root.location | relative_path(fragment)]}
end

defp root_and_path_for_url(root, fragments, url) do
defp root_and_path_for_url(root, fragment, url) do
root = resolve_and_cache_remote_schema(root, url)
{root, [url | relative_path(fragments)]}
{root, [url | relative_path(fragment)]}
end

defp relative_path([fragment = "/" <> _]), do: relative_ref_path(fragment)
defp relative_path(_), do: []
defp relative_path(nil), do: []
defp relative_path(fragment), do: relative_ref_path(fragment)

defp relative_ref_path(ref) do
["" | keys] = unescaped_ref_segments(ref)
Expand Down Expand Up @@ -202,12 +209,15 @@ defmodule ExJsonSchema.Schema do
defp get_ref_schema_with_schema(nil, _, ref) do
raise InvalidSchemaError, message: "reference #{ref_to_string(ref)} could not be resolved"
end

defp get_ref_schema_with_schema(schema, [], _) do
schema
end

defp get_ref_schema_with_schema(schema, [key | path], ref) when is_binary(key) do
get_ref_schema_with_schema(Map.get(schema, key), path, ref)
end

defp get_ref_schema_with_schema(schema, [idx | path], ref) when is_integer(idx) do
try do
get_ref_schema_with_schema(:lists.nth(idx + 1, schema), path, ref)
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Expand Up @@ -4,7 +4,7 @@ defmodule ExJsonSchema.Mixfile do
def project do
[
app: :ex_json_schema,
version: "0.5.0",
version: "0.5.1",
elixir: "~> 1.0",
description: "A JSON Schema validator with full support for the draft 4 specification and zero dependencies.",
deps: deps,
Expand Down
5 changes: 5 additions & 0 deletions test/ex_json_schema/schema_test.exs
Expand Up @@ -55,6 +55,11 @@ defmodule ExJsonSchema.SchemaTest do
assert_raise ExJsonSchema.Schema.InvalidSchemaError, "reference http://json-schema.org/schema#/1 could not be resolved", fn -> resolve(schema) end
end

test "catches invalid references" do
schema = %{"$ref" => "#definitions/foo"}
assert_raise ExJsonSchema.Schema.InvalidSchemaError, "invalid reference #definitions/foo", fn -> resolve(schema) end
end

test "changing the resolution scope" do
schema = %{"id" => "#/foo_scope/", "foo" => %{"$ref" => "bar"}, "foo_scope" => %{"bar" => "baz"}}
resolved = resolve(schema)
Expand Down

0 comments on commit 6dc594a

Please sign in to comment.