Skip to content

Commit

Permalink
Fix canonicalization of relative URI paths with leading slashes
Browse files Browse the repository at this point in the history
Signed-off-by: Juan Cruz Viotti <[email protected]>
  • Loading branch information
jviotti committed Jan 10, 2025
1 parent 55481f3 commit 3ed790f
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 4 deletions.
7 changes: 3 additions & 4 deletions src/uri/uri.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ static auto uri_parse(const std::string &data, UriUriA *uri) -> void {
uri_normalize(uri);
}

static auto canonicalize_path(const std::string &path, const bool is_relative)
static auto canonicalize_path(const std::string &path)
-> std::optional<std::string> {
// TODO: This is a hack, as this whole function works badly for
// relative paths with ".."
Expand Down Expand Up @@ -98,7 +98,7 @@ static auto canonicalize_path(const std::string &path, const bool is_relative)

// Reconstruct the canonical path
std::string canonical_path;
std::string separator = (is_relative && !has_leading_with_word) ? "/" : "";
std::string separator = "";

for (const auto &seg : segments) {
canonical_path += separator + seg;
Expand Down Expand Up @@ -430,8 +430,7 @@ auto URI::canonicalize() -> URI & {
// Clean Path form ".." and "."
const auto result_path{this->path()};
if (result_path.has_value()) {
const auto canonical_path{
canonicalize_path(result_path.value(), this->is_relative())};
const auto canonical_path{canonicalize_path(result_path.value())};
if (canonical_path.has_value()) {
this->path_ = canonical_path.value();
}
Expand Down
32 changes: 32 additions & 0 deletions test/jsonschema/jsonschema_frame_2019_09_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2004,3 +2004,35 @@ TEST(JSONSchema_frame_2019_09, relative_base_uri_with_ref) {
EXPECT_STATIC_REFERENCE(frame, "/allOf/0/$ref", "common#foo", "common",
"foo");
}

TEST(JSONSchema_frame_2019_09, relative_id_leading_slash) {
const sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$id": "/base",
"$schema": "https://json-schema.org/draft/2019-09/schema"
})JSON");

sourcemeta::jsontoolkit::Frame frame;
frame.analyse(document, sourcemeta::jsontoolkit::default_schema_walker,
sourcemeta::jsontoolkit::official_resolver);

EXPECT_EQ(frame.locations().size(), 3);
EXPECT_FRAME_STATIC_2019_09_RESOURCE(frame, "/base", "/base", "", "/base", "",
0);

// JSON Pointers

// TODO: Pointer should be /base instead of base
EXPECT_FRAME_STATIC_2019_09_POINTER(frame, "base#/$id", "/base", "/$id",
"/base", "/$id", 0);
EXPECT_FRAME_STATIC_2019_09_POINTER(frame, "base#/$schema", "/base",
"/$schema", "/base", "/$schema", 0);

// References

EXPECT_EQ(frame.references().size(), 1);

EXPECT_STATIC_REFERENCE(
frame, "/$schema", "https://json-schema.org/draft/2019-09/schema",
"https://json-schema.org/draft/2019-09/schema", std::nullopt);
}
6 changes: 6 additions & 0 deletions test/uri/uri_canonicalize_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ TEST(URI_canonicalize, example_relative_4) {
EXPECT_EQ(uri.recompose(), "foo/bar");
}

TEST(URI_canonicalize, example_relative_6) {
sourcemeta::jsontoolkit::URI uri{"/foo"};
uri.canonicalize();
EXPECT_EQ(uri.recompose(), "/foo");
}

TEST(URI_canonicalize, example_12) {
sourcemeta::jsontoolkit::URI uri{"#foo"};
uri.canonicalize();
Expand Down

0 comments on commit 3ed790f

Please sign in to comment.