changeset 913:3e43de893d88 plugins

POST, DELETE, PUT from Orthanc plugins
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 20 Jun 2014 15:42:14 +0200
parents dcb2469f00f4
children 7285b985626c
files Plugins/Engine/PluginsHttpHandler.cpp Plugins/Engine/PluginsHttpHandler.h Plugins/OrthancCPlugin/OrthancCPlugin.h Plugins/Samples/Basic/Plugin.c
diffstat 4 files changed, 201 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/Plugins/Engine/PluginsHttpHandler.cpp	Fri Jun 20 14:55:24 2014 +0200
+++ b/Plugins/Engine/PluginsHttpHandler.cpp	Fri Jun 20 15:42:14 2014 +0200
@@ -358,7 +358,7 @@
     StringHttpOutput stream;
     HttpOutput http(stream);
 
-    LOG(INFO) << "Plugin making REST call on URI " << p.uri;
+    LOG(INFO) << "Plugin making REST GET call on URI " << p.uri;
 
     if (pimpl_->restApi_ != NULL &&
         pimpl_->restApi_->Handle(http, HttpMethod_Get, uri, headers, getArguments, body))
@@ -374,40 +374,100 @@
   }
 
 
+  void PluginsHttpHandler::RestApiPostPut(bool isPost, const void* parameters)
+  {
+    const _OrthancPluginRestApiPostPut& p = 
+      *reinterpret_cast<const _OrthancPluginRestApiPostPut*>(parameters);
+
+    HttpHandler::Arguments headers;  // No HTTP header
+    HttpHandler::Arguments getArguments;  // No GET argument for POST/PUT
+
+    UriComponents uri;
+    Toolbox::SplitUriComponents(uri, p.uri);
+
+    // TODO Avoid unecessary memcpy
+    std::string body(p.body, p.bodySize);
+
+    StringHttpOutput stream;
+    HttpOutput http(stream);
+
+    HttpMethod method = (isPost ? HttpMethod_Post : HttpMethod_Put);
+    LOG(INFO) << "Plugin making REST " << EnumerationToString(method) << " call on URI " << p.uri;
+
+    if (pimpl_->restApi_ != NULL &&
+        pimpl_->restApi_->Handle(http, method, uri, headers, getArguments, body))
+    {
+      std::string result;
+      stream.GetOutput(result);
+      CopyToMemoryBuffer(*p.target, result);
+    }
+    else
+    {
+      throw OrthancException(ErrorCode_BadRequest);
+    }
+  }
+
+
+  void PluginsHttpHandler::RestApiDelete(const void* parameters)
+  {
+    // The "parameters" point to the URI
+    UriComponents uri;
+    Toolbox::SplitUriComponents(uri, reinterpret_cast<const char*>(parameters));
+
+    HttpHandler::Arguments headers;  // No HTTP header
+    HttpHandler::Arguments getArguments;  // No GET argument for POST/PUT
+    std::string body;  // No body for DELETE
+
+    StringHttpOutput stream;
+    HttpOutput http(stream);
+
+    LOG(INFO) << "Plugin making REST DELETE call on URI " 
+              << reinterpret_cast<const char*>(parameters);
+
+    if (pimpl_->restApi_ == NULL ||
+        !pimpl_->restApi_->Handle(http, HttpMethod_Delete, uri, headers, getArguments, body))
+    {
+      throw OrthancException(ErrorCode_BadRequest);
+    }
+  }
+
+
   bool PluginsHttpHandler::InvokeService(_OrthancPluginService service,
                                          const void* parameters)
   {
     switch (service)
     {
       case _OrthancPluginService_RegisterRestCallback:
-      {
         RegisterRestCallback(parameters);
         return true;
-      }
 
       case _OrthancPluginService_AnswerBuffer:
-      {
         AnswerBuffer(parameters);
         return true;
-      }
 
       case _OrthancPluginService_CompressAndAnswerPngImage:
-      {
         CompressAndAnswerPngImage(parameters);
         return true;
-      }
 
       case _OrthancPluginService_GetDicomForInstance:
-      {
         GetDicomForInstance(parameters);
         return true;
-      }
 
       case _OrthancPluginService_RestApiGet:
-      {
         RestApiGet(parameters);
         return true;
-      }
+
+      case _OrthancPluginService_RestApiPost:
+        RestApiPostPut(true, parameters);
+        return true;
+
+      case _OrthancPluginService_RestApiDelete:
+        RestApiDelete(parameters);
+        return true;
+
+      case _OrthancPluginService_RestApiPut:
+        RestApiPostPut(false, parameters);
+        return true;
 
       default:
         return false;
--- a/Plugins/Engine/PluginsHttpHandler.h	Fri Jun 20 14:55:24 2014 +0200
+++ b/Plugins/Engine/PluginsHttpHandler.h	Fri Jun 20 15:42:14 2014 +0200
@@ -60,6 +60,10 @@
 
     void RestApiGet(const void* parameters);
 
+    void RestApiPostPut(bool isPost, const void* parameters);
+
+    void RestApiDelete(const void* parameters);
+
   public:
     PluginsHttpHandler(ServerContext& context);
 
--- a/Plugins/OrthancCPlugin/OrthancCPlugin.h	Fri Jun 20 14:55:24 2014 +0200
+++ b/Plugins/OrthancCPlugin/OrthancCPlugin.h	Fri Jun 20 15:42:14 2014 +0200
@@ -404,13 +404,13 @@
   }
 
 
+
   typedef struct
   {
     const char* pathRegularExpression;
     OrthancPluginRestCallback callback;
   } _OrthancPluginRestCallback;
 
-
   /**
    * @brief Register a REST callback.
    *
@@ -435,6 +435,7 @@
   }
 
 
+
   typedef struct
   {
     OrthancPluginRestOutput* output;
@@ -443,7 +444,6 @@
     const char*              mimeType;
   } _OrthancPluginAnswerBuffer;
 
-
   /**
    * @brief Answer to a REST request.
    *
@@ -518,13 +518,13 @@
   }
 
 
+
   typedef struct
   {
     OrthancPluginMemoryBuffer*  target;
     const char*                 instanceId;
   } _OrthancPluginGetDicomForInstance;
 
-
   /**
    * @brief Retrieve a DICOM instance using its Orthanc identifier.
    * 
@@ -555,6 +555,17 @@
     const char*                 uri;
   } _OrthancPluginRestApiGet;
 
+  /**
+   * @brief Make a GET call to the built-in Orthanc REST API.
+   * 
+   * Make a GET call to the built-in Orthanc REST API. The result to
+   * the query is stored into a newly allocated memory buffer.
+   * 
+   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
+   * @param target The target memory buffer.
+   * @param uri The URI in the built-in Orthanc API.
+   * @return 0 if success, other value if error.
+   **/
   ORTHANC_PLUGIN_INLINE int  OrthancPluginRestApiGet(
     OrthancPluginContext*       context,
     OrthancPluginMemoryBuffer*  target,
@@ -567,6 +578,92 @@
   }
 
 
+
+  typedef struct
+  {
+    OrthancPluginMemoryBuffer*  target;
+    const char*                 uri;
+    const char*                 body;
+    uint32_t                    bodySize;
+  } _OrthancPluginRestApiPostPut;
+
+  /**
+   * @brief Make a POST call to the built-in Orthanc REST API.
+   * 
+   * Make a POST call to the built-in Orthanc REST API. The result to
+   * the query is stored into a newly allocated memory buffer.
+   * 
+   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
+   * @param target The target memory buffer.
+   * @param uri The URI in the built-in Orthanc API.
+   * @param body The body of the POST request.
+   * @param bodySize The size of the body.
+   * @return 0 if success, other value if error.
+   **/
+  ORTHANC_PLUGIN_INLINE int  OrthancPluginRestApiPost(
+    OrthancPluginContext*       context,
+    OrthancPluginMemoryBuffer*  target,
+    const char*                 uri,
+    const char*                 body,
+    uint32_t                    bodySize)
+  {
+    _OrthancPluginRestApiPostPut params;
+    params.target = target;
+    params.uri = uri;
+    params.body = body;
+    params.bodySize = bodySize;
+    return context->InvokeService(context, _OrthancPluginService_RestApiPost, &params);
+  }
+
+
+
+  /**
+   * @brief Make a DELETE call to the built-in Orthanc REST API.
+   * 
+   * Make a DELETE call to the built-in Orthanc REST API.
+   * 
+   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
+   * @param uri The URI to delete in the built-in Orthanc API.
+   * @return 0 if success, other value if error.
+   **/
+  ORTHANC_PLUGIN_INLINE int  OrthancPluginRestApiDelete(
+    OrthancPluginContext*       context,
+    const char*                 uri)
+  {
+    return context->InvokeService(context, _OrthancPluginService_RestApiDelete, uri);
+  }
+
+
+
+  /**
+   * @brief Make a PUT call to the built-in Orthanc REST API.
+   * 
+   * Make a PUT call to the built-in Orthanc REST API. The result to
+   * the query is stored into a newly allocated memory buffer.
+   * 
+   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
+   * @param target The target memory buffer.
+   * @param uri The URI in the built-in Orthanc API.
+   * @param body The body of the PUT request.
+   * @param bodySize The size of the body.
+   * @return 0 if success, other value if error.
+   **/
+  ORTHANC_PLUGIN_INLINE int  OrthancPluginRestApiPut(
+    OrthancPluginContext*       context,
+    OrthancPluginMemoryBuffer*  target,
+    const char*                 uri,
+    const char*                 body,
+    uint32_t                    bodySize)
+  {
+    _OrthancPluginRestApiPostPut params;
+    params.target = target;
+    params.uri = uri;
+    params.body = body;
+    params.bodySize = bodySize;
+    return context->InvokeService(context, _OrthancPluginService_RestApiPut, &params);
+  }
+
+
 #ifdef  __cplusplus
 }
 #endif
