Mercurial > hg > orthanc
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_) |