Mercurial > hg > orthanc
changeset 1515:c94353fbd4e9
cont http compression
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 10 Aug 2015 17:18:36 +0200 |
parents | d73a2178b319 |
children | f09f5d3225a7 |
files | CMakeLists.txt Core/HttpServer/EmbeddedResourceHttpHandler.cpp Core/HttpServer/FilesystemHttpHandler.cpp Core/HttpServer/IHttpHandler.cpp Core/HttpServer/IHttpHandler.h Core/RestApi/RestApi.cpp Core/RestApi/RestApiOutput.cpp Core/RestApi/RestApiOutput.h |
diffstat | 8 files changed, 145 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Mon Aug 10 16:43:59 2015 +0200 +++ b/CMakeLists.txt Mon Aug 10 17:18:36 2015 +0200 @@ -104,6 +104,7 @@ Core/HttpServer/FilesystemHttpHandler.cpp Core/HttpServer/HttpToolbox.cpp Core/HttpServer/HttpOutput.cpp + Core/HttpServer/IHttpHandler.cpp Core/HttpServer/StringHttpOutput.cpp Core/HttpServer/MongooseServer.cpp Core/HttpServer/HttpFileSender.cpp
--- a/Core/HttpServer/EmbeddedResourceHttpHandler.cpp Mon Aug 10 16:43:59 2015 +0200 +++ b/Core/HttpServer/EmbeddedResourceHttpHandler.cpp Mon Aug 10 17:18:36 2015 +0200 @@ -81,7 +81,7 @@ size_t size = EmbeddedResources::GetDirectoryResourceSize(resourceId_, resourcePath.c_str()); output.SetContentType(contentType.c_str()); - output.SendBody(buffer, size); + output.SendBody(buffer, size, IHttpHandler::GetPreferredCompression(headers, size)); } catch (OrthancException&) {
--- a/Core/HttpServer/FilesystemHttpHandler.cpp Mon Aug 10 16:43:59 2015 +0200 +++ b/Core/HttpServer/FilesystemHttpHandler.cpp Mon Aug 10 17:18:36 2015 +0200 @@ -50,6 +50,7 @@ static void OutputDirectoryContent(HttpOutput& output, + const IHttpHandler::Arguments& headers, const UriComponents& uri, const boost::filesystem::path& p) { @@ -104,7 +105,7 @@ s += " </body>"; s += "</html>"; - output.SendBody(s); + output.SendBody(s, IHttpHandler::GetPreferredCompression(headers, s.size())); } @@ -155,7 +156,7 @@ if (fs::exists(p) && fs::is_regular_file(p)) { - FilesystemHttpSender(p).Send(output); + FilesystemHttpSender(p).Send(output); // TODO COMPRESSION //output.AnswerFileAutodetectContentType(p.string()); } @@ -163,7 +164,7 @@ fs::exists(p) && fs::is_directory(p)) { - OutputDirectoryContent(output, uri, p); + OutputDirectoryContent(output, headers, uri, p); } else {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/HttpServer/IHttpHandler.cpp Mon Aug 10 17:18:36 2015 +0200 @@ -0,0 +1,104 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "../PrecompiledHeaders.h" +#include "IHttpHandler.h" + +#include "../Toolbox.h" + +namespace Orthanc +{ + void IHttpHandler::GetAcceptedCompressions(std::set<HttpCompression>& result, + const Arguments& headers) + { + // Look if the client wishes HTTP compression + // https://en.wikipedia.org/wiki/HTTP_compression + Arguments::const_iterator it = headers.find("accept-encoding"); + if (it != headers.end()) + { + std::vector<std::string> encodings; + Toolbox::TokenizeString(encodings, it->second, ','); + for (size_t i = 0; i < encodings.size(); i++) + { + std::string s = Toolbox::StripSpaces(encodings[i]); + + if (s == "deflate") + { + result.insert(HttpCompression_Deflate); + } + else if (s == "gzip") + { + result.insert(HttpCompression_Gzip); + } + } + } + } + + + HttpCompression IHttpHandler::GetPreferredCompression(const Arguments& headers, + size_t bodySize) + { +#if 0 + // TODO + if (bodySize < 1024) + { + // Do not compress small answers + return HttpCompression_None; + } +#endif + + HttpCompression result = HttpCompression_None; + + Arguments::const_iterator it = headers.find("accept-encoding"); + if (it != headers.end()) + { + std::vector<std::string> encodings; + Toolbox::TokenizeString(encodings, it->second, ','); + for (size_t i = 0; i < encodings.size(); i++) + { + std::string s = Toolbox::StripSpaces(encodings[i]); + + if (s == "deflate" && + result != HttpCompression_Gzip) // Always prefer "gzip" over "deflate" + { + result = HttpCompression_Deflate; + } + else if (s == "gzip") + { + result = HttpCompression_Gzip; + } + } + } + + return result; + } +}
--- a/Core/HttpServer/IHttpHandler.h Mon Aug 10 16:43:59 2015 +0200 +++ b/Core/HttpServer/IHttpHandler.h Mon Aug 10 17:18:36 2015 +0200 @@ -36,6 +36,7 @@ #include "HttpOutput.h" #include <map> +#include <set> #include <vector> #include <string> @@ -58,5 +59,11 @@ const GetArguments& getArguments, const char* bodyData, size_t bodySize) = 0; + + static void GetAcceptedCompressions(std::set<HttpCompression>& result, + const Arguments& headers); + + static HttpCompression GetPreferredCompression(const Arguments& headers, + size_t bodySize); }; }
--- a/Core/RestApi/RestApi.cpp Mon Aug 10 16:43:59 2015 +0200 +++ b/Core/RestApi/RestApi.cpp Mon Aug 10 17:18:36 2015 +0200 @@ -194,30 +194,20 @@ } #endif - { - // Look if the client wishes HTTP compression - // https://en.wikipedia.org/wiki/HTTP_compression - Arguments::const_iterator it = headers.find("accept-encoding"); - if (it != headers.end()) - { - std::vector<std::string> encodings; - Toolbox::TokenizeString(encodings, it->second, ','); - for (size_t i = 0; i < encodings.size(); i++) - { - std::string s = Toolbox::StripSpaces(encodings[i]); + std::set<HttpCompression> compressions; + GetAcceptedCompressions(compressions, headers); - if (s == "deflate") - { - wrappedOutput.AllowDeflateCompression(true); - } - else if (s == "gzip") - { - wrappedOutput.AllowGzipCompression(true); - } - } - } + if (compressions.find(HttpCompression_Deflate) != compressions.end()) + { + wrappedOutput.AllowDeflateCompression(true); } + if (compressions.find(HttpCompression_Gzip) != compressions.end()) + { + wrappedOutput.AllowGzipCompression(true); + } + + Arguments compiled; HttpToolbox::CompileGetArguments(compiled, getArguments);
--- a/Core/RestApi/RestApiOutput.cpp Mon Aug 10 16:43:59 2015 +0200 +++ b/Core/RestApi/RestApiOutput.cpp Mon Aug 10 17:18:36 2015 +0200 @@ -80,8 +80,17 @@ } - HttpCompression RestApiOutput::GetPreferredCompression() const + HttpCompression RestApiOutput::GetPreferredCompression(size_t bodySize) const { +#if 0 + // TODO + if (bodySize < 1024) + { + // Do not compress small answers + return HttpCompression_None; + } +#endif + if (allowGzipCompression_) { return HttpCompression_Gzip; @@ -108,13 +117,13 @@ { CheckStatus(); + std::string s; + if (convertJsonToXml_) { #if ORTHANC_PUGIXML_ENABLED == 1 - std::string s; Toolbox::JsonToXml(s, value); output_.SetContentType("application/xml"); - output_.SendBody(s, GetPreferredCompression()); #else LOG(ERROR) << "Orthanc was compiled without XML support"; throw OrthancException(ErrorCode_InternalError); @@ -124,9 +133,11 @@ { Json::StyledWriter writer; output_.SetContentType("application/json"); - output_.SendBody(writer.write(value), GetPreferredCompression()); + s = writer.write(value); } + output_.SendBody(s, GetPreferredCompression(s.size())); + alreadySent_ = true; } @@ -143,7 +154,7 @@ { CheckStatus(); output_.SetContentType(contentType.c_str()); - output_.SendBody(buffer, length, GetPreferredCompression()); + output_.SendBody(buffer, length, GetPreferredCompression(length)); alreadySent_ = true; }
--- a/Core/RestApi/RestApiOutput.h Mon Aug 10 16:43:59 2015 +0200 +++ b/Core/RestApi/RestApiOutput.h Mon Aug 10 17:18:36 2015 +0200 @@ -51,7 +51,7 @@ void CheckStatus(); - HttpCompression GetPreferredCompression() const; + HttpCompression GetPreferredCompression(size_t bodySize) const; public: RestApiOutput(HttpOutput& output,