changeset 1115:da56a7916e8a

Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 02 Sep 2014 17:30:13 +0200
parents adfd2c7a92f3
children 96a280b815f4
files Core/HttpServer/HttpOutput.cpp Core/HttpServer/HttpOutput.h Core/HttpServer/MongooseServer.cpp Core/HttpServer/MongooseServer.h NEWS OrthancServer/main.cpp Plugins/Engine/PluginsHttpHandler.cpp Resources/Configuration.json
diffstat 8 files changed, 53 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/Core/HttpServer/HttpOutput.cpp	Tue Sep 02 15:56:36 2014 +0200
+++ b/Core/HttpServer/HttpOutput.cpp	Tue Sep 02 17:30:13 2014 +0200
@@ -43,12 +43,14 @@
 
 namespace Orthanc
 {
-  HttpOutput::StateMachine::StateMachine(IHttpOutputStream& stream) : 
+  HttpOutput::StateMachine::StateMachine(IHttpOutputStream& stream,
+                                         bool isKeepAlive) : 
     stream_(stream),
     state_(State_WritingHeader),
     status_(HttpStatus_200_Ok),
     hasContentLength_(false),
-    contentPosition_(0)
+    contentPosition_(0),
+    keepAlive_(isKeepAlive)
   {
   }
 
@@ -160,9 +162,9 @@
         " " + std::string(EnumerationToString(status_)) +
         "\r\n";
 
-      if (status_ != HttpStatus_200_Ok)
+      if (keepAlive_)
       {
-        hasContentLength_ = false;
+        s += "Connection: keep-alive\r\n";
       }
 
       for (std::list<std::string>::const_iterator
@@ -171,6 +173,11 @@
         s += *it;
       }
 
+      if (status_ != HttpStatus_200_Ok)
+      {
+        hasContentLength_ = false;
+      }
+
       uint64_t contentLength = (hasContentLength_ ? contentLength_ : length);
       s += "Content-Length: " + boost::lexical_cast<std::string>(contentLength) + "\r\n\r\n";
 
--- a/Core/HttpServer/HttpOutput.h	Tue Sep 02 15:56:36 2014 +0200
+++ b/Core/HttpServer/HttpOutput.h	Tue Sep 02 17:30:13 2014 +0200
@@ -63,10 +63,12 @@
       bool hasContentLength_;
       uint64_t contentLength_;
       uint64_t contentPosition_;
+      bool keepAlive_;
       std::list<std::string> headers_;
 
     public:
-      StateMachine(IHttpOutputStream& stream);
+      StateMachine(IHttpOutputStream& stream,
+                   bool isKeepAlive);
 
       ~StateMachine();
 
@@ -92,7 +94,9 @@
     StateMachine stateMachine_;
 
   public:
-    HttpOutput(IHttpOutputStream& stream) : stateMachine_(stream)
+    HttpOutput(IHttpOutputStream& stream,
+               bool isKeepAlive) : 
+      stateMachine_(stream, isKeepAlive)
     {
     }
 
--- a/Core/HttpServer/MongooseServer.cpp	Tue Sep 02 15:56:36 2014 +0200
+++ b/Core/HttpServer/MongooseServer.cpp	Tue Sep 02 17:30:13 2014 +0200
@@ -552,7 +552,7 @@
   {
     MongooseServer* that = reinterpret_cast<MongooseServer*>(request->user_data);
     MongooseOutputStream stream(connection);
-    HttpOutput output(stream);
+    HttpOutput output(stream, that->IsKeepAliveEnabled());
 
     // Check remote calls
     if (!that->IsRemoteAccessAllowed() &&
@@ -786,6 +786,7 @@
     ssl_ = false;
     port_ = 8000;
     filter_ = NULL;
+    keepAlive_ = false;
 
 #if ORTHANC_SSL_ENABLED == 1
     // Check for the Heartbleed exploit
@@ -829,7 +830,7 @@
         
         // Optimization reported by Chris Hafey
         // https://groups.google.com/d/msg/orthanc-users/CKueKX0pJ9E/_UCbl8T-VjIJ
-        // "enable_keep_alive", "yes",
+        "enable_keep_alive", (keepAlive_ ? "yes" : "no"),
 
         // Set the SSL certificate, if any. This must be the last option.
         ssl_ ? "ssl_certificate" : NULL,
@@ -917,6 +918,15 @@
 #endif
   }
 
+
+  void MongooseServer::SetKeepAliveEnabled(bool enabled)
+  {
+    Stop();
+    keepAlive_ = enabled;
+    LOG(WARNING) << "HTTP keep alive is " << (enabled ? "enabled" : "disabled");
+  }
+
+
   void MongooseServer::SetAuthenticationEnabled(bool enabled)
   {
     Stop();
--- a/Core/HttpServer/MongooseServer.h	Tue Sep 02 15:56:36 2014 +0200
+++ b/Core/HttpServer/MongooseServer.h	Tue Sep 02 17:30:13 2014 +0200
@@ -78,6 +78,7 @@
     std::string certificate_;
     uint16_t port_;
     IIncomingHttpRequestFilter* filter_;
+    bool keepAlive_;
   
     bool IsRunning() const;
 
@@ -118,6 +119,13 @@
 
     void SetSslEnabled(bool enabled);
 
+    bool IsKeepAliveEnabled() const
+    {
+      return keepAlive_;
+    }
+
+    void SetKeepAliveEnabled(bool enabled);
+
     const std::string& GetSslCertificate() const
     {
       return certificate_;
--- a/NEWS	Tue Sep 02 15:56:36 2014 +0200
+++ b/NEWS	Tue Sep 02 17:30:13 2014 +0200
@@ -2,7 +2,8 @@
 ===============================
 
 * Refactoring of HttpOutput ("Content-Length" header is now always sent)
-* Fixes for Visual Studio 2013 and Visual Studio 64bit
+* Fixes for Visual Studio 2013 and Windows 64bit
+* Experimental "KeepAlive" configuration option to enable HTTP Keep-Alive
 
 
 Version 0.8.2 (2014/08/07)
--- a/OrthancServer/main.cpp	Tue Sep 02 15:56:36 2014 +0200
+++ b/OrthancServer/main.cpp	Tue Sep 02 17:30:13 2014 +0200
@@ -369,6 +369,7 @@
     MongooseServer httpServer;
     httpServer.SetPortNumber(Configuration::GetGlobalIntegerParameter("HttpPort", 8042));
     httpServer.SetRemoteAccessAllowed(Configuration::GetGlobalBoolParameter("RemoteAccessAllowed", false));
+    httpServer.SetKeepAliveEnabled(Configuration::GetGlobalBoolParameter("KeepAlive", false));
     httpServer.SetIncomingHttpRequestFilter(httpFilter);
 
     httpServer.SetAuthenticationEnabled(Configuration::GetGlobalBoolParameter("AuthenticationEnabled", false));
--- a/Plugins/Engine/PluginsHttpHandler.cpp	Tue Sep 02 15:56:36 2014 +0200
+++ b/Plugins/Engine/PluginsHttpHandler.cpp	Tue Sep 02 17:30:13 2014 +0200
@@ -478,7 +478,7 @@
     HttpHandler::ParseGetQuery(uri, getArguments, p.uri);
 
     StringHttpOutput stream;
-    HttpOutput http(stream);
+    HttpOutput http(stream, false /* no keep alive */);
 
     LOG(INFO) << "Plugin making REST GET call on URI " << p.uri;
 
@@ -511,7 +511,7 @@
     std::string body(p.body, p.bodySize);
 
     StringHttpOutput stream;
-    HttpOutput http(stream);
+    HttpOutput http(stream, false /* no keep alive */);
 
     HttpMethod method = (isPost ? HttpMethod_Post : HttpMethod_Put);
     LOG(INFO) << "Plugin making REST " << EnumerationToString(method) << " call on URI " << p.uri;
@@ -541,7 +541,7 @@
     std::string body;  // No body for DELETE
 
     StringHttpOutput stream;
-    HttpOutput http(stream);
+    HttpOutput http(stream, false /* no keep alive */);
 
     LOG(INFO) << "Plugin making REST DELETE call on URI " 
               << reinterpret_cast<const char*>(parameters);
--- a/Resources/Configuration.json	Tue Sep 02 15:56:36 2014 +0200
+++ b/Resources/Configuration.json	Tue Sep 02 17:30:13 2014 +0200
@@ -62,6 +62,13 @@
   // The DICOM port
   "DicomPort" : 4242,
 
+  // The default encoding that is assumed for DICOM files without
+  // "SpecificCharacterSet" DICOM tag. The allowed values are "Ascii",
+  // "Utf8", "Latin1", "Latin2", "Latin3", "Latin4", "Latin5",
+  // "Cyrillic", "Arabic", "Greek", "Hebrew", "Thai", "Japanese",
+  // and "Chinese".
+  "DefaultEncoding" : "Latin1",
+
 
 
   /**
@@ -182,10 +189,7 @@
   // some job finishes.
   "LimitJobs" : 10,
 
-  // The default encoding that is assumed for DICOM files without
-  // "SpecificCharacterSet" DICOM tag. The allowed values are "Ascii",
-  // "Utf8", "Latin1", "Latin2", "Latin3", "Latin4", "Latin5",
-  // "Cyrillic", "Arabic", "Greek", "Hebrew", "Thai", "Japanese",
-  // and "Chinese".
-  "DefaultEncoding" : "Latin1"
+  // Enable or disable HTTP Keep-Alive (experimental). Set this option
+  // to "true" only in the case of high HTTP loads.
+  "KeepAlive" : false
 }