changeset 1645:1558b3226b18

IHttpExceptionFormatter
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 24 Sep 2015 15:55:17 +0200
parents 939b921b2c81
children da799f767e5d
files Core/HttpServer/HttpOutput.cpp Core/HttpServer/HttpOutput.h Core/HttpServer/MongooseServer.cpp Core/HttpServer/MongooseServer.h OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp OrthancServer/main.cpp Plugins/Engine/OrthancPlugins.h Plugins/Engine/PluginsEnumerations.cpp Plugins/Engine/PluginsErrorDictionary.cpp Plugins/Engine/PluginsErrorDictionary.h
diffstat 10 files changed, 140 insertions(+), 101 deletions(-) [+]
line wrap: on
line diff
--- a/Core/HttpServer/HttpOutput.cpp	Wed Sep 23 22:05:27 2015 +0200
+++ b/Core/HttpServer/HttpOutput.cpp	Thu Sep 24 15:55:17 2015 +0200
@@ -302,15 +302,7 @@
     
     stateMachine_.ClearHeaders();
     stateMachine_.SetHttpStatus(status);
-
-    if (describeErrors_)
-    {
-      stateMachine_.SendBody(message, messageSize);
-    }
-    else
-    {
-      stateMachine_.SendBody(NULL, 0);
-    }
+    stateMachine_.SendBody(message, messageSize);
   }
 
 
--- a/Core/HttpServer/HttpOutput.h	Wed Sep 23 22:05:27 2015 +0200
+++ b/Core/HttpServer/HttpOutput.h	Thu Sep 24 15:55:17 2015 +0200
@@ -114,7 +114,6 @@
     StateMachine stateMachine_;
     bool         isDeflateAllowed_;
     bool         isGzipAllowed_;
-    bool         describeErrors_;
 
     HttpCompression GetPreferredCompression(size_t bodySize) const;
 
@@ -123,8 +122,7 @@
                bool isKeepAlive) : 
       stateMachine_(stream, isKeepAlive),
       isDeflateAllowed_(false),
-      isGzipAllowed_(false),
-      describeErrors_(true)
+      isGzipAllowed_(false)
     {
     }
 
@@ -148,16 +146,6 @@
       return isGzipAllowed_;
     }
 
-    void SetDescribeErrorsEnabled(bool enabled)
-    {
-      describeErrors_ = enabled;
-    }
-
-    bool IsDescribeErrorsEnabled() const
-    {
-      return describeErrors_;      
-    }
-
     void SendStatus(HttpStatus status,
 		    const char* message,
 		    size_t messageSize);
--- a/Core/HttpServer/MongooseServer.cpp	Wed Sep 23 22:05:27 2015 +0200
+++ b/Core/HttpServer/MongooseServer.cpp	Thu Sep 24 15:55:17 2015 +0200
@@ -36,7 +36,6 @@
 #include "MongooseServer.h"
 
 #include "../Logging.h"
-#include "../OrthancException.h"
 #include "../ChunkedBuffer.h"
 #include "HttpToolbox.h"
 #include "mongoose.h"
@@ -583,7 +582,6 @@
 
     MongooseOutputStream stream(connection);
     HttpOutput output(stream, that->IsKeepAliveEnabled());
-    output.SetDescribeErrorsEnabled(that->IsDescribeErrorsEnabled());
 
     // Check remote calls
     if (!that->IsRemoteAccessAllowed() &&
@@ -735,12 +733,12 @@
       }
       catch (boost::bad_lexical_cast&)
       {
-        throw OrthancException(ErrorCode_BadParameterType, HttpStatus_400_BadRequest);
+        throw OrthancException(ErrorCode_BadParameterType);
       }
       catch (std::runtime_error&)
       {
         // Presumably an error while parsing the JSON body
-        throw OrthancException(ErrorCode_BadRequest, HttpStatus_400_BadRequest);
+        throw OrthancException(ErrorCode_BadRequest);
       }
 
       if (!found)
@@ -753,22 +751,16 @@
       // Using this candidate handler results in an exception
       LOG(ERROR) << "Exception in the HTTP handler: " << e.What();
 
