fix: make comic-page endpoint public (like covers)

The img src tag doesn't send auth headers, so the comic-page
endpoint needs to be publicly accessible like the cover endpoint.
This commit is contained in:
clawdbot 2026-02-21 12:07:53 -05:00
parent 2245d7e9c6
commit c6c8b378ab
2 changed files with 18 additions and 6 deletions

View file

@ -1217,31 +1217,43 @@ class LibraryItemController {
/** /**
* GET api/items/:id/comic-page/:page/:fileid? * GET api/items/:id/comic-page/:page/:fileid?
* Get a single comic page (extracted and cached on server) * Get a single comic page (extracted and cached on server)
* Public endpoint (no auth required, like covers)
* *
* @param {LibraryItemControllerRequest} req * @param {Request} req
* @param {Response} res * @param {Response} res
*/ */
async getComicPage(req, res) { async getComicPage(req, res) {
const ComicCacheManager = require('../managers/ComicCacheManager') const ComicCacheManager = require('../managers/ComicCacheManager')
const libraryItemId = req.params.id
if (!libraryItemId) {
return res.sendStatus(400)
}
const pageNum = parseInt(req.params.page, 10) const pageNum = parseInt(req.params.page, 10)
if (isNaN(pageNum) || pageNum < 1) { if (isNaN(pageNum) || pageNum < 1) {
return res.status(400).send('Invalid page number') return res.status(400).send('Invalid page number')
} }
// Fetch library item directly (no auth middleware)
const libraryItem = await Database.libraryItemModel.getExpandedById(libraryItemId)
if (!libraryItem?.media) {
return res.sendStatus(404)
}
let ebookFile = null let ebookFile = null
if (req.params.fileid) { if (req.params.fileid) {
ebookFile = req.libraryItem.getLibraryFileWithIno(req.params.fileid) ebookFile = libraryItem.getLibraryFileWithIno(req.params.fileid)
if (!ebookFile?.isEBookFile) { if (!ebookFile?.isEBookFile) {
Logger.error(`[LibraryItemController] Invalid ebook file id "${req.params.fileid}"`) Logger.error(`[LibraryItemController] Invalid ebook file id "${req.params.fileid}"`)
return res.status(400).send('Invalid ebook file id') return res.status(400).send('Invalid ebook file id')
} }
} else { } else {
ebookFile = req.libraryItem.media.ebookFile ebookFile = libraryItem.media.ebookFile
} }
if (!ebookFile) { if (!ebookFile) {
Logger.error(`[LibraryItemController] No ebookFile for library item "${req.libraryItem.media.title}"`) Logger.error(`[LibraryItemController] No ebookFile for library item "${libraryItem.media.title}"`)
return res.sendStatus(404) return res.sendStatus(404)
} }
@ -1255,7 +1267,7 @@ class LibraryItemController {
const comicPath = ebookFile.metadata.path const comicPath = ebookFile.metadata.path
const fileIno = ebookFile.ino const fileIno = ebookFile.ino
const result = await ComicCacheManager.getPage( const result = await ComicCacheManager.getPage(
req.libraryItem.id, libraryItemId,
fileIno, fileIno,
comicPath, comicPath,
pageNum pageNum

View file

@ -128,7 +128,7 @@ class ApiRouter {
this.router.patch('/items/:id/ebook/:fileid/status', LibraryItemController.middleware.bind(this), LibraryItemController.updateEbookFileStatus.bind(this)) this.router.patch('/items/:id/ebook/:fileid/status', LibraryItemController.middleware.bind(this), LibraryItemController.updateEbookFileStatus.bind(this))
// Comic page routes - server-side extraction with caching for performance // Comic page routes - server-side extraction with caching for performance
this.router.get('/items/:id/comic-pages/:fileid?', LibraryItemController.middleware.bind(this), LibraryItemController.getComicPages.bind(this)) this.router.get('/items/:id/comic-pages/:fileid?', LibraryItemController.middleware.bind(this), LibraryItemController.getComicPages.bind(this))
this.router.get('/items/:id/comic-page/:page/:fileid?', LibraryItemController.middleware.bind(this), LibraryItemController.getComicPage.bind(this)) this.router.get('/items/:id/comic-page/:page/:fileid?', LibraryItemController.getComicPage.bind(this))
// //
// User Routes // User Routes