Introduce a ServerConfiguration object.

It is used to store the server configuration instead of passing (a lot of)
arguments to functions/creators.

Please note that this remove the thread protected on m_verbose.
m_verbose is initialized once and never modified, be don't need to protect
access.
This commit is contained in:
Matthieu Gautier 2022-10-06 11:29:24 +02:00
parent 24472e03dd
commit 85f58b8e01
7 changed files with 160 additions and 165 deletions

View File

@ -29,43 +29,60 @@ namespace kiwix
class NameMapper; class NameMapper;
class InternalServer; class InternalServer;
class Server { class ServerConfiguration {
public: public:
/** ServerConfiguration(Library* library, NameMapper* nameMapper=nullptr)
* The default constructor. : mp_library(library),
* mp_nameMapper(nameMapper)
* @param library The library to serve. {}
*/
Server(Library* library, NameMapper* nameMapper=nullptr);
virtual ~Server(); ServerConfiguration& setRoot(const std::string& root);
ServerConfiguration& setAddress(const std::string& addr) {
m_addr = addr;
return *this;
}
/** ServerConfiguration& setPort(int port) {
* Serve the content. m_port = port;
*/ return *this;
bool start(); }
/** ServerConfiguration& setNbThreads(int threads) {
* Stop the daemon. m_nbThreads = threads;
*/ return *this;
void stop(); }
void setRoot(const std::string& root); ServerConfiguration& setMultiZimSearchLimit(unsigned int limit) {
void setAddress(const std::string& addr) { m_addr = addr; } m_multizimSearchLimit = limit;
void setPort(int port) { m_port = port; } return *this;
void setNbThreads(int threads) { m_nbThreads = threads; } }
void setMultiZimSearchLimit(unsigned int limit) { m_multizimSearchLimit = limit; }
void setIpConnectionLimit(int limit) { m_ipConnectionLimit = limit; } ServerConfiguration& setIpConnectionLimit(int limit) {
void setVerbose(bool verbose) { m_verbose = verbose; } m_ipConnectionLimit = limit;
void setIndexTemplateString(const std::string& indexTemplateString) { m_indexTemplateString = indexTemplateString; } return *this;
void setTaskbar(bool withTaskbar, bool withLibraryButton) }
{ m_withTaskbar = withTaskbar; m_withLibraryButton = withLibraryButton; }
void setBlockExternalLinks(bool blockExternalLinks) ServerConfiguration& setVerbose(bool verbose) {
{ m_blockExternalLinks = blockExternalLinks; } m_verbose = verbose;
int getPort(); return *this;
std::string getAddress(); }
ServerConfiguration& setIndexTemplateString(const std::string& indexTemplateString) {
m_indexTemplateString = indexTemplateString;
return *this;
}
ServerConfiguration& setTaskbar(bool withTaskbar, bool withLibraryButton) {
m_withTaskbar = withTaskbar;
m_withLibraryButton = withLibraryButton;
return *this;
}
ServerConfiguration& setBlockExternalLinks(bool blockExternalLinks) {
m_blockExternalLinks = blockExternalLinks;
return *this;
}
protected:
Library* mp_library; Library* mp_library;
NameMapper* mp_nameMapper; NameMapper* mp_nameMapper;
std::string m_root = ""; std::string m_root = "";
@ -79,6 +96,36 @@ namespace kiwix
bool m_withLibraryButton = true; bool m_withLibraryButton = true;
bool m_blockExternalLinks = false; bool m_blockExternalLinks = false;
int m_ipConnectionLimit = 0; int m_ipConnectionLimit = 0;
};
class Server {
public:
/**
* The default constructor.
*
* @param library The library to serve.
*/
Server(const ServerConfiguration& configuration);
virtual ~Server();
/**
* Serve the content.
*/
bool start();
/**
* Stop the daemon.
*/
void stop();
int getPort();
std::string getAddress();
protected:
ServerConfiguration m_configuration;
std::unique_ptr<InternalServer> mp_server; std::unique_ptr<InternalServer> mp_server;
}; };
} }

View File