--- a/Plugins/Samples/Basic/Plugin.c	Fri Jun 20 14:55:24 2014 +0200
+++ b/Plugins/Samples/Basic/Plugin.c	Fri Jun 20 15:42:14 2014 +0200
@@ -129,8 +129,10 @@
 
 ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* c)
 {
+  const char* pathLocator = "\"Path\" : \"";
   OrthancPluginMemoryBuffer tmp;
   char info[1024];
+  char *id, *eos;
 
   context = c;
   OrthancPluginLogWarning(context, "Sample plugin is initializing");
@@ -144,10 +146,31 @@
 
   OrthancPluginRegisterRestCallback(context, "/instances/([^/]+)/preview", Callback4);
 
-  
-  printf(">> %d\n", OrthancPluginRestApiGet(context, &tmp, "/instances"));
-  printf(">> [%s]\n", (const char*) tmp.data);
+  /* Make REST requests to the built-in Orthanc API */
+  OrthancPluginRestApiGet(context, &tmp, "/changes");
+  OrthancPluginFreeMemoryBuffer(context, &tmp);
+  OrthancPluginRestApiGet(context, &tmp, "/changes?limit=1");
   OrthancPluginFreeMemoryBuffer(context, &tmp);
+ 
+  /* Make POST request to create a new DICOM instance */
+  sprintf(info, "{\"PatientName\":\"Test\"}");
+  OrthancPluginRestApiPost(context, &tmp, "/tools/create-dicom", info, strlen(info));
+
+  /**
+   * Recover he ID of the created instance is constructed by a
+   * quick-and-dirty parsing of a JSON string.
+   **/
+  id = strstr((char*) tmp.data, pathLocator) + strlen(pathLocator);
+  eos = strchr(id, '\"');
+  eos[0] = '\0';
+
+  /* Delete the newly created DICOM instance. */
+  OrthancPluginRestApiDelete(context, id);
+  OrthancPluginFreeMemoryBuffer(context, &tmp);
+
+  /* Play with PUT by defining a new target modality. */
+  sprintf(info, "[ \"STORESCP\", \"localhost\", 2000 ]");
+  OrthancPluginRestApiPut(context, &tmp, "/modalities/demo", info, strlen(info));
 
   return 0;
 }