comparison OrthancFramework/Sources/HttpServer/HttpOutput.cpp @ 5406:aaf7c49a9ddc am-http-compression

tentative to implement smart HTTP compression with detection of transfer syntax
author Alain Mazy <am@osimis.io>
date Sat, 04 Nov 2023 13:42:30 +0100
parents 0ea402b4d901
children
comparison
equal deleted inserted replaced
5405:62bb63346185 5406:aaf7c49a9ddc
49 HttpOutput::StateMachine::StateMachine(IHttpOutputStream& stream, 49 HttpOutput::StateMachine::StateMachine(IHttpOutputStream& stream,
50 bool isKeepAlive, 50 bool isKeepAlive,
51 unsigned int keepAliveTimeout) : 51 unsigned int keepAliveTimeout) :
52 stream_(stream), 52 stream_(stream),
53 state_(State_WritingHeader), 53 state_(State_WritingHeader),
54 contentCompression_(ContentCompression_Unknown),
54 status_(HttpStatus_200_Ok), 55 status_(HttpStatus_200_Ok),
55 hasContentLength_(false), 56 hasContentLength_(false),
56 contentLength_(0), 57 contentLength_(0),
57 contentPosition_(0), 58 contentPosition_(0),
58 keepAlive_(isKeepAlive), 59 keepAlive_(isKeepAlive),
98 } 99 }
99 100
100 void HttpOutput::StateMachine::SetContentType(const char* contentType) 101 void HttpOutput::StateMachine::SetContentType(const char* contentType)
101 { 102 {
102 AddHeader("Content-Type", contentType); 103 AddHeader("Content-Type", contentType);
104 }
105
106 void HttpOutput::StateMachine::SetContentCompression(ContentCompression contentCompression)
107 {
108 contentCompression_ = contentCompression;
109 }
110
111 bool HttpOutput::StateMachine::IsContentCompressible() const
112 {
113 // We assume that all files that compress correctly (mainly JSON, XML) are clearly identified.
114 // Therefore, only the content identified as NotCompressed are compressed again.
115 // We consider that the content whose compression is Unknown, likely DICOM file whose transfer syntax
116 // could not be determined, must not be compressed either.
117 return contentCompression_ == ContentCompression_NotCompressed;
103 } 118 }
104 119
105 void HttpOutput::StateMachine::SetContentFilename(const char* filename) 120 void HttpOutput::StateMachine::SetContentFilename(const char* filename)
106 { 121 {
107 // TODO Escape double quotes 122 // TODO Escape double quotes
273 } 288 }
274 289
275 290
276 HttpCompression HttpOutput::GetPreferredCompression(size_t bodySize) const 291 HttpCompression HttpOutput::GetPreferredCompression(size_t bodySize) const
277 { 292 {
278 #if 0 293 // Do not compress small files since there is no real size benefit.
279 // TODO Do not compress small files? 294 if (bodySize < 2048)
280 if (bodySize < 512)
281 { 295 {
282 return HttpCompression_None; 296 return HttpCompression_None;
283 } 297 }
284 #endif
285 298
286 // Prefer "gzip" over "deflate" if the choice is offered 299 // Prefer "gzip" over "deflate" if the choice is offered
287 300
288 if (isGzipAllowed_) 301 if (isGzipAllowed_)
289 { 302 {
373 void HttpOutput::SetContentType(const std::string &contentType) 386 void HttpOutput::SetContentType(const std::string &contentType)
374 { 387 {
375 stateMachine_.SetContentType(contentType.c_str()); 388 stateMachine_.SetContentType(contentType.c_str());
376 } 389 }
377 390
391 void HttpOutput::SetContentCompression(ContentCompression contentCompression)
392 {
393 stateMachine_.SetContentCompression(contentCompression);
394 }
395
378 void HttpOutput::SetContentFilename(const char *filename) 396 void HttpOutput::SetContentFilename(const char *filename)
379 { 397 {
380 stateMachine_.SetContentFilename(filename); 398 stateMachine_.SetContentFilename(filename);
381 } 399 }
382 400
440 return; 458 return;
441 } 459 }
442 460
443 HttpCompression compression = GetPreferredCompression(length); 461 HttpCompression compression = GetPreferredCompression(length);
444 462
445 if (compression == HttpCompression_None) 463 if (compression == HttpCompression_None || !IsContentCompressible())
446 { 464 {
447 stateMachine_.SetContentLength(length); 465 stateMachine_.SetContentLength(length);
448 stateMachine_.SendBody(buffer, length); 466 stateMachine_.SendBody(buffer, length);
449 return; 467 return;
450 } 468 }
814 832
815 void HttpOutput::Answer(IHttpStreamAnswer& stream) 833 void HttpOutput::Answer(IHttpStreamAnswer& stream)
816 { 834 {
817 HttpCompression compression = stream.SetupHttpCompression(isGzipAllowed_, isDeflateAllowed_); 835 HttpCompression compression = stream.SetupHttpCompression(isGzipAllowed_, isDeflateAllowed_);
818 836
837 if (!IsContentCompressible())
838 {
839 compression = HttpCompression_None;
840 }
841
819 switch (compression) 842 switch (compression)
820 { 843 {
821 case HttpCompression_None: 844 case HttpCompression_None:
822 { 845 {
823 if (isGzipAllowed_ || isDeflateAllowed_) 846 if (isGzipAllowed_ || isDeflateAllowed_)