From 9e01fdbfc7e7f49eb1365d978ba4e597d429db6e Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Fri, 10 Jan 2025 08:35:50 -0400 Subject: [PATCH] Support serving schemas without identifiers (#115) Signed-off-by: Juan Cruz Viotti --- src/index/index.cc | 16 +++++- src/server/server.cc | 25 +++++++-- test/e2e/common/get.hurl | 9 +++ test/e2e/common/unidentify.hurl | 98 +++++++++++++++++++++++++++++++++ test/sandbox/manifest-ce.txt | 18 ++++++ test/sandbox/manifest-ee.txt | 18 ++++++ 6 files changed, 177 insertions(+), 7 deletions(-) create mode 100644 test/e2e/common/unidentify.hurl diff --git a/src/index/index.cc b/src/index/index.cc index 02994e2..b4f58cb 100644 --- a/src/index/index.cc +++ b/src/index/index.cc @@ -198,7 +198,7 @@ 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}; @@ -206,6 +206,20 @@ static auto index(sourcemeta::jsontoolkit::FlatFileSchemaResolver &resolver, 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; diff --git a/src/server/server.cc b/src/server/server.cc index f14521a..bbdca13 100644 --- a/src/server/server.cc +++ b/src/server/server.cc @@ -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 { static const auto SERVER_BASE_URL{ sourcemeta::jsontoolkit::URI{configuration().at("url").to_string()} @@ -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; } @@ -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", @@ -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, diff --git a/test/e2e/common/get.hurl b/test/e2e/common/get.hurl index d66ab3a..b03eade 100644 --- a/test/e2e/common/get.hurl +++ b/test/e2e/common/get.hurl @@ -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 diff --git a/test/e2e/common/unidentify.hurl b/test/e2e/common/unidentify.hurl new file mode 100644 index 0000000..52895a5 --- /dev/null +++ b/test/e2e/common/unidentify.hurl @@ -0,0 +1,98 @@ +GET {{base}}/example/bundling/single.json?unidentify=1 +HTTP 200 +Content-Type: application/schema+json +Link: ; 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: ; 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" +} diff --git a/test/sandbox/manifest-ce.txt b/test/sandbox/manifest-ce.txt index 75732f2..faf7fc9 100644 --- a/test/sandbox/manifest-ce.txt +++ b/test/sandbox/manifest-ce.txt @@ -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 diff --git a/test/sandbox/manifest-ee.txt b/test/sandbox/manifest-ee.txt index 8dbeab8..6e9b826 100644 --- a/test/sandbox/manifest-ee.txt +++ b/test/sandbox/manifest-ee.txt @@ -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