# HG changeset patch # User Sebastien Jodogne # Date 1439217839 -7200 # Node ID d73a2178b319d429b05d46228a401f8e24858f41 # Parent fe07f82d83d344be4fef58dc1ef33ce523a288bc support of deflate and gzip content-types diff -r fe07f82d83d3 -r d73a2178b319 Core/Enumerations.h --- a/Core/Enumerations.h Mon Aug 10 16:01:37 2015 +0200 +++ b/Core/Enumerations.h Mon Aug 10 16:43:59 2015 +0200 @@ -325,7 +325,7 @@ * buffer is non-empty, the buffer is compatible with the * "deflate" HTTP compression. **/ - CompressionType_Zlib = 2 + CompressionType_ZlibWithSize = 2 }; enum FileContentType diff -r fe07f82d83d3 -r d73a2178b319 Core/FileStorage/CompressedFileStorageAccessor.cpp --- a/Core/FileStorage/CompressedFileStorageAccessor.cpp Mon Aug 10 16:01:37 2015 +0200 +++ b/Core/FileStorage/CompressedFileStorageAccessor.cpp Mon Aug 10 16:43:59 2015 +0200 @@ -64,7 +64,7 @@ return FileInfo(uuid, type, size, md5); } - case CompressionType_Zlib: + case CompressionType_ZlibWithSize: { std::string compressed; zlib_.Compress(compressed, data, size); @@ -86,7 +86,7 @@ } return FileInfo(uuid, type, size, md5, - CompressionType_Zlib, compressed.size(), compressedMD5); + CompressionType_ZlibWithSize, compressed.size(), compressedMD5); } default: @@ -131,7 +131,7 @@ GetStorageArea().Read(content, uuid, type); break; - case CompressionType_Zlib: + case CompressionType_ZlibWithSize: { std::string compressed; GetStorageArea().Read(compressed, uuid, type); @@ -155,7 +155,7 @@ return uncompressedAccessor.ConstructHttpFileSender(uuid, type); } - case CompressionType_Zlib: + case CompressionType_ZlibWithSize: { std::string compressed; GetStorageArea().Read(compressed, uuid, type); diff -r fe07f82d83d3 -r d73a2178b319 Core/HttpServer/HttpOutput.cpp --- a/Core/HttpServer/HttpOutput.cpp Mon Aug 10 16:01:37 2015 +0200 +++ b/Core/HttpServer/HttpOutput.cpp Mon Aug 10 16:43:59 2015 +0200 @@ -36,6 +36,7 @@ #include "../Logging.h" #include "../OrthancException.h" #include "../Toolbox.h" +#include "../Compression/GzipCompressor.h" #include "../Compression/ZlibCompressor.h" #include @@ -275,16 +276,27 @@ break; } + case HttpCompression_Gzip: case HttpCompression_Deflate: { - LOG(TRACE) << "Compressing a HTTP answer using Deflate"; - ZlibCompressor compressor; + std::string compressed, encoding; - // Do not prefix the buffer with its uncompressed size, to be compatible with "deflate" - compressor.SetPrefixWithUncompressedSize(false); + if (compression == HttpCompression_Deflate) + { + encoding = "deflate"; + ZlibCompressor compressor; + // Do not prefix the buffer with its uncompressed size, to be compatible with "deflate" + compressor.SetPrefixWithUncompressedSize(false); + compressor.Compress(compressed, buffer, length); + } + else + { + encoding = "gzip"; + GzipCompressor compressor; + compressor.Compress(compressed, buffer, length); + } - std::string compressed; - compressor.Compress(compressed, buffer, length); + LOG(TRACE) << "Compressing a HTTP answer using " << encoding; // The body is empty, do not use Deflate compression if (compressed.size() == 0) @@ -293,7 +305,7 @@ } else { - stateMachine_.AddHeader("Content-Encoding", "deflate"); + stateMachine_.AddHeader("Content-Encoding", encoding); stateMachine_.SendBody(compressed.c_str(), compressed.size()); } diff -r fe07f82d83d3 -r d73a2178b319 Core/RestApi/RestApi.cpp --- a/Core/RestApi/RestApi.cpp Mon Aug 10 16:01:37 2015 +0200 +++ b/Core/RestApi/RestApi.cpp Mon Aug 10 16:43:59 2015 +0200 @@ -205,12 +205,15 @@ for (size_t i = 0; i < encodings.size(); i++) { std::string s = Toolbox::StripSpaces(encodings[i]); + if (s == "deflate") { - wrappedOutput.SetHttpCompression(HttpCompression_Deflate); + wrappedOutput.AllowDeflateCompression(true); } - - // TODO HttpCompression_Gzip ? + else if (s == "gzip") + { + wrappedOutput.AllowGzipCompression(true); + } } } } diff -r fe07f82d83d3 -r d73a2178b319 Core/RestApi/RestApiOutput.cpp --- a/Core/RestApi/RestApiOutput.cpp Mon Aug 10 16:01:37 2015 +0200 +++ b/Core/RestApi/RestApiOutput.cpp Mon Aug 10 16:43:59 2015 +0200 @@ -45,7 +45,8 @@ HttpMethod method) : output_(output), method_(method), - compression_(HttpCompression_None), + allowDeflateCompression_(false), + allowGzipCompression_(false), convertJsonToXml_(false) { alreadySent_ = false; @@ -78,6 +79,24 @@ } } + + HttpCompression RestApiOutput::GetPreferredCompression() const + { + if (allowGzipCompression_) + { + return HttpCompression_Gzip; + } + else if (allowDeflateCompression_) + { + return HttpCompression_Deflate; + } + else + { + return HttpCompression_None; + } + } + + void RestApiOutput::AnswerFile(HttpFileSender& sender) { CheckStatus(); @@ -95,7 +114,7 @@ std::string s; Toolbox::JsonToXml(s, value); output_.SetContentType("application/xml"); - output_.SendBody(s, compression_); + output_.SendBody(s, GetPreferredCompression()); #else LOG(ERROR) << "Orthanc was compiled without XML support"; throw OrthancException(ErrorCode_InternalError); @@ -105,7 +124,7 @@ { Json::StyledWriter writer; output_.SetContentType("application/json"); - output_.SendBody(writer.write(value), compression_); + output_.SendBody(writer.write(value), GetPreferredCompression()); } alreadySent_ = true; @@ -114,10 +133,8 @@ void RestApiOutput::AnswerBuffer(const std::string& buffer, const std::string& contentType) { - CheckStatus(); - output_.SetContentType(contentType.c_str()); - output_.SendBody(buffer, compression_); - alreadySent_ = true; + AnswerBuffer(buffer.size() == 0 ? NULL : buffer.c_str(), + buffer.size(), contentType); } void RestApiOutput::AnswerBuffer(const void* buffer, @@ -126,7 +143,7 @@ { CheckStatus(); output_.SetContentType(contentType.c_str()); - output_.SendBody(buffer, length, compression_); + output_.SendBody(buffer, length, GetPreferredCompression()); alreadySent_ = true; } diff -r fe07f82d83d3 -r d73a2178b319 Core/RestApi/RestApiOutput.h --- a/Core/RestApi/RestApiOutput.h Mon Aug 10 16:01:37 2015 +0200 +++ b/Core/RestApi/RestApiOutput.h Mon Aug 10 16:43:59 2015 +0200 @@ -42,14 +42,17 @@ class RestApiOutput { private: - HttpOutput& output_; - HttpMethod method_; - HttpCompression compression_; - bool alreadySent_; - bool convertJsonToXml_; + HttpOutput& output_; + HttpMethod method_; + bool allowDeflateCompression_; + bool allowGzipCompression_; + bool alreadySent_; + bool convertJsonToXml_; void CheckStatus(); + HttpCompression GetPreferredCompression() const; + public: RestApiOutput(HttpOutput& output, HttpMethod method); @@ -76,14 +79,14 @@ return convertJsonToXml_; } - void SetHttpCompression(HttpCompression compression) + void AllowDeflateCompression(bool allow) { - compression_ = compression; + allowDeflateCompression_ = allow; } - HttpCompression GetHttpCompression() const + void AllowGzipCompression(bool allow) { - return compression_; + allowGzipCompression_ = allow; } void AnswerFile(HttpFileSender& sender); diff -r fe07f82d83d3 -r d73a2178b319 NEWS --- a/NEWS Mon Aug 10 16:01:37 2015 +0200 +++ b/NEWS Mon Aug 10 16:43:59 2015 +0200 @@ -2,6 +2,7 @@ =============================== * "limit" and "since" arguments while retrieving DICOM resources in the REST API +* Support of "deflate" and "gzip" content-types in HTTP requests Version 0.9.3 (2015/08/07) diff -r fe07f82d83d3 -r d73a2178b319 OrthancServer/ServerContext.cpp --- a/OrthancServer/ServerContext.cpp Mon Aug 10 16:01:37 2015 +0200 +++ b/OrthancServer/ServerContext.cpp Mon Aug 10 16:43:59 2015 +0200 @@ -214,7 +214,8 @@ if (compressionEnabled_) { - accessor_.SetCompressionForNextOperations(CompressionType_Zlib); + // TODO Should we use "gzip" instead? + accessor_.SetCompressionForNextOperations(CompressionType_ZlibWithSize); } else { @@ -403,7 +404,8 @@ if (compressionEnabled_) { - accessor_.SetCompressionForNextOperations(CompressionType_Zlib); + // TODO Should we use "gzip" instead? + accessor_.SetCompressionForNextOperations(CompressionType_ZlibWithSize); } else { diff -r fe07f82d83d3 -r d73a2178b319 UnitTestsSources/FileStorageTests.cpp --- a/UnitTestsSources/FileStorageTests.cpp Mon Aug 10 16:01:37 2015 +0200 +++ b/UnitTestsSources/FileStorageTests.cpp Mon Aug 10 16:43:59 2015 +0200 @@ -188,7 +188,7 @@ FilesystemStorage s("UnitTestsStorage"); CompressedFileStorageAccessor accessor(s); - accessor.SetCompressionForNextOperations(CompressionType_Zlib); + accessor.SetCompressionForNextOperations(CompressionType_ZlibWithSize); std::string data = "Hello world"; FileInfo info = accessor.Write(data, FileContentType_Dicom); @@ -196,7 +196,7 @@ accessor.Read(r, info.GetUuid(), FileContentType_Unknown); ASSERT_EQ(data, r); - ASSERT_EQ(CompressionType_Zlib, info.GetCompressionType()); + ASSERT_EQ(CompressionType_ZlibWithSize, info.GetCompressionType()); ASSERT_EQ(11u, info.GetUncompressedSize()); ASSERT_EQ(FileContentType_Dicom, info.GetContentType()); } @@ -211,13 +211,13 @@ std::string compressedData = "Hello"; std::string uncompressedData = "HelloWorld"; - accessor.SetCompressionForNextOperations(CompressionType_Zlib); + accessor.SetCompressionForNextOperations(CompressionType_ZlibWithSize); FileInfo compressedInfo = accessor.Write(compressedData, FileContentType_Dicom); accessor.SetCompressionForNextOperations(CompressionType_None); FileInfo uncompressedInfo = accessor.Write(uncompressedData, FileContentType_Dicom); - accessor.SetCompressionForNextOperations(CompressionType_Zlib); + accessor.SetCompressionForNextOperations(CompressionType_ZlibWithSize); accessor.Read(r, compressedInfo.GetUuid(), FileContentType_Unknown); ASSERT_EQ(compressedData, r); @@ -227,7 +227,7 @@ /* // This test is too slow on Windows - accessor.SetCompressionForNextOperations(CompressionType_Zlib); + accessor.SetCompressionForNextOperations(CompressionType_ZlibWithSize); ASSERT_THROW(accessor.Read(r, uncompressedInfo.GetUuid(), FileContentType_Unknown), OrthancException); */ } diff -r fe07f82d83d3 -r d73a2178b319 UnitTestsSources/ServerIndexTests.cpp --- a/UnitTestsSources/ServerIndexTests.cpp Mon Aug 10 16:01:37 2015 +0200 +++ b/UnitTestsSources/ServerIndexTests.cpp Mon Aug 10 16:43:59 2015 +0200 @@ -350,7 +350,7 @@ ASSERT_EQ(0u, md.size()); index_->AddAttachment(a[4], FileInfo("my json file", FileContentType_DicomAsJson, 42, "md5", - CompressionType_Zlib, 21, "compressedMD5")); + CompressionType_ZlibWithSize, 21, "compressedMD5")); index_->AddAttachment(a[4], FileInfo("my dicom file", FileContentType_Dicom, 42, "md5")); index_->AddAttachment(a[6], FileInfo("world", FileContentType_Dicom, 44, "md5")); index_->SetMetadata(a[4], MetadataType_Instance_RemoteAet, "PINNACLE"); @@ -409,7 +409,7 @@ ASSERT_EQ("md5", att.GetUncompressedMD5()); ASSERT_EQ("compressedMD5", att.GetCompressedMD5()); ASSERT_EQ(42u, att.GetUncompressedSize()); - ASSERT_EQ(CompressionType_Zlib, att.GetCompressionType()); + ASSERT_EQ(CompressionType_ZlibWithSize, att.GetCompressionType()); ASSERT_TRUE(index_->LookupAttachment(att, a[6], FileContentType_Dicom)); ASSERT_EQ("world", att.GetUuid());