# HG changeset patch # User Alain Mazy # Date 1671015043 -3600 # Node ID bdec57f3cbf2854da5ae4b57244c430ebc6263f7 # Parent 030cd210845e11736020baaec88e3f78fab1fa63 New configuration KeepAliveTimeout with a default value of 1 second diff -r 030cd210845e -r bdec57f3cbf2 NEWS --- 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 -------- diff -r 030cd210845e -r bdec57f3cbf2 OrthancFramework/Resources/CMake/CivetwebConfiguration.cmake --- 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 - ) diff -r 030cd210845e -r bdec57f3cbf2 OrthancFramework/Sources/HttpServer/HttpOutput.cpp --- 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(CIVETWEB_KEEP_ALIVE_TIMEOUT_SECONDS) + "\r\n"); + boost::lexical_cast(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) { diff -r 030cd210845e -r bdec57f3cbf2 OrthancFramework/Sources/HttpServer/HttpOutput.h --- 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 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); diff -r 030cd210845e -r bdec57f3cbf2 OrthancFramework/Sources/HttpServer/HttpServer.cpp --- 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(port_); std::string numThreads = boost::lexical_cast(threadsCount_); std::string requestTimeoutMilliseconds = boost::lexical_cast(requestTimeout_ * 1000); - std::string keepAliveTimeoutMilliseconds = boost::lexical_cast(CIVETWEB_KEEP_ALIVE_TIMEOUT_SECONDS * 1000); + std::string keepAliveTimeoutMilliseconds = boost::lexical_cast(keepAliveTimeout_ * 1000); std::string sslMinimumVersion = boost::lexical_cast(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(); diff -r 030cd210845e -r bdec57f3cbf2 OrthancFramework/Sources/HttpServer/HttpServer.h --- 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); diff -r 030cd210845e -r bdec57f3cbf2 OrthancFramework/Sources/HttpServer/IHttpHandler.cpp --- 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)) diff -r 030cd210845e -r bdec57f3cbf2 OrthancFramework/Sources/RestApi/RestApi.cpp --- 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 */, diff -r 030cd210845e -r bdec57f3cbf2 OrthancServer/Resources/Configuration.json --- 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 diff -r 030cd210845e -r bdec57f3cbf2 OrthancServer/Sources/main.cpp --- 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));