Cannot Open Any Books [No mapping for GET /book/XXXXXXXXXX/read-epub]
Closed this issue · 4 comments
Steps to reproduce
When attempting to open any book in Komga, the screen remains blank [with a simple warning sign in the middle], and the Chrome web traffic logs show a 404 error when trying to load the next or previous book.
- Deploy Komga using Docker with the following configuration:
- Version:
1.14.0
- Media stored on an NFS server.
- Configuration specified via Helm chart (see below).
- Using Traefik as reverse proxy.
- No path modification, servers hosted on https://read.${SECRET_DOMAIN}
- Version:
- Open the Komga UI and attempt to open any book in the library.
- Check Chrome web traffic logs when the book fails to load.
Expected behavior
The book should display correctly without any 404 errors, and navigating to the next or previous book should function properly.
Actual behavior
- A blank screen is displayed when trying to open any book.
- Chrome web traffic logs show a 404 error when requesting both
/api/v1/books/{bookId}/next
and/api/v1/books/{bookId}/previous
.
Error response from the logs:
{
"timestamp": "2024-09-29T11:53:25.418+00:00",
"status": 404,
"error": "Not Found",
"message": "404 NOT_FOUND",
"path": "/api/v1/books/0HDYCWF45AHWN/next"
}
Logs
____ __.
| |/ _|____ _____ _________
| < / _ \ / \ / ___\__ \
| | ( <_> ) Y Y \/ /_/ > __ \_
|____|__ \____/|__|_| /\___ (____ /
\/ \//_____/ \/
Version: 1.14.0
2024-09-29T13:05:44.902+01:00 INFO 1 --- [ main] org.gotson.komga.ApplicationKt : Starting ApplicationKt v1.14.0 using Java 21.0.4 with PID 1 (/app/BOOT-INF/classes started by ? in /app)
2024-09-29T13:05:44.907+01:00 DEBUG 1 --- [ main] org.gotson.komga.ApplicationKt : Running with Spring Boot v3.2.2, Spring v6.1.3
2024-09-29T13:05:44.908+01:00 INFO 1 --- [ main] org.gotson.komga.ApplicationKt : The following 1 profile is active: "docker"
[DELETED]
2024-09-29T13:05:52.750+01:00 INFO 1 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure Or [Mvc [pattern='/api/**'], Mvc [pattern='/opds/**'], Mvc [pattern='/sse/**'], Mvc [pattern='/oauth2/authorization/**'], Mvc [pattern='/login/oauth2/code/**'], EndpointRequestMatcher includes=[*], excludes=[], includeLinks=true] with [org.springframework.security.web.session.DisableEncodeUrlFilter@27b89e0a, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@42bb0492, org.springframework.security.web.context.SecurityContextHolderFilter@1100363d, org.springframework.security.web.header.HeaderWriterFilter@786125a6, org.springframework.web.filter.CorsFilter@6eed5b68, org.springframework.security.web.authentication.logout.LogoutFilter@20fdf45a, org.springframework.security.web.session.ConcurrentSessionFilter@656c356c, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@6b8773c7, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@788be73c, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@65018381, org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter@3d70dab8, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@4377b35b, org.springframework.security.web.session.SessionManagementFilter@642ebd4c, org.springframework.security.web.access.ExceptionTranslationFilter@46700301, org.springframework.security.web.access.intercept.AuthorizationFilter@7c6f91d2]
2024-09-29T13:05:52.772+01:00 INFO 1 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure Or [Mvc [pattern='/kobo/**']] with [org.springframework.security.web.session.DisableEncodeUrlFilter@3796ca50, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@55154761, org.springframework.security.web.context.SecurityContextHolderFilter@39384ba6, org.springframework.security.web.header.HeaderWriterFilter@1b52f723, org.springframework.web.filter.CorsFilter@304e83a, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@e7529ac, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@6770a229, org.gotson.komga.infrastructure.security.apikey.ApiKeyAuthenticationFilter@5e9db5e7, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@5fd8302e, org.springframework.security.web.access.ExceptionTranslationFilter@25198ead, org.springframework.security.web.access.intercept.AuthorizationFilter@1009a9b4]
2024-09-29T13:05:53.198+01:00 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 25600 (http) with context path ''
[DELETED]
2024-09-29T13:06:02.593+01:00 INFO 1 --- [io-25600-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2024-09-29T13:06:02.594+01:00 INFO 1 --- [io-25600-exec-2] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2024-09-29T13:06:02.596+01:00 INFO 1 --- [io-25600-exec-2] o.s.web.servlet.DispatcherServlet : Completed initialization in 2 ms
2024-09-29T13:06:02.652+01:00 WARN 1 --- [io-25600-exec-2] o.s.web.servlet.PageNotFound : No mapping for GET /book/0HDYCWF4HAN6Y/read-epub
2024-09-29T13:06:03.329+01:00 DEBUG 1 --- [ task-6] o.g.k.i.security.LoginListener : AuthenticationActivity(userId=0HDXR6V18ZAE1, email=admin@maia.ac, apiKeyId=null, apiKeyComment=null, ip=[REDACTED_IP], userAgent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/[REDACTED_IP] Safari/537.36, success=true, error=null, dateTime=2024-09-29T13:06:03.322730328, source=RememberMe)
2024-09-29T13:06:03.785+01:00 DEBUG 1 --- [ task-6] o.g.k.i.s.session.SessionListener : SessionCreatedEvent: 325ddb6a-febb-497e-bebf-af284f16181c
2024-09-29T13:06:05.202+01:00 DEBUG 1 --- [io-25600-exec-8] o.g.komga.domain.service.BookAnalyzer : Get file OEBPS/9781368016193_epub_cvi_r1.xhtml for book: BookWithMedia(book=Book(name=The Lying Woods - Ashley Elston, url=file:/data/Ashley%20Elston/The%20Lying%20Woods%20(67)/The%20Lying%20Woods%20-%20Ashley%20Elston.epub, fileLastModified=2024-09-29T12:22:28.068, fileSize=1179801, fileHash=6f27c021db1dd6298b15bfb19a51c632, number=1, id=0HDYCWF4HAN6Y, seriesId=0HDYCWF4DARHS, libraryId=0HDXRE4RCZCQ6, deletedDate=null, oneshot=false, createdDate=2024-09-29T12:46:27, lastModifiedDate=2024-09-29T12:46:55.030), media=Media(status=READY, mediaType=application/epub+zip, comment=null, bookId='0HDYCWF4HAN6Y', createdDate=2024-09-29T12:46:27, lastModifiedDate=2024-09-29T12:46:49.875))
2024-09-29T13:06:13.210+01:00 DEBUG 1 --- [ scheduling-1] o.g.komga.interfaces.sse.SseController : Publish SSE: 'TaskQueueStatus':TaskQueueSseDto(count=0, countByType={})
Komga version
1.14.0
Operating system
Talos OS (K8S, Docker)
Installation method
jar
Other details
My Deployment:
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: komga
namespace: media
spec:
interval: 15m
chart:
spec:
chart: app-template
version: 1.5.1
sourceRef:
kind: HelmRepository
name: bjw-s
namespace: flux-system
install:
createNamespace: true
remediation:
retries: 5
upgrade:
remediation:
retries: 5
values:
image:
repository: gotson/komga
tag: latest
env:
TZ: "${TIMEZONE}"
CACHE_DIR: /cache
LOGGING_LEVEL_ORG_GOTSON_KOMGA: "DEBUG"
KOMGA_CORS_ALLOWED_ORIGINS: &cors "https://read.${SECRET_DOMAIN}"
SERVER_PORT: &port 25600
service:
main:
ports:
http:
port: *port
ingress:
main:
enabled: true
ingressClassName: traefik
annotations:
kubernetes.io/tls-acme: "true"
cert-manager.io/cluster-issuer: letsencrypt-production
traefik.ingress.kubernetes.io/router.entrypoints: "websecure"
traefik.ingress.kubernetes.io/router.middlewares: >-
networking-traefik-secure-headers@kubernetescrd,
networking-rfc1918@kubernetescrd,
media-komga-middleware@kubernetescrd
hosts:
- host: &host "read.${SECRET_DOMAIN}"
paths:
- path: /
pathType: Prefix
tls:
- secretName: &tls "tls-komga"
hosts:
- *host
persistence:
data:
enabled: true
volumeSpec:
nfs:
server: "${NFS_SERVER_IP_COLD_2}"
path: "${NFS_SERVER_IP_COLD_2_MEDIA_VAULT}/books"
mountPath: /data
readOnly: false
My Reverse Proxy Config:
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: komga-secure-middleware
namespace: media
spec:
headers:
# Custom request headers for Komga
customRequestHeaders:
X-Forwarded-Proto: https
# Allow GET and POST methods for cross-origin requests
accessControlAllowMethods:
- GET
- POST
# Allow cross-origin requests from specific domains
accessControlAllowOriginList:
- https://*.${SECRET_DOMAIN}
- https://${SECRET_DOMAIN}
# Cache preflight responses for 100 seconds
accessControlMaxAge: 100
# Enforce strict Content Security Policy (CSP)
contentSecurityPolicy: |
default-src 'none'; form-action 'none'; frame-ancestors 'none'; base-uri 'none'
# Add 'Vary: Origin' header to responses
addVaryHeader: true
# Enable protection against XSS attacks
browserXssFilter: true
# Prevent MIME-type sniffing
contentTypeNosniff: true
# Enable HTTP Strict Transport Security (HSTS) for 2 years
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 63072000
# Prevent the page from being framed (clickjacking protection)
frameDeny: true
# Set the referrer policy to 'same-origin'
referrerPolicy: 'same-origin'
# Ensure all traffic is redirected to HTTPS
sslRedirect: true
Acknowledgements
- I have searched the existing issues (open AND closed) and this is a new ticket, NOT a duplicate or related to another open issue.
- I have written a short but informative title.
- I have checked the FAQ.
- I have updated the app to the latest version.
- I will fill out all of the requested information in this form.
can you get the logs from the Javascript console of the browser, and the XHR network requests made by the browser?
Hi @gotson,
I think the javascript console might be hiding the reason for this error.....but the 404 is really strange....
Okay @gotson,
I had a look at the X-Frame-Options on my traefik side. I made the following addition for anyone in this situation:
---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: komga-middleware
namespace: media
spec:
headers:
customRequestHeaders:
X-Forwarded-Proto: https
customFrameOptionsValue: "ALLOW-FROM https://read.${SECRET_DOMAIN}" # This can still be kept if you want to allow this specific origin
contentSecurityPolicy: "frame-ancestors 'self' https://read.${SECRET_DOMAIN};" # Allow framing from self and specified URL
Books are now opening!!! 👍🏼
However, I still see the 404 error but the webpage works fine. Maybe an old call still on the webui code?
but the 404 is really strange
this is expected behaviour if the series has only 1 book