-      Json::Value message = Json::objectValue;
-      message["Method"] = EnumerationToString(method);
-      message["Uri"] = request->uri;
-
-      // TODO
-      message["HttpError"] = EnumerationToString(e.GetHttpStatus());
-      message["HttpStatus"] = e.GetHttpStatus();
-      message["Message"] = e.What();
-      message["OrthancError"] = EnumerationToString(e.GetErrorCode());
-      message["OrthancStatus"] = e.GetErrorCode();
-
-      std::string info = message.toStyledString();
-
       try
       {
-	output.SendStatus(e.GetHttpStatus(), info);
+        if (that->GetExceptionFormatter() == NULL)
+        {
+          output.SendStatus(e.GetHttpStatus());
+        }
+        else
+        {
+          that->GetExceptionFormatter()->Format(output, e, method, request->uri);
+        }
       }
       catch (OrthancException&)
       {
@@ -834,7 +826,7 @@
     filter_ = NULL;
     keepAlive_ = false;
     httpCompression_ = true;
-    describeErrors_ = true;
+    exceptionFormatter_ = NULL;
 
 #if ORTHANC_SSL_ENABLED == 1
     // Check for the Heartbleed exploit
@@ -985,18 +977,20 @@
     LOG(WARNING) << "HTTP compression is " << (enabled ? "enabled" : "disabled");
   }
   
-  void MongooseServer::SetDescribeErrorsEnabled(bool enabled)
-  {
-    describeErrors_ = enabled;
-    LOG(INFO) << "Description of the errors in the HTTP answers is " << (enabled ? "enabled" : "disabled");
-  }
-
   void MongooseServer::SetIncomingHttpRequestFilter(IIncomingHttpRequestFilter& filter)
   {
     Stop();
     filter_ = &filter;
   }
 
+
+  void MongooseServer::SetHttpExceptionFormatter(IHttpExceptionFormatter& formatter)
+  {
+    Stop();
+    exceptionFormatter_ = &formatter;
+  }
+
+
   bool MongooseServer::IsValidBasicHttpAuthentication(const std::string& basic) const
   {
     return registeredUsers_.find(basic) != registeredUsers_.end();
--- a/Core/HttpServer/MongooseServer.h	Wed Sep 23 22:05:27 2015 +0200
+++ b/Core/HttpServer/MongooseServer.h	Thu Sep 24 15:55:17 2015 +0200
@@ -34,6 +34,8 @@
 
 #include "IHttpHandler.h"
 
+#include "../OrthancException.h"
+
 #include <list>
 #include <map>
 #include <set>
@@ -57,6 +59,21 @@
                            const char* username) const = 0;
   };
 
+
+  class IHttpExceptionFormatter
+  {
+  public:
+    virtual ~IHttpExceptionFormatter()
+    {
+    }
+
+    virtual void Format(HttpOutput& output,
+                        const OrthancException& exception,
+                        HttpMethod method,
+                        const char* uri) = 0;
+  };
+
+
   class MongooseServer
   {
   private:
@@ -77,7 +94,7 @@
     IIncomingHttpRequestFilter* filter_;
     bool keepAlive_;
     bool httpCompression_;
-    bool describeErrors_;
+    IHttpExceptionFormatter* exceptionFormatter_;
   
     bool IsRunning() const;
 
@@ -144,13 +161,6 @@
 
     void SetHttpCompressionEnabled(bool enabled);
 
-    bool IsDescribeErrorsEnabled() const
-    {
-      return describeErrors_;
-    }
-
-    void SetDescribeErrorsEnabled(bool enabled);
-
     const IIncomingHttpRequestFilter* GetIncomingHttpRequestFilter() const
     {
       return filter_;
@@ -170,5 +180,12 @@
     }
 
     IHttpHandler& GetHandler() const;
+
+    void SetHttpExceptionFormatter(IHttpExceptionFormatter& formatter);
+
+    IHttpExceptionFormatter* GetExceptionFormatter()
+    {
+      return exceptionFormatter_;
+    }
   };
 }
--- a/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp	Wed Sep 23 22:05:27 2015 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp	Thu Sep 24 15:55:17 2015 +0200
@@ -365,6 +365,8 @@
 
   static void ModifyInstance(RestApiPostCall& call)
   {
+    throw OrthancException(ErrorCode_CannotStoreInstance);
+
     DicomModification modification;
     modification.SetAllowManualIdentifiers(true);
 
--- a/OrthancServer/main.cpp	Wed Sep 23 22:05:27 2015 +0200
+++ b/OrthancServer/main.cpp	Thu Sep 24 15:55:17 2015 +0200
@@ -307,6 +307,67 @@
 };
 
 
