Merge pull request #16 from kiwix/kiwix-serve.bugfix

Kiwix serve.bugfix
This commit is contained in:
Matthieu Gautier 2017-03-20 11:05:21 +01:00 committed by GitHub
commit 25091c320b

View File

@ -49,6 +49,7 @@ extern "C" {
#include <getopt.h> #include <getopt.h>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector>
#include <map> #include <map>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
@ -120,12 +121,12 @@ static std::string getMimeTypeForFile(const std::string& filename) {
void introduceTaskbar(string &content, const string &humanReadableBookId) { void introduceTaskbar(string &content, const string &humanReadableBookId) {
if (!nosearchbarFlag) { if (!nosearchbarFlag) {
content = appendToFirstOccurence(content, "<head>", content = appendToFirstOccurence(content, "<head>",
replaceRegex(RESOURCE::include_html_part, replaceRegex(RESOURCE::include_html_part,
humanReadableBookId, "__CONTENT__")); humanReadableBookId, "__CONTENT__"));
content = appendToFirstOccurence(content, "<head>", "<style>" + content = appendToFirstOccurence(content, "<head>", "<style>" +
RESOURCE::taskbar_css + "</style>"); RESOURCE::taskbar_css + "</style>");
content = appendToFirstOccurence(content, "<body[^>]*>", content = appendToFirstOccurence(content, "<body[^>]*>",
replaceRegex(RESOURCE::taskbar_html_part, replaceRegex(RESOURCE::taskbar_html_part,
humanReadableBookId, "__CONTENT__")); humanReadableBookId, "__CONTENT__"));
} }
@ -140,50 +141,47 @@ bool isVerbose() {
return value; return value;
} }
/* For compression */
#define COMPRESSOR_BUFFER_SIZE 10000000
static Bytef *compr = (Bytef *)malloc(COMPRESSOR_BUFFER_SIZE);
static uLongf comprLen;
static static
bool compress_content(string &content, bool compress_content(string &content,
const string &mimeType) const string &mimeType)
{ {
static std::vector<Bytef> compr_buffer;
/* Should be deflate */
bool deflated = mimeType.find("text/") != string::npos ||
mimeType.find("application/javascript") != string::npos ||
mimeType.find("application/json") != string::npos;
if ( ! deflated )
return false;
/* Compute the lengh */ /* Compute the lengh */
unsigned int contentLength = content.size(); unsigned int contentLength = content.size();
/* Should be deflate */ /* If the content is too short, no need to compress it */
bool deflated = if ( contentLength <= KIWIX_MIN_CONTENT_SIZE_TO_DEFLATE)
contentLength > KIWIX_MIN_CONTENT_SIZE_TO_DEFLATE && return false;
contentLength < COMPRESSOR_BUFFER_SIZE &&
(mimeType.find("text/") != string::npos || uLong bufferBound = compressBound(contentLength);
mimeType.find("application/javascript") != string::npos ||
mimeType.find("application/json") != string::npos);
/* Compress the content if necessary */ /* Compress the content if necessary */
if (deflated) { pthread_mutex_lock(&compressorLock);
pthread_mutex_lock(&compressorLock); compr_buffer.reserve(bufferBound);
comprLen = COMPRESSOR_BUFFER_SIZE; uLongf comprLen = compr_buffer.capacity();
compress(compr, &comprLen, (const Bytef*)(content.data()), contentLength); int err = compress(&compr_buffer[0], &comprLen, (const Bytef*)(content.data()), contentLength);
if (comprLen > 2 && comprLen < contentLength) { if (err == Z_OK && comprLen > 2 && comprLen < (contentLength+2)) {
/* /!\ Internet Explorer has a bug with deflate compression.
/* /!\ Internet Explorer has a bug with deflate compression. It can not handle the first two bytes (compression headers)
It can not handle the first two bytes (compression headers) We need to chunk them off (move the content 2bytes)
We need to chunk them off (move the content 2bytes) It has no incidence on other browsers
It has no incidence on other browsers See http://www.subbu.org/blog/2008/03/ie7-deflate-or-not and comments */
See http://www.subbu.org/blog/2008/03/ie7-deflate-or-not and comments */ content = string((char *)&compr_buffer[2], comprLen-2);
compr += 2; } else {
deflated = false;
content = string((char *)compr, comprLen);
contentLength = comprLen;
} else {
deflated = false;
}
pthread_mutex_unlock(&compressorLock);
} }
pthread_mutex_unlock(&compressorLock);
return deflated; return deflated;
} }
@ -426,7 +424,6 @@ struct MHD_Response* handle_random(struct MHD_Connection * connection,
bool acceptEncodingDeflate) bool acceptEncodingDeflate)
{ {
std::string httpRedirection; std::string httpRedirection;
bool cacheEnabled = false;
httpResponseCode = MHD_HTTP_FOUND; httpResponseCode = MHD_HTTP_FOUND;
if (reader != NULL) { if (reader != NULL) {
pthread_mutex_lock(&readerLock); pthread_mutex_lock(&readerLock);
@ -449,7 +446,6 @@ struct MHD_Response* handle_content(struct MHD_Connection * connection,
std::string baseUrl; std::string baseUrl;
std::string content; std::string content;
std::string mimeType; std::string mimeType;
unsigned int contentLength;
bool found = false; bool found = false;
zim::Article article; zim::Article article;
@ -591,7 +587,7 @@ static int accessHandlerCallback(void *cls,
const char* acceptEncodingHeaderValue = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_ACCEPT_ENCODING); const char* acceptEncodingHeaderValue = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_ACCEPT_ENCODING);
const bool acceptEncodingDeflate = acceptEncodingHeaderValue && string(acceptEncodingHeaderValue).find("deflate") != string::npos; const bool acceptEncodingDeflate = acceptEncodingHeaderValue && string(acceptEncodingHeaderValue).find("deflate") != string::npos;
/* Check if range is requested */ /* Check if range is requested. [TODO] Handle this somehow */
const char* acceptRangeHeaderValue = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_RANGE); const char* acceptRangeHeaderValue = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_RANGE);
const bool acceptRange = acceptRangeHeaderValue != NULL; const bool acceptRange = acceptRangeHeaderValue != NULL;
@ -607,7 +603,7 @@ static int accessHandlerCallback(void *cls,
const char* tmpGetValue = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "content"); const char* tmpGetValue = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "content");
humanReadableBookId = (tmpGetValue != NULL ? string(tmpGetValue) : ""); humanReadableBookId = (tmpGetValue != NULL ? string(tmpGetValue) : "");
} else { } else {
humanReadableBookId = urlStr.substr(1, urlStr.find("/", 1) != string::npos ? humanReadableBookId = urlStr.substr(1, urlStr.find("/", 1) != string::npos ?
urlStr.find("/", 1) - 1 : urlStr.size() - 2); urlStr.find("/", 1) - 1 : urlStr.size() - 2);
if (!humanReadableBookId.empty()) { if (!humanReadableBookId.empty()) {
urlStr = urlStr.substr(urlStr.find("/", 1) != string::npos ? urlStr = urlStr.substr(urlStr.find("/", 1) != string::npos ?
@ -697,7 +693,7 @@ static int accessHandlerCallback(void *cls,
httpResponseCode, httpResponseCode,
response); response);
MHD_destroy_response(response); MHD_destroy_response(response);
return ret; return ret;
} }
@ -792,7 +788,7 @@ int main(int argc, char **argv) {
if (libraryFlag) { if (libraryFlag) {
vector<string> libraryPaths = kiwix::split(libraryPath, ";"); vector<string> libraryPaths = kiwix::split(libraryPath, ";");
vector<string>::iterator itr; vector<string>::iterator itr;
for ( itr = libraryPaths.begin(); itr != libraryPaths.end(); ++itr ) { for ( itr = libraryPaths.begin(); itr != libraryPaths.end(); ++itr ) {
if (!itr->empty()) { if (!itr->empty()) {
bool retVal = false; bool retVal = false;
@ -924,7 +920,7 @@ int main(int argc, char **argv) {
pthread_mutex_init(&compressorLock, NULL); pthread_mutex_init(&compressorLock, NULL);
pthread_mutex_init(&verboseFlagLock, NULL); pthread_mutex_init(&verboseFlagLock, NULL);
pthread_mutex_init(&mimeTypeLock, NULL); pthread_mutex_init(&mimeTypeLock, NULL);
/* Hard coded mimetypes */ /* Hard coded mimetypes */
extMimeTypes["html"] = "text/html"; extMimeTypes["html"] = "text/html";
extMimeTypes["htm"] = "text/html"; extMimeTypes["htm"] = "text/html";
@ -945,7 +941,7 @@ int main(int argc, char **argv) {
extMimeTypes["ttf"] = "application/font-ttf"; extMimeTypes["ttf"] = "application/font-ttf";
extMimeTypes["woff"] = "application/font-woff"; extMimeTypes["woff"] = "application/font-woff";
extMimeTypes["vtt"] = "text/vtt"; extMimeTypes["vtt"] = "text/vtt";
/* Start the HTTP daemon */ /* Start the HTTP daemon */
void *page = NULL; void *page = NULL;
if (interface.length() > 0) { if (interface.length() > 0) {
@ -956,7 +952,6 @@ int main(int argc, char **argv) {
struct sockaddr_in sockAddr; struct sockaddr_in sockAddr;
struct ifaddrs *ifaddr, *ifa; struct ifaddrs *ifaddr, *ifa;
int family, n; int family, n;
char host[NI_MAXHOST];
/* Search all available interfaces */ /* Search all available interfaces */
if (getifaddrs(&ifaddr) == -1) { if (getifaddrs(&ifaddr) == -1) {