changeset 5119:bdec57f3cbf2

New configuration KeepAliveTimeout with a default value of 1 second
author Alain Mazy <am@osimis.io>
date Wed, 14 Dec 2022 11:50:43 +0100
parents 030cd210845e
children a6fa660ec26e
files NEWS OrthancFramework/Resources/CMake/CivetwebConfiguration.cmake OrthancFramework/Sources/HttpServer/HttpOutput.cpp OrthancFramework/Sources/HttpServer/HttpOutput.h OrthancFramework/Sources/HttpServer/HttpServer.cpp OrthancFramework/Sources/HttpServer/HttpServer.h OrthancFramework/Sources/HttpServer/IHttpHandler.cpp OrthancFramework/Sources/RestApi/RestApi.cpp OrthancServer/Resources/Configuration.json OrthancServer/Sources/main.cpp
diffstat 10 files changed, 55 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Fri Dec 09 12:42:17 2022 +0100
+++ b/NEWS	Wed Dec 14 11:50:43 2022 +0100
@@ -9,6 +9,7 @@
 * Made the default SQLite DB more robust wrt future updates like adding new columns in DB.
 * Made the HTTP Client errors more verbose by including the url in the logs.
 * Optimization: now using multiple threads to transcode files for asynchronous download of studies archive.
+* New configuration "KeepAliveTimeout" with a default value of 1 second.
 
 REST API
 --------
--- a/OrthancFramework/Resources/CMake/CivetwebConfiguration.cmake	Fri Dec 09 12:42:17 2022 +0100
+++ b/OrthancFramework/Resources/CMake/CivetwebConfiguration.cmake	Wed Dec 14 11:50:43 2022 +0100
@@ -140,9 +140,3 @@
 
   unset(CMAKE_REQUIRED_LIBRARIES)  # This reset must be after "CHECK_LIBRARY_EXISTS"
 endif()
-
-
-# New in Orthanc 1.8.1
-add_definitions(
-  -DCIVETWEB_KEEP_ALIVE_TIMEOUT_SECONDS=10
-  )
--- a/OrthancFramework/Sources/HttpServer/HttpOutput.cpp	Fri Dec 09 12:42:17 2022 +0100
+++ b/OrthancFramework/Sources/HttpServer/HttpOutput.cpp	Wed Dec 14 11:50:43 2022 +0100
@@ -47,14 +47,16 @@
 namespace Orthanc
 {
   HttpOutput::StateMachine::StateMachine(IHttpOutputStream& stream,
-                                         bool isKeepAlive) : 
+                                         bool isKeepAlive,
+                                         unsigned int keepAliveTimeout) : 
     stream_(stream),
     state_(State_WritingHeader),
     status_(HttpStatus_200_Ok),
     hasContentLength_(false),
     contentLength_(0),
     contentPosition_(0),
-    keepAlive_(isKeepAlive)
+    keepAlive_(isKeepAlive),
+    keepAliveTimeout_(keepAliveTimeout)
   {
   }
 
@@ -189,7 +191,7 @@
          * HTTP header, so we can't use the milliseconds granularity.
          **/
         s += ("Keep-Alive: timeout=" +
-              boost::lexical_cast<std::string>(CIVETWEB_KEEP_ALIVE_TIMEOUT_SECONDS) + "\r\n");
+              boost::lexical_cast<std::string>(keepAliveTimeout_) + "\r\n");
       }
       else
       {
@@ -299,8 +301,9 @@
 
 
   HttpOutput::HttpOutput(IHttpOutputStream &stream,
-                         bool isKeepAlive) :
-    stateMachine_(stream, isKeepAlive),
+                         bool isKeepAlive,
+                         unsigned int keepAliveTimeout) :
+    stateMachine_(stream, isKeepAlive, keepAliveTimeout),
     isDeflateAllowed_(false),
     isGzipAllowed_(false)
   {
--- a/OrthancFramework/Sources/HttpServer/HttpOutput.h	Fri Dec 09 12:42:17 2022 +0100
+++ b/OrthancFramework/Sources/HttpServer/HttpOutput.h	Wed Dec 14 11:50:43 2022 +0100
@@ -61,6 +61,7 @@
       uint64_t contentLength_;
       uint64_t contentPosition_;
       bool keepAlive_;
+      unsigned int keepAliveTimeout_;
       std::list<std::string> headers_;
 
       std::string multipartBoundary_;
@@ -70,7 +71,8 @@
 
     public:
       StateMachine(IHttpOutputStream& stream,
-                   bool isKeepAlive);
+                   bool isKeepAlive,
+                   unsigned int keepAliveTimeout);
 
       ~StateMachine();
 
@@ -126,7 +128,8 @@
 
   public:
     HttpOutput(IHttpOutputStream& stream,
-               bool isKeepAlive);
+               bool isKeepAlive,
+               unsigned int keepAliveTimeout);
 
     void SetDeflateAllowed(bool allowed);
 