+
+class MyHttpExceptionFormatter : public IHttpExceptionFormatter
+{
+private:
+  bool             describeErrors_;
+  OrthancPlugins*  plugins_;
+
+public:
+  MyHttpExceptionFormatter(bool describeErrors,
+                           OrthancPlugins* plugins) :
+    describeErrors_(describeErrors),
+    plugins_(plugins)
+  {
+  }
+
+  virtual void Format(HttpOutput& output,
+                      const OrthancException& exception,
+                      HttpMethod method,
+                      const char* uri)
+  {
+    if (!describeErrors_)
+    {
+      output.SendStatus(exception.GetHttpStatus());
+      return;
+    }
+
+    Json::Value message = Json::objectValue;
+    message["Method"] = EnumerationToString(method);
+    message["Uri"] = uri;
+
+    ErrorCode errorCode = exception.GetErrorCode();
+    HttpStatus httpStatus = exception.GetHttpStatus();
+
+    bool isPlugin = false;
+
+#if ORTHANC_PLUGINS_ENABLED == 1
+    if (plugins_ != NULL &&
+        plugins_->GetErrorDictionary().Format(message, httpStatus, exception))
+    {
+      errorCode = ErrorCode_Plugin;
+      isPlugin = true;
+    }
+#endif
+
+    if (!isPlugin)
+    {
+      message["Message"] = exception.What();
+    }
+
+    message["HttpError"] = EnumerationToString(httpStatus);
+    message["HttpStatus"] = httpStatus;
+    message["OrthancError"] = EnumerationToString(errorCode);
+    message["OrthancStatus"] = errorCode;
+
+    std::string info = message.toStyledString();
+    output.SendStatus(httpStatus, info);
+  }
+};
+
+
+
 static void PrintHelp(char* path)
 {
   std::cout 
@@ -413,7 +474,8 @@
 
 
 static bool StartHttpServer(ServerContext& context,
-                            OrthancRestApi& restApi)
+                            OrthancRestApi& restApi,
+                            OrthancPlugins* plugins)
 {
   if (!Configuration::GetGlobalBoolParameter("HttpServerEnabled", true))
   {
@@ -421,6 +483,9 @@
     return WaitForExit(context, restApi);
   }
 
+  MyHttpExceptionFormatter exceptionFormatter(Configuration::GetGlobalBoolParameter("HttpDescribeErrors", true), plugins);
+  
+
   // HTTP server
   MyIncomingHttpRequestFilter httpFilter(context);
   MongooseServer httpServer;
@@ -428,8 +493,8 @@
   httpServer.SetRemoteAccessAllowed(Configuration::GetGlobalBoolParameter("RemoteAccessAllowed", false));
   httpServer.SetKeepAliveEnabled(Configuration::GetGlobalBoolParameter("KeepAlive", false));
   httpServer.SetHttpCompressionEnabled(Configuration::GetGlobalBoolParameter("HttpCompressionEnabled", true));
-  httpServer.SetDescribeErrorsEnabled(Configuration::GetGlobalBoolParameter("HttpDescribeErrors", true));
   httpServer.SetIncomingHttpRequestFilter(httpFilter);
+  httpServer.SetHttpExceptionFormatter(exceptionFormatter);
 
   httpServer.SetAuthenticationEnabled(Configuration::GetGlobalBoolParameter("AuthenticationEnabled", false));
   Configuration::SetupRegisteredUsers(httpServer);
@@ -461,12 +526,13 @@
 
 
 static bool StartDicomServer(ServerContext& context,
-                             OrthancRestApi& restApi)
+                             OrthancRestApi& restApi,
+                             OrthancPlugins* plugins)
 {
   if (!Configuration::GetGlobalBoolParameter("DicomServerEnabled", true))
   {
     LOG(WARNING) << "The DICOM server is disabled";
-    return StartHttpServer(context, restApi);
+    return StartHttpServer(context, restApi, plugins);
   }
 
   MyDicomServerFactory serverFactory(context);
@@ -485,7 +551,7 @@
   dicomServer.Start();
   LOG(WARNING) << "DICOM server listening on port: " << dicomServer.GetPortNumber();
 
-  bool restart = StartHttpServer(context, restApi);
+  bool restart = StartHttpServer(context, restApi, plugins);
 
   dicomServer.Stop();
   LOG(WARNING) << "    DICOM server has stopped";
@@ -522,7 +588,7 @@
   OrthancRestApi restApi(context);
   context.GetHttpHandler().Register(restApi, true);
 
-  return StartDicomServer(context, restApi);
+  return StartDicomServer(context, restApi, plugins);
 }
 
 
--- a/Plugins/Engine/OrthancPlugins.h	Wed Sep 23 22:05:27 2015 +0200
+++ b/Plugins/Engine/OrthancPlugins.h	Thu Sep 24 15:55:17 2015 +0200
@@ -42,14 +42,6 @@
 {
   class OrthancPlugins : public boost::noncopyable
   {
-  private:
-    PluginsErrorDictionary  dictionary_;
-
-  public:
-    PluginsErrorDictionary& GetErrorDictionary()
-    {
-      return dictionary_;
-    }
   };
 }
 