@ -29,9 +29,8 @@
namespace kiwix { namespace kiwix {
Server::Server(Library* library, NameMapper* nameMapper) : Server::Server(const ServerConfiguration& configuration) :
mp_library(library), m_configuration(configuration),
mp_nameMapper(nameMapper),
mp_server(nullptr) mp_server(nullptr)
{ {
} }
@ -39,20 +38,7 @@ Server::Server(Library* library, NameMapper* nameMapper) :
Server::~Server() = default; Server::~Server() = default;
bool Server::start() { bool Server::start() {
mp_server.reset(new InternalServer( mp_server.reset(new InternalServer(m_configuration));
mp_library,
mp_nameMapper,
m_addr,
m_port,
m_root,
m_nbThreads,
m_multizimSearchLimit,
m_verbose,
m_withTaskbar,
m_withLibraryButton,
m_blockExternalLinks,
m_indexTemplateString,
m_ipConnectionLimit));
return mp_server->start(); return mp_server->start();
} }
@ -63,7 +49,7 @@ void Server::stop() {
} }
} }
void Server::setRoot(const std::string& root) ServerConfiguration& ServerConfiguration::setRoot(const std::string& root)
{ {
m_root = root; m_root = root;
if (m_root[0] != '/') { if (m_root[0] != '/') {
@ -72,6 +58,7 @@ void Server::setRoot(const std::string& root)
if (m_root.back() == '/') { if (m_root.back() == '/') {
m_root.erase(m_root.size() - 1); m_root.erase(m_root.size() - 1);
} }
return *this;
} }
int Server::getPort() int Server::getPort()

View File

@ -276,7 +276,7 @@ std::pair<std::string, Library::BookIdSet> InternalServer::selectBooks(const Req
// Check for filtering // Check for filtering
Filter filter = get_search_filter(request, "books.filter."); Filter filter = get_search_filter(request, "books.filter.");
auto id_vec = mp_library->filter(filter); auto id_vec = m_configuration.mp_library->filter(filter);
if (id_vec.empty()) { if (id_vec.empty()) {
throw Error(nonParameterizedMessage("no-book-found")); throw Error(nonParameterizedMessage("no-book-found"));
} }
@ -288,7 +288,7 @@ std::pair<std::string, Library::BookIdSet> InternalServer::selectBooks(const Req
SearchInfo InternalServer::getSearchInfo(const RequestContext& request) const SearchInfo InternalServer::getSearchInfo(const RequestContext& request) const
{ {
auto bookIds = selectBooks(request); auto bookIds = selectBooks(request);
checkBookNumber(bookIds.second, m_multizimSearchLimit); checkBookNumber(bookIds.second, m_configuration.m_multizimSearchLimit);
auto pattern = request.get_optional_param<std::string>("pattern", ""); auto pattern = request.get_optional_param<std::string>("pattern", "");
GeoQuery geoQuery; GeoQuery geoQuery;
@ -366,35 +366,14 @@ public:
}; };
InternalServer::InternalServer(Library* library, InternalServer::InternalServer(const ServerConfiguration& configuration) :
NameMapper* nameMapper, m_configuration(configuration),
std::string addr, m_root(normalizeRootUrl(configuration.m_root)),
int port, m_indexTemplateString(configuration.m_indexTemplateString.empty() ? RESOURCE::templates::index_html : configuration.m_indexTemplateString),
std::string root, mp_nameMapper(configuration.mp_nameMapper ? configuration.mp_nameMapper : &defaultNameMapper),
int nbThreads,
unsigned int multizimSearchLimit,
bool verbose,
bool withTaskbar,
bool withLibraryButton,
bool blockExternalLinks,
std::string indexTemplateString,
int ipConnectionLimit) :
m_addr(addr),
m_port(port),
m_root(normalizeRootUrl(root)),
m_nbThreads(nbThreads),
m_multizimSearchLimit(multizimSearchLimit),
m_verbose(verbose),
m_withTaskbar(withTaskbar),
m_withLibraryButton(withLibraryButton),
m_blockExternalLinks(blockExternalLinks),
m_indexTemplateString(indexTemplateString.empty() ? RESOURCE::templates::index_html : indexTemplateString),
m_ipConnectionLimit(ipConnectionLimit),
mp_daemon(nullptr), mp_daemon(nullptr),
mp_library(library),
mp_nameMapper(nameMapper ? nameMapper : &defaultNameMapper),
searchCache(getEnvVar<int>("KIWIX_SEARCH_CACHE_SIZE", DEFAULT_CACHE_SIZE)), searchCache(getEnvVar<int>("KIWIX_SEARCH_CACHE_SIZE", DEFAULT_CACHE_SIZE)),
suggestionSearcherCache(getEnvVar<int>("KIWIX_SUGGESTION_SEARCHER_CACHE_SIZE", std::max((unsigned int) (mp_library->getBookCount(true, true)*0.1), 1U))), suggestionSearcherCache(getEnvVar<int>("KIWIX_SUGGESTION_SEARCHER_CACHE_SIZE", std::max((unsigned int) (m_configuration.mp_library->getBookCount(true, true)*0.1), 1U))),
m_customizedResources(new CustomizedResources) m_customizedResources(new CustomizedResources)
{} {}
@ -406,13 +385,13 @@ bool InternalServer::start() {
#else #else
int flags = MHD_USE_POLL_INTERNALLY; int flags = MHD_USE_POLL_INTERNALLY;
#endif #endif
if (m_verbose.load()) if (m_configuration.m_verbose)
flags |= MHD_USE_DEBUG; flags |= MHD_USE_DEBUG;
struct sockaddr_in sockAddr; struct sockaddr_in sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr)); memset(&sockAddr, 0, sizeof(sockAddr));
sockAddr.sin_family = AF_INET; sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(m_port); sockAddr.sin_port = htons(m_configuration.m_port);
if (m_addr.empty()) { if (m_addr.empty()) {
if (0 != INADDR_ANY) { if (0 != INADDR_ANY) {
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
@ -425,17 +404,17 @@ bool InternalServer::start() {
} }
} }
mp_daemon = MHD_start_daemon(flags, mp_daemon = MHD_start_daemon(flags,
m_port, m_configuration.m_port,
NULL, NULL,
NULL, NULL,
&staticHandlerCallback, &staticHandlerCallback,
this, this,
MHD_OPTION_SOCK_ADDR, &sockAddr, MHD_OPTION_SOCK_ADDR, &sockAddr,
MHD_OPTION_THREAD_POOL_SIZE, m_nbThreads, MHD_OPTION_THREAD_POOL_SIZE, m_configuration.m_nbThreads,
MHD_OPTION_PER_IP_CONNECTION_LIMIT, m_ipConnectionLimit, MHD_OPTION_PER_IP_CONNECTION_LIMIT, m_configuration.m_ipConnectionLimit,
MHD_OPTION_END); MHD_OPTION_END);
if (mp_daemon == nullptr) { if (mp_daemon == nullptr) {
std::cerr << "Unable to instantiate the HTTP daemon. The port " << m_port std::cerr << "Unable to instantiate the HTTP daemon. The port " << m_configuration.m_port
<< " is maybe already occupied or need more permissions to be open. " << " is maybe already occupied or need more permissions to be open. "
"Please try as root or with a port number higher or equal to 1024." "Please try as root or with a port number higher or equal to 1024."
<< std::endl; << std::endl;
@ -481,14 +460,14 @@ MHD_Result InternalServer::handlerCallback(struct MHD_Connection* connection,
void** cont_cls) void** cont_cls)
{ {
auto start_time = std::chrono::steady_clock::now(); auto start_time = std::chrono::steady_clock::now();
if (m_verbose.load() ) { if (m_configuration.m_verbose) {
printf("======================\n"); printf("======================\n");
printf("Requesting : \n"); printf("Requesting : \n");
printf("full_url : %s\n", url); printf("full_url : %s\n", url);
} }
RequestContext request(connection, m_root, url, method, version); RequestContext request(connection, m_root, url, method, version);
if (m_verbose.load() ) { if (m_configuration.m_verbose) {
request.print_debug_info(); request.print_debug_info();
} }
/* Unexpected method */ /* Unexpected method */
@ -504,7 +483,7 @@ MHD_Result InternalServer::handlerCallback(struct MHD_Connection* connection,
if (response->getReturnCode() == MHD_HTTP_INTERNAL_SERVER_ERROR) { if (response->getReturnCode() == MHD_HTTP_INTERNAL_SERVER_ERROR) {
printf("========== INTERNAL ERROR !! ============\n"); printf("========== INTERNAL ERROR !! ============\n");
if (!m_verbose.load()) { if (!m_configuration.m_verbose) {
printf("Requesting : \n"); printf("Requesting : \n");
printf("full_url : %s\n", url); printf("full_url : %s\n", url);
request.print_debug_info(); request.print_debug_info();
@ -517,7 +496,7 @@ MHD_Result InternalServer::handlerCallback(struct MHD_Connection* connection,
auto ret = response->send(request, connection); auto ret = response->send(request, connection);
auto end_time = std::chrono::steady_clock::now(); auto end_time = std::chrono::steady_clock::now();
auto time_span = std::chrono::duration_cast<std::chrono::duration<double>>(end_time - start_time); auto time_span = std::chrono::duration_cast<std::chrono::duration<double>>(end_time - start_time);
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("Request time : %fs\n", time_span.count()); printf("Request time : %fs\n", time_span.count());
printf("----------------------\n"); printf("----------------------\n");
} }
@ -650,7 +629,7 @@ class InternalServer::LockableSuggestionSearcher : public zim::SuggestionSearche
std::unique_ptr<Response> InternalServer::handle_suggest(const RequestContext& request) std::unique_ptr<Response> InternalServer::handle_suggest(const RequestContext& request)
{ {
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("** running handle_suggest\n"); printf("** running handle_suggest\n");
} }
@ -664,7 +643,7 @@ std::unique_ptr<Response> InternalServer::handle_suggest(const RequestContext& r
try { try {
bookName = request.get_argument("content"); bookName = request.get_argument("content");
bookId = mp_nameMapper->getIdForName(bookName); bookId = mp_nameMapper->getIdForName(bookName);
archive = mp_library->getArchiveById(bookId); archive = m_configuration.mp_library->getArchiveById(bookId);
} catch (const std::out_of_range&) { } catch (const std::out_of_range&) {
// error handled by the archive == nullptr check below // error handled by the archive == nullptr check below
} }
@ -681,7 +660,7 @@ std::unique_ptr<Response> InternalServer::handle_suggest(const RequestContext& r
count = 10; count = 10;
} }
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("Searching suggestions for: \"%s\"\n", queryString.c_str()); printf("Searching suggestions for: \"%s\"\n", queryString.c_str());
} }
@ -734,21 +713,21 @@ std::unique_ptr<Response> InternalServer::handle_suggest(const RequestContext& r
std::unique_ptr<Response> InternalServer::handle_viewer_settings(const RequestContext& request) std::unique_ptr<Response> InternalServer::handle_viewer_settings(const RequestContext& request)
{ {
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("** running handle_viewer_settings\n"); printf("** running handle_viewer_settings\n");
} }
const kainjow::mustache::object data{ const kainjow::mustache::object data{
{"enable_toolbar", m_withTaskbar ? "true" : "false" }, {"enable_toolbar", m_configuration.m_withTaskbar ? "true" : "false" },
{"enable_link_blocking", m_blockExternalLinks ? "true" : "false" }, {"enable_link_blocking", m_configuration.m_blockExternalLinks ? "true" : "false" },
{"enable_library_button", m_withLibraryButton ? "true" : "false" } {"enable_library_button", m_configuration.m_withLibraryButton ? "true" : "false" }
}; };
return ContentResponse::build(*this, RESOURCE::templates::viewer_settings_js, data, "application/javascript; charset=utf-8"); return ContentResponse::build(*this, RESOURCE::templates::viewer_settings_js, data, "application/javascript; charset=utf-8");
} }
std::unique_ptr<Response> InternalServer::handle_skin(const RequestContext& request) std::unique_ptr<Response> InternalServer::handle_skin(const RequestContext& request)
{ {
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("** running handle_skin\n"); printf("** running handle_skin\n");
} }
@ -771,7 +750,7 @@ std::unique_ptr<Response> InternalServer::handle_skin(const RequestContext& requ
std::unique_ptr<Response> InternalServer::handle_search(const RequestContext& request) std::unique_ptr<Response> InternalServer::handle_search(const RequestContext& request)
{ {
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("** running handle_search\n"); printf("** running handle_search\n");
} }
@ -793,14 +772,14 @@ std::unique_ptr<Response> InternalServer::handle_search(const RequestContext& re
/* Make the search */ /* Make the search */
// Try to get a search from the searchInfo, else build it // Try to get a search from the searchInfo, else build it
auto searcher = mp_library->getSearcherByIds(bookIds); auto searcher = m_configuration.mp_library->getSearcherByIds(bookIds);
auto lock(searcher->getLock()); auto lock(searcher->getLock());
std::shared_ptr<zim::Search> search; std::shared_ptr<zim::Search> search;
try { try {
search = searchCache.getOrPut(searchInfo, search = searchCache.getOrPut(searchInfo,
[=](){ [=](){
return make_shared<zim::Search>(searcher->search(searchInfo.getZimQuery(m_verbose.load()))); return make_shared<zim::Search>(searcher->search(searchInfo.getZimQuery(m_configuration.m_verbose)));
} }
); );
} catch(std::runtime_error& e) { } catch(std::runtime_error& e) {
@ -818,7 +797,7 @@ std::unique_ptr<Response> InternalServer::handle_search(const RequestContext& re
if(bookIds.size() == 1) { if(bookIds.size() == 1) {
auto bookId = *bookIds.begin(); auto bookId = *bookIds.begin();
auto bookName = mp_nameMapper->getNameForId(bookId); auto bookName = mp_nameMapper->getNameForId(bookId);
response += TaskbarInfo(bookName, mp_library->getArchiveById(bookId).get()); response += TaskbarInfo(bookName, m_configuration.mp_library->getArchiveById(bookId).get());
} }
*/ */
return response; return response;
@ -842,7 +821,7 @@ std::unique_ptr<Response> InternalServer::handle_search(const RequestContext& re
} }
/* Get the results */ /* Get the results */
SearchRenderer renderer(search->getResults(start-1, pageLength), mp_nameMapper, mp_library, start, SearchRenderer renderer(search->getResults(start-1, pageLength), mp_nameMapper, m_configuration.mp_library, start,
search->getEstimatedMatches()); search->getEstimatedMatches());
renderer.setSearchPattern(searchInfo.pattern); renderer.setSearchPattern(searchInfo.pattern);
renderer.setSearchBookQuery(searchInfo.bookFilterQuery); renderer.setSearchBookQuery(searchInfo.bookFilterQuery);
@ -859,7 +838,7 @@ std::unique_ptr<Response> InternalServer::handle_search(const RequestContext& re
if(bookIds.size() == 1) { if(bookIds.size() == 1) {
auto bookId = *bookIds.begin(); auto bookId = *bookIds.begin();
auto bookName = mp_nameMapper->getNameForId(bookId); auto bookName = mp_nameMapper->getNameForId(bookId);
response->set_taskbar(bookName, mp_library->getArchiveById(bookId).get()); response->set_taskbar(bookName, m_configuration.mp_library->getArchiveById(bookId).get());
} }
*/ */
return std::move(response); return std::move(response);
@ -872,7 +851,7 @@ std::unique_ptr<Response> InternalServer::handle_search(const RequestContext& re
std::unique_ptr<Response> InternalServer::handle_random(const RequestContext& request) std::unique_ptr<Response> InternalServer::handle_random(const RequestContext& request)
{ {
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("** running handle_random\n"); printf("** running handle_random\n");
} }
@ -886,7 +865,7 @@ std::unique_ptr<Response> InternalServer::handle_random(const RequestContext& re
try { try {
bookName = request.get_argument("content"); bookName = request.get_argument("content");
const std::string bookId = mp_nameMapper->getIdForName(bookName); const std::string bookId = mp_nameMapper->getIdForName(bookName);
archive = mp_library->getArchiveById(bookId); archive = m_configuration.mp_library->getArchiveById(bookId);
} catch (const std::out_of_range&) { } catch (const std::out_of_range&) {
// error handled by the archive == nullptr check below // error handled by the archive == nullptr check below
} }
@ -924,7 +903,7 @@ std::unique_ptr<Response> InternalServer::handle_captured_external(const Request
std::unique_ptr<Response> InternalServer::handle_catch(const RequestContext& request) std::unique_ptr<Response> InternalServer::handle_catch(const RequestContext& request)
{ {
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("** running handle_catch\n"); printf("** running handle_catch\n");
} }
@ -938,7 +917,7 @@ std::unique_ptr<Response> InternalServer::handle_catch(const RequestContext& req
std::unique_ptr<Response> InternalServer::handle_catalog(const RequestContext& request) std::unique_ptr<Response> InternalServer::handle_catalog(const RequestContext& request)
{ {
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("** running handle_catalog"); printf("** running handle_catalog");
} }
@ -967,13 +946,13 @@ std::unique_ptr<Response> InternalServer::handle_catalog(const RequestContext& r
} }
zim::Uuid uuid; zim::Uuid uuid;
kiwix::OPDSDumper opdsDumper(mp_library, mp_nameMapper); kiwix::OPDSDumper opdsDumper(m_configuration.mp_library, mp_nameMapper);
opdsDumper.setRootLocation(m_root); opdsDumper.setRootLocation(m_root);
opdsDumper.setLibraryId(m_library_id); opdsDumper.setLibraryId(m_library_id);
std::vector<std::string> bookIdsToDump; std::vector<std::string> bookIdsToDump;
if (url == "root.xml") { if (url == "root.xml") {
uuid = zim::Uuid::generate(host); uuid = zim::Uuid::generate(host);
bookIdsToDump = mp_library->filter(kiwix::Filter().valid(true).local(true).remote(true)); bookIdsToDump = m_configuration.mp_library->filter(kiwix::Filter().valid(true).local(true).remote(true));
} else if (url == "search") { } else if (url == "search") {
bookIdsToDump = search_catalog(request, opdsDumper); bookIdsToDump = search_catalog(request, opdsDumper);
uuid = zim::Uuid::generate(); uuid = zim::Uuid::generate();
@ -994,7 +973,7 @@ InternalServer::search_catalog(const RequestContext& request,
const std::string q = filter.hasQuery() const std::string q = filter.hasQuery()
? filter.getQuery() ? filter.getQuery()
: "<Empty query>"; : "<Empty query>";
std::vector<std::string> bookIdsToDump = mp_library->filter(filter); std::vector<std::string> bookIdsToDump = m_configuration.mp_library->filter(filter);
const auto totalResults = bookIdsToDump.size(); const auto totalResults = bookIdsToDump.size();
const size_t count = request.get_optional_param("count", 10UL); const size_t count = request.get_optional_param("count", 10UL);
const size_t startIndex = request.get_optional_param("start", 0UL); const size_t startIndex = request.get_optional_param("start", 0UL);
@ -1030,7 +1009,7 @@ std::unique_ptr<Response> InternalServer::handle_content(const RequestContext& r
{ {
const std::string url = request.get_url(); const std::string url = request.get_url();
const std::string pattern = url.substr((url.find_last_of('/'))+1); const std::string pattern = url.substr((url.find_last_of('/'))+1);
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("** running handle_content\n"); printf("** running handle_content\n");
} }
@ -1042,7 +1021,7 @@ std::unique_ptr<Response> InternalServer::handle_content(const RequestContext& r
std::shared_ptr<zim::Archive> archive; std::shared_ptr<zim::Archive> archive;
try { try {
const std::string bookId = mp_nameMapper->getIdForName(bookName); const std::string bookId = mp_nameMapper->getIdForName(bookName);
archive = mp_library->getArchiveById(bookId); archive = m_configuration.mp_library->getArchiveById(bookId);
} catch (const std::out_of_range& e) {} } catch (const std::out_of_range& e) {}
if (archive == nullptr) { if (archive == nullptr) {
@ -1071,14 +1050,14 @@ std::unique_ptr<Response> InternalServer::handle_content(const RequestContext& r
} }
auto response = ItemResponse::build(*this, request, entry.getItem()); auto response = ItemResponse::build(*this, request, entry.getItem());
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("Found %s\n", entry.getPath().c_str()); printf("Found %s\n", entry.getPath().c_str());
printf("mimeType: %s\n", entry.getItem(true).getMimetype().c_str()); printf("mimeType: %s\n", entry.getItem(true).getMimetype().c_str());
} }
return response; return response;
} catch(zim::EntryNotFound& e) { } catch(zim::EntryNotFound& e) {
if (m_verbose.load()) if (m_configuration.m_verbose)
printf("Failed to find %s\n", urlStr.c_str()); printf("Failed to find %s\n", urlStr.c_str());
std::string searchURL = m_root + "/search?content=" + bookName + "&pattern=" + kiwix::urlEncode(pattern, true); std::string searchURL = m_root + "/search?content=" + bookName + "&pattern=" + kiwix::urlEncode(pattern, true);
@ -1091,7 +1070,7 @@ std::unique_ptr<Response> InternalServer::handle_content(const RequestContext& r
std::unique_ptr<Response> InternalServer::handle_raw(const RequestContext& request) std::unique_ptr<Response> InternalServer::handle_raw(const RequestContext& request)
{ {
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("** running handle_raw\n"); printf("** running handle_raw\n");
} }
@ -1114,7 +1093,7 @@ std::unique_ptr<Response> InternalServer::handle_raw(const RequestContext& reque
std::shared_ptr<zim::Archive> archive; std::shared_ptr<zim::Archive> archive;
try { try {
const std::string bookId = mp_nameMapper->getIdForName(bookName); const std::string bookId = mp_nameMapper->getIdForName(bookName);
archive = mp_library->getArchiveById(bookId); archive = m_configuration.mp_library->getArchiveById(bookId);
} catch (const std::out_of_range& e) {} } catch (const std::out_of_range& e) {}
if (archive == nullptr) { if (archive == nullptr) {
@ -1141,7 +1120,7 @@ std::unique_ptr<Response> InternalServer::handle_raw(const RequestContext& reque
return ItemResponse::build(*this, request, entry.getItem()); return ItemResponse::build(*this, request, entry.getItem());
} }
} catch (zim::EntryNotFound& e ) { } catch (zim::EntryNotFound& e ) {
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("Failed to find %s\n", itemPath.c_str()); printf("Failed to find %s\n", itemPath.c_str());
} }
return HTTP404Response(*this, request) return HTTP404Response(*this, request)
@ -1157,13 +1136,13 @@ bool InternalServer::isLocallyCustomizedResource(const std::string& url) const
std::unique_ptr<Response> InternalServer::handle_locally_customized_resource(const RequestContext& request) std::unique_ptr<Response> InternalServer::handle_locally_customized_resource(const RequestContext& request)
{ {
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("** running handle_locally_customized_resource\n"); printf("** running handle_locally_customized_resource\n");
} }
const CustomizedResourceData& crd = m_customizedResources->at(request.get_url()); const CustomizedResourceData& crd = m_customizedResources->at(request.get_url());
if (m_verbose.load()) { if (m_configuration.m_verbose) {
std::cout << "Reading " << crd.resourceFilePath << std::endl; std::cout << "Reading " << crd.resourceFilePath << std::endl;
} }
const auto resourceData = getFileContent(crd.resourceFilePath); const auto resourceData = getFileContent(crd.resourceFilePath);

View File

@ -27,6 +27,7 @@ extern "C" {
#include "library.h" #include "library.h"
#include "name_mapper.h" #include "name_mapper.h"
#include "server.h"
#include <zim/search.h> #include <zim/search.h>
#include <zim/suggestion.h> #include <zim/suggestion.h>
@ -92,19 +93,7 @@ class OPDSDumper;
class InternalServer { class InternalServer {
public: public:
InternalServer(Library* library, InternalServer(const ServerConfiguration& configuration);
NameMapper* nameMapper,
std::string addr,
int port,
std::string root,
int nbThreads,
unsigned int multizimSearchLimit,
bool verbose,
bool withTaskbar,
bool withLibraryButton,
bool blockExternalLinks,
std::string indexTemplateString,
int ipConnectionLimit);
virtual ~InternalServer(); virtual ~InternalServer();
MHD_Result handlerCallback(struct MHD_Connection* connection, MHD_Result handlerCallback(struct MHD_Connection* connection,
@ -117,7 +106,7 @@ class InternalServer {
bool start(); bool start();
void stop(); void stop();
std::string getAddress() { return m_addr; } std::string getAddress() { return m_addr; }
int getPort() { return m_port; } int getPort() { return m_configuration.m_port; }
private: // functions private: // functions
std::unique_ptr<Response> handle_request(const RequestContext& request); std::unique_ptr<Response> handle_request(const RequestContext& request);
@ -160,21 +149,12 @@ class InternalServer {
typedef ConcurrentCache<std::string, std::shared_ptr<LockableSuggestionSearcher>> SuggestionSearcherCache; typedef ConcurrentCache<std::string, std::shared_ptr<LockableSuggestionSearcher>> SuggestionSearcherCache;
private: // data private: // data
ServerConfiguration m_configuration;
std::string m_addr; std::string m_addr;
int m_port;
std::string m_root; std::string m_root;
int m_nbThreads;
unsigned int m_multizimSearchLimit;
std::atomic_bool m_verbose;
bool m_withTaskbar;
bool m_withLibraryButton;
bool m_blockExternalLinks;
std::string m_indexTemplateString; std::string m_indexTemplateString;
int m_ipConnectionLimit;
struct MHD_Daemon* mp_daemon;
Library* mp_library;
NameMapper* mp_nameMapper; NameMapper* mp_nameMapper;
struct MHD_Daemon* mp_daemon;
SearchCache searchCache; SearchCache searchCache;
SuggestionSearcherCache suggestionSearcherCache; SuggestionSearcherCache suggestionSearcherCache;

View File

@ -35,7 +35,7 @@ namespace kiwix {
std::unique_ptr<Response> InternalServer::handle_catalog_v2(const RequestContext& request) std::unique_ptr<Response> InternalServer::handle_catalog_v2(const RequestContext& request)
{ {
if (m_verbose.load()) { if (m_configuration.m_verbose) {
printf("** running handle_catalog_v2"); printf("** running handle_catalog_v2");
} }
@ -50,7 +50,7 @@ std::unique_ptr<Response> InternalServer::handle_catalog_v2(const RequestContext
if (url == "root.xml") { if (url == "root.xml") {
return handle_catalog_v2_root(request); return handle_catalog_v2_root(request);
} else if (url == "searchdescription.xml") { } else if (url == "searchdescription.xml") {
const std::string endpoint_root = m_root + "/catalog/v2"; const std::string endpoint_root = m_configuration.m_root + "/catalog/v2";
return ContentResponse::build(*this, return ContentResponse::build(*this,
RESOURCE::catalog_v2_searchdescription_xml, RESOURCE::catalog_v2_searchdescription_xml,
kainjow::mustache::object({{"endpoint_root", endpoint_root}}), kainjow::mustache::object({{"endpoint_root", endpoint_root}}),
@ -82,7 +82,7 @@ std::unique_ptr<Response> InternalServer::handle_catalog_v2_root(const RequestCo
RESOURCE::templates::catalog_v2_root_xml, RESOURCE::templates::catalog_v2_root_xml,
kainjow::mustache::object{ kainjow::mustache::object{
{"date", gen_date_str()}, {"date", gen_date_str()},
{"endpoint_root", m_root + "/catalog/v2"}, {"endpoint_root", m_configuration.m_root + "/catalog/v2"},
{"feed_id", gen_uuid(m_library_id)}, {"feed_id", gen_uuid(m_library_id)},
{"all_entries_feed_id", gen_uuid(m_library_id + "/entries")}, {"all_entries_feed_id", gen_uuid(m_library_id + "/entries")},
{"partial_entries_feed_id", gen_uuid(m_library_id + "/partial_entries")}, {"partial_entries_feed_id", gen_uuid(m_library_id + "/partial_entries")},
@ -95,8 +95,8 @@ std::unique_ptr<Response> InternalServer::handle_catalog_v2_root(const RequestCo
std::unique_ptr<Response> InternalServer::handle_catalog_v2_entries(const RequestContext& request, bool partial) std::unique_ptr<Response> InternalServer::handle_catalog_v2_entries(const RequestContext& request, bool partial)
{ {
OPDSDumper opdsDumper(mp_library, mp_nameMapper); OPDSDumper opdsDumper(m_configuration.mp_library, m_configuration.mp_nameMapper);
opdsDumper.setRootLocation(m_root); opdsDumper.setRootLocation(m_configuration.m_root);
opdsDumper.setLibraryId(m_library_id); opdsDumper.setLibraryId(m_library_id);
const auto bookIds = search_catalog(request, opdsDumper); const auto bookIds = search_catalog(request, opdsDumper);
const auto opdsFeed = opdsDumper.dumpOPDSFeedV2(bookIds, request.get_query(), partial); const auto opdsFeed = opdsDumper.dumpOPDSFeedV2(bookIds, request.get_query(), partial);
@ -110,14 +110,14 @@ std::unique_ptr<Response> InternalServer::handle_catalog_v2_entries(const Reques
std::unique_ptr<Response> InternalServer::handle_catalog_v2_complete_entry(const RequestContext& request, const std::string& entryId) std::unique_ptr<Response> InternalServer::handle_catalog_v2_complete_entry(const RequestContext& request, const std::string& entryId)
{ {
try { try {
mp_library->getBookById(entryId); m_configuration.mp_library->getBookById(entryId);
} catch (const std::out_of_range&) { } catch (const std::out_of_range&) {
return HTTP404Response(*this, request) return HTTP404Response(*this, request)
+ urlNotFoundMsg; + urlNotFoundMsg;
} }
OPDSDumper opdsDumper(mp_library, mp_nameMapper); OPDSDumper opdsDumper(m_configuration.mp_library, m_configuration.mp_nameMapper);
opdsDumper.setRootLocation(m_root); opdsDumper.setRootLocation(m_configuration.m_root);
opdsDumper.setLibraryId(m_library_id); opdsDumper.setLibraryId(m_library_id);
const auto opdsFeed = opdsDumper.dumpOPDSCompleteEntry(entryId); const auto opdsFeed = opdsDumper.dumpOPDSCompleteEntry(entryId);
return ContentResponse::build( return ContentResponse::build(
@ -129,8 +129,8 @@ std::unique_ptr<Response> InternalServer::handle_catalog_v2_complete_entry(const
std::unique_ptr<Response> InternalServer::handle_catalog_v2_categories(const RequestContext& request) std::unique_ptr<Response> InternalServer::handle_catalog_v2_categories(const RequestContext& request)
{ {
OPDSDumper opdsDumper(mp_library, mp_nameMapper); OPDSDumper opdsDumper(m_configuration.mp_library, m_configuration.mp_nameMapper);
opdsDumper.setRootLocation(m_root); opdsDumper.setRootLocation(m_configuration.m_root);
opdsDumper.setLibraryId(m_library_id); opdsDumper.setLibraryId(m_library_id);
return ContentResponse::build( return ContentResponse::build(
*this, *this,
@ -141,8 +141,8 @@ std::unique_ptr<Response> InternalServer::handle_catalog_v2_categories(const Req
std::unique_ptr<Response> InternalServer::handle_catalog_v2_languages(const RequestContext& request) std::unique_ptr<Response> InternalServer::handle_catalog_v2_languages(const RequestContext& request)
{ {
OPDSDumper opdsDumper(mp_library, mp_nameMapper); OPDSDumper opdsDumper(m_configuration.mp_library, m_configuration.mp_nameMapper);
opdsDumper.setRootLocation(m_root); opdsDumper.setRootLocation(m_configuration.m_root);
opdsDumper.setLibraryId(m_library_id); opdsDumper.setLibraryId(m_library_id);
return ContentResponse::build( return ContentResponse::build(
*this, *this,
@ -155,7 +155,7 @@ std::unique_ptr<Response> InternalServer::handle_catalog_v2_illustration(const R
{ {
try { try {
const auto bookId = request.get_url_part(3); const auto bookId = request.get_url_part(3);
auto book = mp_library->getBookByIdThreadSafe(bookId); auto book = m_configuration.mp_library->getBookByIdThreadSafe(bookId);
auto size = request.get_argument<unsigned int>("size"); auto size = request.get_argument<unsigned int>("size");
auto illustration = book.getIllustration(size); auto illustration = book.getIllustration(size);
return ContentResponse::build( return ContentResponse::build(

View File

@ -114,7 +114,7 @@ Response::Response(bool verbose)
std::unique_ptr<Response> Response::build(const InternalServer& server) std::unique_ptr<Response> Response::build(const InternalServer& server)
{ {
return std::unique_ptr<Response>(new Response(server.m_verbose.load())); return std::unique_ptr<Response>(new Response(server.m_configuration.m_verbose));
} }
std::unique_ptr<Response> Response::build_304(const InternalServer& server, const ETag& etag) std::unique_ptr<Response> Response::build_304(const InternalServer& server, const ETag& etag)
@ -389,8 +389,8 @@ std::unique_ptr<ContentResponse> ContentResponse::build(
const std::string& mimetype) const std::string& mimetype)
{ {
return std::unique_ptr<ContentResponse>(new ContentResponse( return std::unique_ptr<ContentResponse>(new ContentResponse(
server.m_root, server.m_configuration.m_root,
server.m_verbose.load(), server.m_configuration.m_verbose,
content, content,
mimetype)); mimetype));
} }
@ -435,7 +435,7 @@ std::unique_ptr<Response> ItemResponse::build(const InternalServer& server, cons
} }
return std::unique_ptr<Response>(new ItemResponse( return std::unique_ptr<Response>(new ItemResponse(
server.m_verbose.load(), server.m_configuration.m_verbose,
item, item,
mimetype, mimetype,
byteRange)); byteRange));

View File

@ -130,18 +130,20 @@ void ZimFileServer::run(int serverPort, std::string indexTemplateString)
} else { } else {
nameMapper.reset(new kiwix::HumanReadableNameMapper(library, false)); nameMapper.reset(new kiwix::HumanReadableNameMapper(library, false));
} }
server.reset(new kiwix::Server(&library, nameMapper.get())); kiwix::ServerConfiguration configuration(&library, nameMapper.get());
server->setRoot("ROOT"); configuration.setRoot("ROOT")
server->setAddress(address); .setAddress(address)
server->setPort(serverPort); .setPort(serverPort)
server->setNbThreads(2); .setNbThreads(2)
server->setVerbose(false); .setVerbose(false)
server->setTaskbar(options & WITH_TASKBAR, options & WITH_LIBRARY_BUTTON); .setTaskbar(options & WITH_TASKBAR, options & WITH_LIBRARY_BUTTON)
server->setBlockExternalLinks(options & BLOCK_EXTERNAL_LINKS); .setBlockExternalLinks(options & BLOCK_EXTERNAL_LINKS)
server->setMultiZimSearchLimit(3); .setMultiZimSearchLimit(3);
if (!indexTemplateString.empty()) { if (!indexTemplateString.empty()) {
server->setIndexTemplateString(indexTemplateString); configuration.setIndexTemplateString(indexTemplateString);
} }
server.reset(new kiwix::Server(configuration));
if ( !server->start() ) if ( !server->start() )
throw std::runtime_error("ZimFileServer failed to start"); throw std::runtime_error("ZimFileServer failed to start");