Skip to content

Commit

Permalink
Support serving schemas without identifiers (#115)
Browse files Browse the repository at this point in the history
Signed-off-by: Juan Cruz Viotti <[email protected]>
  • Loading branch information
jviotti authored Jan 10, 2025
1 parent f341338 commit 9e01fdb
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 7 deletions.
16 changes: 15 additions & 1 deletion src/index/index.cc
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,28 @@ static auto index(sourcemeta::jsontoolkit::FlatFileSchemaResolver &resolver,
std::filesystem::relative(schema_output, output / "schemas")};
std::filesystem::create_directories(bundle_path.parent_path());
std::cerr << "Bundling: " << schema.first << "\n";
const auto bundled_schema{sourcemeta::jsontoolkit::bundle(
auto bundled_schema{sourcemeta::jsontoolkit::bundle(
result.value(), sourcemeta::jsontoolkit::default_schema_walker,
resolver)};
std::ofstream bundle_stream{bundle_path};
sourcemeta::jsontoolkit::prettify(
bundled_schema, bundle_stream,
sourcemeta::jsontoolkit::schema_format_compare);
bundle_stream << "\n";

auto unidentified_path{
output / "unidentified" /
std::filesystem::relative(schema_output, output / "schemas")};
std::filesystem::create_directories(unidentified_path.parent_path());
std::cerr << "Bundling without identifiers: " << schema.first << "\n";
sourcemeta::jsontoolkit::unidentify(
bundled_schema, sourcemeta::jsontoolkit::default_schema_walker,
resolver);
std::ofstream unidentified_stream{unidentified_path};
sourcemeta::jsontoolkit::prettify(
bundled_schema, unidentified_stream,
sourcemeta::jsontoolkit::schema_format_compare);
unidentified_stream << "\n";
}

return EXIT_SUCCESS;
Expand Down
25 changes: 19 additions & 6 deletions src/server/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,19 @@ static auto request_path_to_schema_uri(const std::string &server_base_url,
return schema_identifier.str();
}

static auto resolver(std::string_view identifier, const bool bundle)
static auto schema_directory(const bool bundle, const bool unidentify) noexcept
-> std::filesystem::path {
if (unidentify) {
return "unidentified";
} else if (bundle) {
return "bundles";
} else {
return "schemas";
}
}

static auto resolver(std::string_view identifier, const bool bundle,
const bool unidentify)
-> std::optional<sourcemeta::jsontoolkit::JSON> {
static const auto SERVER_BASE_URL{
sourcemeta::jsontoolkit::URI{configuration().at("url").to_string()}
Expand All @@ -76,8 +88,8 @@ static auto resolver(std::string_view identifier, const bool bundle)

assert(uri.path().has_value());
const auto schema_path{
bundle ? path_join(*(__global_data) / "bundles", uri.path().value())
: path_join(*(__global_data) / "schemas", uri.path().value())};
path_join(*(__global_data) / schema_directory(bundle, unidentify),
uri.path().value())};
if (!std::filesystem::exists(schema_path)) {
return std::nullopt;
}
Expand Down Expand Up @@ -199,8 +211,9 @@ static auto on_request(const sourcemeta::hydra::http::ServerLogger &logger,

const auto schema_identifier{request_path_to_schema_uri(
configuration().at("url").to_string(), request_path)};
const auto maybe_schema{
resolver(schema_identifier, request.query("bundle").has_value())};
const auto maybe_schema{resolver(schema_identifier,
request.query("bundle").has_value(),
request.query("unidentify").has_value())};
if (!maybe_schema.has_value()) {
json_error(logger, request, response,
sourcemeta::hydra::http::Status::NOT_FOUND, "not-found",
Expand Down Expand Up @@ -263,7 +276,7 @@ static auto on_otherwise(const sourcemeta::hydra::http::ServerLogger &logger,
const auto maybe_schema{
resolver(request_path_to_schema_uri(configuration().at("url").to_string(),
request.path()),
false)};
false, false)};

if (maybe_schema.has_value()) {
json_error(logger, request, response,
Expand Down
9 changes: 9 additions & 0 deletions test/e2e/common/get.hurl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ HTTP 200
"type": "string"
}

# With random unknown query parameters
GET {{base}}/example/schemas/string.json?foo=bar&baz=qux
HTTP 200
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "{{base}}/example/schemas/string.json",
"type": "string"
}

# Identifier derived from file path
GET {{base}}/example/schemas/no-id.json
HTTP 200
Expand Down
98 changes: 98 additions & 0 deletions test/e2e/common/unidentify.hurl
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
GET {{base}}/example/bundling/single.json?unidentify=1
HTTP 200
Content-Type: application/schema+json
Link: <http://json-schema.org/draft-07/schema\#>; rel="describedby"
[Asserts]
header "ETag" exists
header "X-Request-id" exists

GET {{base}}/example/bundling/single.json?unidentify=1
HTTP 200
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Bundling",
"description": "A bundling example",
"properties": {
"foo": {
"$ref": "#/definitions/http%3A~1~1localhost%3A8000~1example~1v2.0~1schema.json"
}
},
"definitions": {
"http://localhost:8000/example/v2.0/schema.json": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "integer"
}
}
}

GET {{base}}/example/bundling/single.json?unidentify=0
HTTP 200
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Bundling",
"description": "A bundling example",
"properties": {
"foo": {
"$ref": "#/definitions/http%3A~1~1localhost%3A8000~1example~1v2.0~1schema.json"
}
},
"definitions": {
"http://localhost:8000/example/v2.0/schema.json": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "integer"
}
}
}

GET {{base}}/example/bundling/single.json?unidentify=true
HTTP 200
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Bundling",
"description": "A bundling example",
"properties": {
"foo": {
"$ref": "#/definitions/http%3A~1~1localhost%3A8000~1example~1v2.0~1schema.json"
}
},
"definitions": {
"http://localhost:8000/example/v2.0/schema.json": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "integer"
}
}
}

