From f4148d0842f7132ee902bbf6e02f0254e4e6a2ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mickae=CC=88l=20Menu?= Date: Fri, 1 Jul 2022 12:36:03 +0200 Subject: [PATCH] Fix serving EPUB hrefs with anchor or query parameters --- CHANGELOG.md | 4 +++ .../r2/shared/fetcher/ArchiveFetcher.kt | 14 +++++++-- .../r2/shared/fetcher/ArchiveFetcherTest.kt | 30 +++++++++++++++---- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ab053d1b8..2d852b7e13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,10 @@ All notable changes to this project will be documented in this file. Take a look * Fixed parsing the table of contents of an EPUB 3 using NCX instead of a Navigation Document. +#### Navigator + +* [swift-toolkit#61](https://github.com/readium/swift-toolkit/issues/61) Fixed serving EPUB resources when the HREF contains an anchor or query parameters. + ## [2.2.0] diff --git a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/ArchiveFetcher.kt b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/ArchiveFetcher.kt index 8444ce5b8c..d3039b0ae2 100644 --- a/readium/shared/src/main/java/org/readium/r2/shared/fetcher/ArchiveFetcher.kt +++ b/readium/shared/src/main/java/org/readium/r2/shared/fetcher/ArchiveFetcher.kt @@ -13,6 +13,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.readium.r2.shared.extensions.addPrefix import org.readium.r2.shared.extensions.tryOr +import org.readium.r2.shared.extensions.tryOrLog import org.readium.r2.shared.extensions.tryOrNull import org.readium.r2.shared.publication.Link import org.readium.r2.shared.publication.Properties @@ -57,8 +58,7 @@ class ArchiveFetcher private constructor(private val archive: Archive) : Fetcher suspend fun entry(): ResourceTry { if (!::_entry.isInitialized) { _entry = try { - val entry = archive.entry(originalLink.href.removePrefix("/")) - Try.success(entry) + Try.success(findEntry(originalLink)) } catch (e: Exception) { Try.failure(Resource.Exception.NotFound(e)) } @@ -67,6 +67,16 @@ class ArchiveFetcher private constructor(private val archive: Archive) : Fetcher return _entry } + suspend fun findEntry(link: Link): Archive.Entry { + val href = link.href.removePrefix("/") + return try { + archive.entry(href) + } catch (e: Exception) { + // Try again after removing query parameters and anchors from the href. + archive.entry(href.takeWhile { it !in "#?" }) + } + } + override suspend fun link(): Link { val entry = entry().getOrNull() ?: return originalLink return originalLink.addProperties(entry.toLinkProperties()) diff --git a/readium/shared/src/test/java/org/readium/r2/shared/fetcher/ArchiveFetcherTest.kt b/readium/shared/src/test/java/org/readium/r2/shared/fetcher/ArchiveFetcherTest.kt index bac5887199..4dca58644d 100644 --- a/readium/shared/src/test/java/org/readium/r2/shared/fetcher/ArchiveFetcherTest.kt +++ b/readium/shared/src/test/java/org/readium/r2/shared/fetcher/ArchiveFetcherTest.kt @@ -1,10 +1,7 @@ /* - * Module: r2-shared-kotlin - * Developers: Quentin Gliosca - * - * Copyright (c) 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. */ package org.readium.r2.shared.fetcher @@ -172,4 +169,25 @@ class ArchiveFetcherTest { ) } + /** + * When the HREF contains query parameters, the fetcher should first be able to remove them as + * a fallback. + */ + @Test + fun `Get resource from HREF with query parameters`() = runBlocking { + val resource = fetcher.get(Link(href = "/mimetype?query=param")) + val result = resource.readAsString().getOrNull() + assertEquals("application/epub+zip", result) + } + + /** + * When the HREF contains an anchor, the fetcher should first be able to remove them as + * a fallback. + */ + @Test + fun `Get resource from HREF with anchors`() = runBlocking { + val resource = fetcher.get(Link(href = "/mimetype#anchor")) + val result = resource.readAsString().getOrNull() + assertEquals("application/epub+zip", result) + } }