mirror of https://github.com/kiwix/libkiwix.git
Add `raw` endpoint.
As the name suggests it, this endpoint is not smart : It returns the content as it is and only if it is present (no compatibility or whatever). The only "smart" thing is to return a redirect if the entry is a redirect.
This commit is contained in:
parent
160a74f5f8
commit
dc15a9a824
|
@ -285,6 +285,9 @@ std::unique_ptr<Response> InternalServer::handle_request(const RequestContext& r
|
|||
if (startsWith(request.get_url(), "/catalog/"))
|
||||
return handle_catalog(request);
|
||||
|
||||
if (startsWith(request.get_url(), "/raw/"))
|
||||
return handle_raw(request);
|
||||
|
||||
if (request.get_url() == "/meta")
|
||||
return handle_meta(request);
|
||||
|
||||
|
@ -878,4 +881,62 @@ std::unique_ptr<Response> InternalServer::handle_content(const RequestContext& r
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<Response> InternalServer::handle_raw(const RequestContext& request)
|
||||
{
|
||||
if (m_verbose.load()) {
|
||||
printf("** running handle_raw\n");
|
||||
}
|
||||
|
||||
std::string bookName;
|
||||
std::string kind;
|
||||
try {
|
||||
bookName = request.get_url_part(1);
|
||||
kind = request.get_url_part(2);
|
||||
} catch (const std::out_of_range& e) {
|
||||
return Response::build_404(*this, request.get_full_url(), bookName, "", "");
|
||||
}
|
||||
|
||||
if (kind != "meta" && kind!= "content") {
|
||||
const std::string error_details = kind + " is not a valid request for raw content.";
|
||||
return Response::build_404(*this, request.get_full_url(), bookName, "", error_details);
|
||||
}
|
||||
|
||||
std::shared_ptr<zim::Archive> archive;
|
||||
try {
|
||||
const std::string bookId = mp_nameMapper->getIdForName(bookName);
|
||||
archive = mp_library->getArchiveById(bookId);
|
||||
} catch (const std::out_of_range& e) {}
|
||||
|
||||
if (archive == nullptr) {
|
||||
const std::string error_details = "No such book: " + bookName;
|
||||
return Response::build_404(*this, request.get_full_url(), bookName, "", error_details);
|
||||
}
|
||||
|
||||
// Remove the beggining of the path:
|
||||
// /raw/<bookName>/<kind>/foo
|
||||
// ^^^^^ ^ ^
|
||||
// 5 + 1 + 1 = 7
|
||||
auto itemPath = request.get_url().substr(bookName.size()+kind.size()+7);
|
||||
|
||||
try {
|
||||
if (kind == "meta") {
|
||||
auto item = archive->getMetadataItem(itemPath);
|
||||
return ItemResponse::build(*this, request, item, /*raw=*/true);
|
||||
} else {
|
||||
auto entry = archive->getEntryByPath(itemPath);
|
||||
if (entry.isRedirect()) {
|
||||
return build_redirect(bookName, entry.getItem(true));
|
||||
}
|
||||
return ItemResponse::build(*this, request, entry.getItem(), /*raw=*/true);
|
||||
}
|
||||
} catch (zim::EntryNotFound& e ) {
|
||||
if (m_verbose.load()) {
|
||||
printf("Failed to find %s\n", itemPath.c_str());
|
||||
}
|
||||
const std::string error_details = "Cannot find " + kind + " entry " + itemPath;
|
||||
return Response::build_404(*this, request.get_full_url(), bookName, getArchiveTitle(*archive), error_details);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -89,6 +89,7 @@ class InternalServer {
|
|||
std::unique_ptr<Response> handle_random(const RequestContext& request);
|
||||
std::unique_ptr<Response> handle_captured_external(const RequestContext& request);
|
||||
std::unique_ptr<Response> handle_content(const RequestContext& request);
|
||||
std::unique_ptr<Response> handle_raw(const RequestContext& request);
|
||||
|
||||
std::vector<std::string> search_catalog(const RequestContext& request,
|
||||
kiwix::OPDSDumper& opdsDumper);
|
||||
|
|
|
@ -185,6 +185,9 @@ const ResourceCollection resources200Compressible{
|
|||
|
||||
{ WITH_ETAG, "/ROOT/zimfile/A/index" },
|
||||
{ WITH_ETAG, "/ROOT/zimfile/A/Ray_Charles" },
|
||||
|
||||
{ WITH_ETAG, "/ROOT/raw/zimfile/content/A/index" },
|
||||
{ WITH_ETAG, "/ROOT/raw/zimfile/content/A/Ray_Charles" },
|
||||
};
|
||||
|
||||
const ResourceCollection resources200Uncompressible{
|
||||
|
@ -208,6 +211,10 @@ const ResourceCollection resources200Uncompressible{
|
|||
{ WITH_ETAG, "/ROOT/corner_cases/A/empty.html" },
|
||||
{ WITH_ETAG, "/ROOT/corner_cases/-/empty.css" },
|
||||
{ WITH_ETAG, "/ROOT/corner_cases/-/empty.js" },
|
||||
|
||||
// The title and creator are too small to be compressed
|
||||
{ WITH_ETAG, "/ROOT/raw/zimfile/meta/Creator" },
|
||||
{ WITH_ETAG, "/ROOT/raw/zimfile/meta/Title" },
|
||||
};
|
||||
|
||||
ResourceCollection all200Resources()
|
||||
|
@ -313,6 +320,32 @@ TEST_F(ServerTest, BookMainPageIsRedirectedToArticleIndex)
|
|||
ASSERT_EQ("/ROOT/zimfile/A/index", g->get_header_value("Location"));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ServerTest, RawEntry)
|
||||
{
|
||||
auto p = zfs1_->GET("/ROOT/raw/zimfile/meta/Title");
|
||||
EXPECT_EQ(200, p->status);
|
||||
EXPECT_EQ(p->body, std::string("Ray Charles"));
|
||||
|
||||
p = zfs1_->GET("/ROOT/raw/zimfile/meta/Creator");
|
||||
EXPECT_EQ(200, p->status);
|
||||
EXPECT_EQ(p->body, std::string("Wikipedia"));
|
||||
|
||||
// The raw content of Ray_Charles returned by the server is
|
||||
// the same as the one in the zim file.
|
||||
auto archive = zim::Archive("./test/zimfile.zim");
|
||||
auto entry = archive.getEntryByPath("A/Ray_Charles");
|
||||
p = zfs1_->GET("/ROOT/raw/zimfile/content/A/Ray_Charles");
|
||||
EXPECT_EQ(200, p->status);
|
||||
EXPECT_EQ(std::string(p->body), std::string(entry.getItem(true).getData()));
|
||||
|
||||
// ... but the "normal" content is not
|
||||
p = zfs1_->GET("/ROOT/zimfile/A/Ray_Charles");
|
||||
EXPECT_EQ(200, p->status);
|
||||
EXPECT_NE(std::string(p->body), std::string(entry.getItem(true).getData()));
|
||||
EXPECT_TRUE(p->body.find("taskbar") != std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(ServerTest, HeadMethodIsSupported)
|
||||
{
|
||||
for ( const Resource& res : all200Resources() )
|
||||
|
|
Loading…
Reference in New Issue