GET {{base}}/example/bundling/single.json?bundle=1&unidentify=1
HTTP 200
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Bundling",
"description": "A bundling example",
"properties": {
"foo": {
"$ref": "#/definitions/http%3A~1~1localhost%3A8000~1example~1v2.0~1schema.json"
}
},
"definitions": {
"http://localhost:8000/example/v2.0/schema.json": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "integer"
}
}
}

GET {{base}}/example/v2.0/schema.json?unidentify=1
HTTP 200
Content-Type: application/schema+json
Link: <http://json-schema.org/draft-07/schema\#>; rel="describedby"
[Asserts]
header "ETag" exists
header "X-Request-id" exists

GET {{base}}/example/v2.0/schema.json?unidentify=1
HTTP 200
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "integer"
}
18 changes: 18 additions & 0 deletions test/sandbox/manifest-ce.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,21 @@
./schemas/example/schemas/string.json
./schemas/example/v2.0
./schemas/example/v2.0/schema.json
./unidentified
./unidentified/doc
./unidentified/doc/string-1.json
./unidentified/example
./unidentified/example/bundling
./unidentified/example/bundling/single.json
./unidentified/example/extension
./unidentified/example/extension/with.schema.json
./unidentified/example/schemas
./unidentified/example/schemas/absolute-refs.json
./unidentified/example/schemas/camelcase.json
./unidentified/example/schemas/no-id-draft7-ref.json
./unidentified/example/schemas/no-id.json
./unidentified/example/schemas/no-schema-nor-id.json
./unidentified/example/schemas/no-schema.json
./unidentified/example/schemas/string.json
./unidentified/example/v2.0
./unidentified/example/v2.0/schema.json
18 changes: 18 additions & 0 deletions test/sandbox/manifest-ee.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,21 @@
./schemas/example/schemas/string.json
./schemas/example/v2.0
./schemas/example/v2.0/schema.json
./unidentified
./unidentified/doc
./unidentified/doc/string-1.json
./unidentified/example
./unidentified/example/bundling
./unidentified/example/bundling/single.json
./unidentified/example/extension
./unidentified/example/extension/with.schema.json
./unidentified/example/schemas
./unidentified/example/schemas/absolute-refs.json
./unidentified/example/schemas/camelcase.json
./unidentified/example/schemas/no-id-draft7-ref.json
./unidentified/example/schemas/no-id.json
./unidentified/example/schemas/no-schema-nor-id.json
./unidentified/example/schemas/no-schema.json
./unidentified/example/schemas/string.json
./unidentified/example/v2.0
./unidentified/example/v2.0/schema.json

0 comments on commit 9e01fdb

Please sign in to comment.