diff --git a/src/calibre/srv/content.py b/src/calibre/srv/content.py index 153e51ba4b..d2d46d1769 100644 --- a/src/calibre/srv/content.py +++ b/src/calibre/srv/content.py @@ -12,9 +12,11 @@ from io import BytesIO from calibre.db.errors import NoSuchFormat from calibre.ebooks.metadata import authors_to_string from calibre.ebooks.metadata.meta import set_metadata +from calibre.ebooks.metadata.opf2 import metadata_to_opf from calibre.library.save_to_disk import find_plugboard from calibre.srv.errors import HTTPNotFound from calibre.srv.routes import endpoint +from calibre.srv.utils import http_date from calibre.utils.config_base import tweaks from calibre.utils.date import timestampfromdt from calibre.utils.filenames import ascii_filename @@ -142,10 +144,10 @@ def get(ctx, rd, what, book_id, library_id): db = ctx.get_library(library_id) if db is None: raise HTTPNotFound('Library %r not found' % library_id) - library_id = db.server_library_id with db.safe_read_lock: if not db.has_id(book_id): raise HTTPNotFound('Book with id %r does not exist' % book_id) + library_id = db.server_library_id # in case library_id was None if what == 'thumb' or what.startswith('thumb_'): try: w, h = map(int, what.partition('_')[2].partition('x')[::2]) @@ -154,7 +156,13 @@ def get(ctx, rd, what, book_id, library_id): return cover(ctx, rd, library_id, db, book_id, width=w, height=h) elif what == 'cover': return cover(ctx, rd, library_id, db, book_id) - # TODO: Implement opf and json + elif what == 'opf': + mi = db.get_metadata(book_id, get_cover=False) + rd.outheaders['Content-Type'] = 'application/oebps-package+xml; charset=UTF-8' + rd.outheaders['Last-Modified'] = http_date(timestampfromdt(mi.last_modified)) + return metadata_to_opf(mi) + elif what == 'json': + raise NotImplementedError('TODO: Implement this') else: try: return book_fmt(ctx, rd, library_id, db, book_id, what.lower()) diff --git a/src/calibre/srv/tests/content.py b/src/calibre/srv/tests/content.py index 024c7f78f8..44c205dc06 100644 --- a/src/calibre/srv/tests/content.py +++ b/src/calibre/srv/tests/content.py @@ -6,10 +6,11 @@ from __future__ import (unicode_literals, division, absolute_import, __license__ = 'GPL v3' __copyright__ = '2015, Kovid Goyal ' -import httplib +import httplib, zlib from io import BytesIO from calibre.ebooks.metadata.epub import get_metadata +from calibre.ebooks.metadata.opf2 import OPF from calibre.srv.tests.base import LibraryBaseTest from calibre.utils.magick.draw import identify_data @@ -122,6 +123,7 @@ class ContentTest(LibraryBaseTest): self.ae(r.status, httplib.OK) self.ae(data, db.cover(1)) self.ae(r.getheader('Used-Cache'), 'no') + self.ae(r.getheader('Content-Type'), 'image/jpeg') r, data = get('cover', 1) self.ae(r.status, httplib.OK) self.ae(data, db.cover(1)) @@ -148,4 +150,18 @@ class ContentTest(LibraryBaseTest): self.ae(identify_data(data), (100, 100, 'jpeg')) self.ae(r.getheader('Used-Cache'), 'no') + # Test serving of metadata as opf + r, data = get('opf', 1) + self.ae(r.status, httplib.OK) + self.ae(r.getheader('Content-Type'), 'application/oebps-package+xml; charset=UTF-8') + self.assertIsNotNone(r.getheader('Last-Modified')) + opf = OPF(BytesIO(data), populate_spine=False, try_to_guess_cover=False) + self.ae(db.field_for('title', 1), opf.title) + self.ae(db.field_for('authors', 1), tuple(opf.authors)) + conn.request('GET', '/get/opf/1', headers={'Accept-Encoding':'gzip'}) + r = conn.getresponse() + self.ae(r.status, httplib.OK), self.ae(r.getheader('Content-Encoding'), 'gzip') + raw = r.read() + self.ae(zlib.decompress(raw, 16+zlib.MAX_WBITS), data) + # }}}