--- a/OrthancFramework/Sources/HttpServer/HttpServer.cpp	Fri Dec 09 12:42:17 2022 +0100
+++ b/OrthancFramework/Sources/HttpServer/HttpServer.cpp	Wed Dec 14 11:50:43 2022 +0100
@@ -353,7 +353,7 @@
                         size_t size)
     {
       StringHttpOutput stringOutput;
-      HttpOutput fakeOutput(stringOutput, false);
+      HttpOutput fakeOutput(stringOutput, false /* assume no keep-alive */, 0);
       HttpToolbox::GetArguments getArguments;
       
       if (!handler_.Handle(fakeOutput, RequestOrigin_RestApi, remoteIp_.c_str(), username_.c_str(), 
@@ -1456,13 +1456,13 @@
       if (server == NULL)
       {
         MongooseOutputStream stream(connection);
-        HttpOutput output(stream, false /* assume no keep-alive */);
+        HttpOutput output(stream, false /* assume no keep-alive */, 0);
         output.SendStatus(HttpStatus_500_InternalServerError);
         return;
       }
 
       MongooseOutputStream stream(connection);
-      HttpOutput output(stream, server->IsKeepAliveEnabled());
+      HttpOutput output(stream, server->IsKeepAliveEnabled(), server->GetKeepAliveTimeout());
       HttpMethod method = HttpMethod_Get;
 
       try
@@ -1588,6 +1588,7 @@
     port_(8000),
     filter_(NULL),
     keepAlive_(false),
+    keepAliveTimeout_(1),
     httpCompression_(true),
     exceptionFormatter_(NULL),
     realm_(ORTHANC_REALM),
@@ -1655,7 +1656,7 @@
       std::string port = boost::lexical_cast<std::string>(port_);
       std::string numThreads = boost::lexical_cast<std::string>(threadsCount_);
       std::string requestTimeoutMilliseconds = boost::lexical_cast<std::string>(requestTimeout_ * 1000);
-      std::string keepAliveTimeoutMilliseconds = boost::lexical_cast<std::string>(CIVETWEB_KEEP_ALIVE_TIMEOUT_SECONDS * 1000);
+      std::string keepAliveTimeoutMilliseconds = boost::lexical_cast<std::string>(keepAliveTimeout_ * 1000);
       std::string sslMinimumVersion = boost::lexical_cast<std::string>(sslMinimumVersion_);
 
       if (ssl_)
@@ -1959,6 +1960,20 @@
 #endif
   }
 
+  void HttpServer::SetKeepAliveTimeout(unsigned int timeout)
+  {
+    Stop();
+    keepAliveTimeout_ = timeout;
+    CLOG(INFO, HTTP) << "HTTP keep alive Timeout is now " << keepAliveTimeout_ << " seconds";
+
+#if ORTHANC_ENABLE_MONGOOSE == 1
+    if (enabled)
+    {
+      CLOG(WARNING, HTTP) << "You should disable HTTP keep alive, as you are using Mongoose";
+    }
+#endif
+  }
+
   const std::string &HttpServer::GetSslCertificate() const
   {
     return certificate_;
@@ -1998,6 +2013,11 @@
     return keepAlive_;
   }
 
+  unsigned int HttpServer::GetKeepAliveTimeout() const
+  {
+    return keepAliveTimeout_;
+  }
+
   void HttpServer::SetRemoteAccessAllowed(bool allowed)
   {
     Stop();
--- a/OrthancFramework/Sources/HttpServer/HttpServer.h	Fri Dec 09 12:42:17 2022 +0100
+++ b/OrthancFramework/Sources/HttpServer/HttpServer.h	Wed Dec 14 11:50:43 2022 +0100
@@ -106,6 +106,7 @@
     uint16_t port_;
     IIncomingHttpRequestFilter* filter_;
     bool keepAlive_;
+    unsigned int keepAliveTimeout_;
     bool httpCompression_;
     IHttpExceptionFormatter* exceptionFormatter_;
     std::string realm_;
@@ -157,8 +158,12 @@
 
     bool IsKeepAliveEnabled() const;
 
+    unsigned int GetKeepAliveTimeout() const;
+
     void SetKeepAliveEnabled(bool enabled);
 
+    void SetKeepAliveTimeout(unsigned int timeout);
+
     const std::string& GetSslCertificate() const;
 
     void SetSslCertificate(const char* path);
--- a/OrthancFramework/Sources/HttpServer/IHttpHandler.cpp	Fri Dec 09 12:42:17 2022 +0100
+++ b/OrthancFramework/Sources/HttpServer/IHttpHandler.cpp	Wed Dec 14 11:50:43 2022 +0100
@@ -45,7 +45,7 @@
     HttpToolbox::ParseGetQuery(curi, getArguments, uri.c_str());
 
     StringHttpOutput stream;
-    HttpOutput http(stream, false /* no keep alive */);
+    HttpOutput http(stream, false /* assume no keep-alive */, 0);
 
     if (handler.Handle(http, origin, LOCALHOST, "", HttpMethod_Get, curi, 
                        httpHeaders, getArguments, NULL /* no body for GET */, 0))
@@ -82,7 +82,7 @@
     Toolbox::SplitUriComponents(curi, uri);
 
     StringHttpOutput stream;
-    HttpOutput http(stream, false /* no keep alive */);
+    HttpOutput http(stream, false /* assume no keep-alive */, 0);
 
     if (handler.Handle(http, origin, LOCALHOST, "", method, curi, 
                        httpHeaders, getArguments, bodyData, bodySize))
@@ -141,7 +141,7 @@
     HttpToolbox::GetArguments getArguments;  // No GET argument for DELETE
 
     StringHttpOutput stream;
-    HttpOutput http(stream, false /* no keep alive */);
+    HttpOutput http(stream, false /* assume no keep-alive */, 0);
 
     if (handler.Handle(http, origin, LOCALHOST, "", HttpMethod_Delete, curi, 
                        httpHeaders, getArguments, NULL /* no body for DELETE */, 0))
--- a/OrthancFramework/Sources/RestApi/RestApi.cpp	Fri Dec 09 12:42:17 2022 +0100
+++ b/OrthancFramework/Sources/RestApi/RestApi.cpp	Wed Dec 14 11:50:43 2022 +0100
@@ -182,7 +182,7 @@
           totalPathsCount_ ++;
           
           StringHttpOutput o1;
-          HttpOutput o2(o1, false);
+          HttpOutput o2(o1, false /* assume no keep-alive */, 0);
           RestApiOutput o3(o2, HttpMethod_Get);
           RestApiGetCall call(o3, restApi_, RequestOrigin_Documentation, "" /* remote IP */,
                               "" /* username */, HttpToolbox::Arguments() /* HTTP headers */,
@@ -220,7 +220,7 @@
           totalPathsCount_ ++;
           
           StringHttpOutput o1;
-          HttpOutput o2(o1, false);
+          HttpOutput o2(o1, false /* assume no keep-alive */, 0);
           RestApiOutput o3(o2, HttpMethod_Post);
           RestApiPostCall call(o3, restApi_, RequestOrigin_Documentation, "" /* remote IP */,
                                "" /* username */, HttpToolbox::Arguments() /* HTTP headers */,
@@ -258,7 +258,7 @@
           totalPathsCount_ ++;
           
           StringHttpOutput o1;
-          HttpOutput o2(o1, false);
+          HttpOutput o2(o1, false /* assume no keep-alive */, 0);
           RestApiOutput o3(o2, HttpMethod_Delete);
           RestApiDeleteCall call(o3, restApi_, RequestOrigin_Documentation, "" /* remote IP */,
                                  "" /* username */, HttpToolbox::Arguments() /* HTTP headers */,
@@ -295,7 +295,7 @@
           totalPathsCount_ ++;
           
           StringHttpOutput o1;
-          HttpOutput o2(o1, false);
+          HttpOutput o2(o1, false /* assume no keep-alive */, 0);
           RestApiOutput o3(o2, HttpMethod_Put);
           RestApiPutCall call(o3, restApi_, RequestOrigin_Documentation, "" /* remote IP */,
                               "" /* username */, HttpToolbox::Arguments() /* HTTP headers */,
--- a/OrthancServer/Resources/Configuration.json	Fri Dec 09 12:42:17 2022 +0100
+++ b/OrthancServer/Resources/Configuration.json	Wed Dec 14 11:50:43 2022 +0100
@@ -596,6 +596,10 @@
   // Mongoose.
   "KeepAlive" : true,
 
+  // Defines the Keep-Alive timeout in seconds.
+  // (new in Orthanc 1.11.3)
+  "KeepAliveTimeout" : 1,
+
   // Enable or disable Nagle's algorithm. Only taken into
   // consideration if Orthanc is compiled to use CivetWeb. Experiments
   // show that best performance can be obtained by setting both
--- a/OrthancServer/Sources/main.cpp	Fri Dec 09 12:42:17 2022 +0100
+++ b/OrthancServer/Sources/main.cpp	Wed Dec 14 11:50:43 2022 +0100
@@ -1029,6 +1029,7 @@
       httpServer.SetPortNumber(lock.GetConfiguration().GetUnsignedIntegerParameter("HttpPort", 8042));
       httpServer.SetRemoteAccessAllowed(lock.GetConfiguration().GetBooleanParameter("RemoteAccessAllowed", false));
       httpServer.SetKeepAliveEnabled(lock.GetConfiguration().GetBooleanParameter("KeepAlive", defaultKeepAlive));
+      httpServer.SetKeepAliveTimeout(lock.GetConfiguration().GetUnsignedIntegerParameter("KeepAliveTimeout", 1));
       httpServer.SetHttpCompressionEnabled(lock.GetConfiguration().GetBooleanParameter("HttpCompressionEnabled", true));
       httpServer.SetTcpNoDelay(lock.GetConfiguration().GetBooleanParameter("TcpNoDelay", true));
       httpServer.SetRequestTimeout(lock.GetConfiguration().GetUnsignedIntegerParameter("HttpRequestTimeout", 30));