--- a/Plugins/Engine/PluginsEnumerations.cpp	Wed Sep 23 22:05:27 2015 +0200
+++ b/Plugins/Engine/PluginsEnumerations.cpp	Thu Sep 24 15:55:17 2015 +0200
@@ -316,7 +316,7 @@
           return ErrorCode_DatabaseNotInitialized;
 
         default:
-          return ErrorCode_Plugin;
+          return ErrorCode_InternalError;
       }
     }
 
--- a/Plugins/Engine/PluginsErrorDictionary.cpp	Wed Sep 23 22:05:27 2015 +0200
+++ b/Plugins/Engine/PluginsErrorDictionary.cpp	Thu Sep 24 15:55:17 2015 +0200
@@ -38,6 +38,7 @@
 #endif
 
 
+
 #include "PluginsEnumerations.h"
 #include "PluginsManager.h"
 
@@ -61,17 +62,17 @@
   }
 
 
-  OrthancPluginErrorCode PluginsErrorDictionary::Register(SharedLibrary& library,
-                                                          int32_t pluginCode,
-                                                          const char* description,
-                                                          uint16_t httpStatus)
+  OrthancPluginErrorCode PluginsErrorDictionary::Register(const std::string& pluginName,
+                                                          int32_t  pluginCode,
+                                                          uint16_t httpStatus,
+                                                          const char* description)
   {
     std::auto_ptr<Error> error(new Error);
 
+    error->pluginName_ = pluginName;
     error->pluginCode_ = pluginCode;
     error->description_ = description;
     error->httpStatus_ = static_cast<HttpStatus>(httpStatus);
-    error->pluginName_ = PluginsManager::GetPluginName(library);
 
     OrthancPluginErrorCode code;
 
@@ -86,12 +87,10 @@
   }
 
 
-  void  PluginsErrorDictionary::GetExceptionMessage(Json::Value& message,  /* out */
-                                                    HttpStatus& httpStatus,  /* out */
-                                                    const OrthancException& exception)
+  bool  PluginsErrorDictionary::Format(Json::Value& message,  /* out */
+                                       HttpStatus& httpStatus,  /* out */
+                                       const OrthancException& exception)
   {
-    bool done = false;
-
     if (exception.GetErrorCode() >= ErrorCode_START_PLUGINS)
     {
       boost::mutex::scoped_lock lock(mutex_);
@@ -104,20 +103,10 @@
         message["PluginCode"] = error->second->pluginCode_;
         message["Message"] = error->second->description_;
 
-        done = true;
+        return true;
       }
     }
 
-    if (!done)
-    {
-      httpStatus = exception.GetHttpStatus();
-      message["Message"] = exception.What();
-    }
-
-    message["HttpError"] = EnumerationToString(httpStatus);
-    message["HttpStatus"] = httpStatus;
-    message["OrthancError"] = EnumerationToString(exception.GetErrorCode());
-    message["OrthancStatus"] = exception.GetErrorCode();
+    return false;
   }
-
 }
--- a/Plugins/Engine/PluginsErrorDictionary.h	Wed Sep 23 22:05:27 2015 +0200
+++ b/Plugins/Engine/PluginsErrorDictionary.h	Thu Sep 24 15:55:17 2015 +0200
@@ -36,7 +36,6 @@
 
 #include "../Include/orthanc/OrthancCPlugin.h"
 #include "../../Core/OrthancException.h"
-#include "SharedLibrary.h"
 
 #include <map>
 #include <string>
@@ -52,10 +51,10 @@
   private:
     struct Error
     {
+      std::string  pluginName_;
       int32_t      pluginCode_;
+      HttpStatus   httpStatus_;
       std::string  description_;
-      HttpStatus   httpStatus_;
-      std::string  pluginName_;
     };
     
     typedef std::map<int32_t, Error*>  Errors;
@@ -69,14 +68,14 @@
 
     ~PluginsErrorDictionary();
 
-    OrthancPluginErrorCode  Register(SharedLibrary& library,
+    OrthancPluginErrorCode  Register(const std::string& pluginName,
                                      int32_t  pluginCode,
-                                     const char* description,
-                                     uint16_t httpStatus);
+                                     uint16_t httpStatus,
+                                     const char* description);
 
-    void  GetExceptionMessage(Json::Value& message,  /* out */
-                              HttpStatus& httpStatus,  /* out */
-                              const OrthancException& exception);
+    bool  Format(Json::Value& message,  /* out */
+                 HttpStatus& httpStatus,  /* out */
+                 const OrthancException& exception);
   };
 }