From a70949b91213da546bf7125b205249b375e5cf3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mickae=CC=88l=20Menu?= Date: Fri, 1 Jul 2022 12:21:31 +0200 Subject: [PATCH] Fix serving EPUB hrefs with anchor or query parameters --- CHANGELOG.md | 1 + Sources/Shared/Fetcher/ArchiveFetcher.swift | 28 ++++++++++++------- .../Fetcher/ArchiveFetcherTests.swift | 26 +++++++++++------ 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa763ee07..2c14180a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file. Take a look #### Navigator * Fixed memory leaks in the EPUB and PDF navigators. +* [#61](https://github.com/readium/swift-toolkit/issues/61) Fixed serving EPUB resources when the HREF contains an anchor or query parameters. #### Streamer diff --git a/Sources/Shared/Fetcher/ArchiveFetcher.swift b/Sources/Shared/Fetcher/ArchiveFetcher.swift index 58568e3be..ff6ffa3f3 100644 --- a/Sources/Shared/Fetcher/ArchiveFetcher.swift +++ b/Sources/Shared/Fetcher/ArchiveFetcher.swift @@ -1,12 +1,7 @@ // -// ArchiveFetcher.swift -// r2-shared-swift -// -// Created by Mickaël Menu on 11/05/2020. -// -// Copyright 2020 Readium Foundation. All rights reserved. -// Use of this source code is governed by a BSD-style license which is detailed -// in the LICENSE file present in the project repository where this source code is maintained. +// Copyright 2022 Readium Foundation. All rights reserved. +// Use of this source code is governed by the BSD-style license +// available in the top-level LICENSE file of the project. // import Foundation @@ -31,8 +26,8 @@ public final class ArchiveFetcher: Fetcher, Loggable { public func get(_ link: Link) -> Resource { guard - let entry = archive.entry(at: link.href), - let reader = archive.readEntry(at: link.href) + let entry = findEntry(at: link.href), + let reader = archive.readEntry(at: entry.path) else { return FailureResource(link: link, error: .notFound(nil)) } @@ -40,6 +35,19 @@ public final class ArchiveFetcher: Fetcher, Loggable { return ArchiveResource(link: link, entry: entry, reader: reader) } + private func findEntry(at href: String) -> ArchiveEntry? { + if let entry = archive.entry(at: href) { + return entry + } + + // Try after removing query parameters and anchors from the href. + guard let href = href.components(separatedBy: .init(charactersIn: "#?")).first else { + return nil + } + + return archive.entry(at: href) + } + public func close() {} private final class ArchiveResource: Resource { diff --git a/Tests/SharedTests/Fetcher/ArchiveFetcherTests.swift b/Tests/SharedTests/Fetcher/ArchiveFetcherTests.swift index d75c08128..d52c7555d 100644 --- a/Tests/SharedTests/Fetcher/ArchiveFetcherTests.swift +++ b/Tests/SharedTests/Fetcher/ArchiveFetcherTests.swift @@ -1,12 +1,7 @@ // -// ArchiveFetcherTests.swift -// r2-shared-swift -// -// Created by Mickaël Menu on 11/05/2020. -// -// Copyright 2020 Readium Foundation. All rights reserved. -// Use of this source code is governed by a BSD-style license which is detailed -// in the LICENSE file present in the project repository where this source code is maintained. +// Copyright 2022 Readium Foundation. All rights reserved. +// Use of this source code is governed by the BSD-style license +// available in the top-level LICENSE file of the project. // import XCTest @@ -104,4 +99,19 @@ class ArchiveFetcherTests: XCTestCase { ) } + /// When the HREF contains query parameters, the fetcher should first be able to remove them as + /// a fallback. + func testHREFWithQueryParameters() { + let resource = fetcher.get(Link(href: "/mimetype?query=param")) + let result = resource.readAsString(encoding: .ascii) + XCTAssertEqual(result.getOrNil(), "application/epub+zip") + } + + /// When the HREF contains an anchor, the fetcher should first be able to remove them as + /// a fallback. + func testHREFWithAnchor() { + let resource = fetcher.get(Link(href: "/mimetype#anchor")) + let result = resource.readAsString(encoding: .ascii) + XCTAssertEqual(result.getOrNil(), "application/epub+zip") + } }