changeset 416:1188cb0ddaa5

http method faking
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 06 May 2013 16:32:27 +0200
parents d558fa565c42
children 7441037663cd
files CMakeLists.txt Core/HttpServer/MongooseServer.cpp Core/RestApi/RestApi.cpp NEWS OrthancCppClient/HttpEnumerations.cpp OrthancCppClient/HttpEnumerations.h
diffstat 6 files changed, 96 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Mon May 06 13:51:59 2013 +0200
+++ b/CMakeLists.txt	Mon May 06 16:32:27 2013 +0200
@@ -150,6 +150,7 @@
   Core/Lua/LuaFunctionCall.cpp
 
   OrthancCppClient/HttpClient.cpp
+  OrthancCppClient/HttpEnumerations.cpp
   OrthancCppClient/HttpException.cpp
   )  
 
--- a/Core/HttpServer/MongooseServer.cpp	Mon May 06 13:51:59 2013 +0200
+++ b/Core/HttpServer/MongooseServer.cpp	Mon May 06 16:32:27 2013 +0200
@@ -268,9 +268,9 @@
 
 
 
-  static PostDataStatus ReadPostData(std::string& postData,
-                                     struct mg_connection *connection,
-                                     const HttpHandler::Arguments& headers)
+  static PostDataStatus ReadBody(std::string& postData,
+                                 struct mg_connection *connection,
+                                 const HttpHandler::Arguments& headers)
   {
     HttpHandler::Arguments::const_iterator cs = headers.find("content-length");
     if (cs == headers.end())
@@ -322,7 +322,7 @@
     std::string boundary = "--" + contentType.substr(multipartLength);
 
     std::string postData;
-    PostDataStatus status = ReadPostData(postData, connection, headers);
+    PostDataStatus status = ReadBody(postData, connection, headers);
 
     if (status != PostDataStatus_Success)
     {
@@ -518,13 +518,17 @@
       // A faking has been done within this request
       Toolbox::ToUpperCase(overriden);
 
+      LOG(INFO) << "HTTP method faking has been detected for " << overriden;
+
       if (overriden == "PUT")
       {
         method = Orthanc_HttpMethod_Put;
+        return true;
       }
       else if (overriden == "DELETE")
       {
         method = Orthanc_HttpMethod_Delete;
+        return true;
       }
       else
       {
@@ -568,7 +572,6 @@
       MongooseServer* that = (MongooseServer*) (request->user_data);
       MongooseOutput output(connection);
 
-
       // Check remote calls
       if (!that->IsRemoteAccessAllowed() &&
           request->remote_ip != LOCALHOST)
@@ -600,7 +603,7 @@
       Orthanc_HttpMethod method;
       if (!ExtractMethod(method, request, headers, argumentsGET))
       {
-        output.SendHeader(Orthanc_HttpStatus_405_MethodNotAllowed);
+        output.SendHeader(Orthanc_HttpStatus_400_BadRequest);
         return (void*) "";
       }
 
@@ -639,42 +642,44 @@
       if (method == Orthanc_HttpMethod_Post ||
           method == Orthanc_HttpMethod_Put)
       {
+        PostDataStatus status;
+
         HttpHandler::Arguments::const_iterator ct = headers.find("content-type");
         if (ct == headers.end())
         {
-          output.SendHeader(Orthanc_HttpStatus_400_BadRequest);
-          return (void*) "";
-        }
-
-        PostDataStatus status;
-      
-        std::string contentType = ct->second;
-        if (contentType.size() >= multipartLength &&
-            !memcmp(contentType.c_str(), multipart, multipartLength))
-        {
-          status = ParseMultipartPost(body, connection, headers, contentType, that->GetChunkStore());
+          // No content-type specified. Assume no multi-part content occurs at this point.
+          status = ReadBody(body, connection, headers);          
         }
         else
         {
-          status = ReadPostData(body, connection, headers);
+          std::string contentType = ct->second;
+          if (contentType.size() >= multipartLength &&
+              !memcmp(contentType.c_str(), multipart, multipartLength))
+          {
+            status = ParseMultipartPost(body, connection, headers, contentType, that->GetChunkStore());
+          }
+          else
+          {
+            status = ReadBody(body, connection, headers);
+          }
         }
 
         switch (status)
         {
-        case PostDataStatus_NoLength:
-          output.SendHeader(Orthanc_HttpStatus_411_LengthRequired);
-          return (void*) "";
+          case PostDataStatus_NoLength:
+            output.SendHeader(Orthanc_HttpStatus_411_LengthRequired);
+            return (void*) "";
 
-        case PostDataStatus_Failure:
-          output.SendHeader(Orthanc_HttpStatus_400_BadRequest);
-          return (void*) "";
+          case PostDataStatus_Failure:
+            output.SendHeader(Orthanc_HttpStatus_400_BadRequest);
+            return (void*) "";
 
-        case PostDataStatus_Pending:
-          output.AnswerBufferWithContentType(NULL, 0, "");
-          return (void*) "";
+          case PostDataStatus_Pending:
+            output.AnswerBufferWithContentType(NULL, 0, "");
+            return (void*) "";
 
-        default:
-          break;
+          default:
+            break;
         }
       }
 
@@ -697,6 +702,7 @@
       {
         try
         {
+          LOG(INFO) << Orthanc_HttpMethod_ToString(method) << " " << Toolbox::FlattenUri(uri);
           handler->Handle(output, method, uri, headers, argumentsGET, body);
         }
         catch (OrthancException& e)
--- a/Core/RestApi/RestApi.cpp	Mon May 06 13:51:59 2013 +0200
+++ b/Core/RestApi/RestApi.cpp	Mon May 06 16:32:27 2013 +0200
@@ -198,7 +198,7 @@
       {
         if (it->first->Match(components, trailing, uri))
         {
-          LOG(INFO) << "REST GET call on: " << Toolbox::FlattenUri(uri);
+          //LOG(INFO) << "REST GET call on: " << Toolbox::FlattenUri(uri);
           ok = true;
           GetCall call;
           call.output_ = &restOutput;
@@ -220,7 +220,7 @@
       {
         if (it->first->Match(components, trailing, uri))
         {
-          LOG(INFO) << "REST PUT call on: " << Toolbox::FlattenUri(uri);
+          //LOG(INFO) << "REST PUT call on: " << Toolbox::FlattenUri(uri);
           ok = true;
           PutCall call;
           call.output_ = &restOutput;
@@ -242,7 +242,7 @@
       {
         if (it->first->Match(components, trailing, uri))
         {
-          LOG(INFO) << "REST POST call on: " << Toolbox::FlattenUri(uri);
+          //LOG(INFO) << "REST POST call on: " << Toolbox::FlattenUri(uri);
           ok = true;
           PostCall call;
           call.output_ = &restOutput;
@@ -264,7 +264,7 @@
       {
         if (it->first->Match(components, trailing, uri))
         {
-          LOG(INFO) << "REST DELETE call on: " << Toolbox::FlattenUri(uri);
+          //LOG(INFO) << "REST DELETE call on: " << Toolbox::FlattenUri(uri);
           ok = true;
           DeleteCall call;
           call.output_ = &restOutput;
@@ -280,7 +280,8 @@
 
     if (!ok)
     {
-      LOG(INFO) << "REST method " << method << " not allowed on: " << Toolbox::FlattenUri(uri);
+      LOG(INFO) << "REST method " << Orthanc_HttpMethod_ToString(method) 
+                << " not allowed on: " << Toolbox::FlattenUri(uri);
       output.SendMethodNotAllowedError(GetAcceptedMethods(uri));
     }
   }
--- a/NEWS	Mon May 06 13:51:59 2013 +0200
+++ b/NEWS	Mon May 06 16:32:27 2013 +0200
@@ -9,6 +9,7 @@
 * Filtering of incoming HTTP requests (through Lua scripting)
 * Clearing of "/exports" and "/changes"
 * Check MD5 of third party downloads
+* Faking of the HTTP methods PUT and DELETE
 
 
 Version 0.5.1 (2013/04/17)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OrthancCppClient/HttpEnumerations.cpp	Mon May 06 16:32:27 2013 +0200
@@ -0,0 +1,50 @@
+/**
+ * Orthanc - A Lightweight, RESTful DICOM Store
+ * Copyright (C) 2012-2013 Medical Physics Department, CHU of Liege,
+ * Belgium
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ **/
+
+
+#include "HttpEnumerations.h"
+
+const char* Orthanc_HttpMethod_ToString(Orthanc_HttpMethod method)
+{
+  switch (method)
+  {
+    case Orthanc_HttpMethod_Get:
+      return "GET";
+
+    case Orthanc_HttpMethod_Post:
+      return "POST";
+
+    case Orthanc_HttpMethod_Delete:
+      return "DELETE";
+
+    case Orthanc_HttpMethod_Put:
+      return "PUT";
+
+    default:
+      return "?";
+  }
+}
+
--- a/OrthancCppClient/HttpEnumerations.h	Mon May 06 13:51:59 2013 +0200
+++ b/OrthancCppClient/HttpEnumerations.h	Mon May 06 16:32:27 2013 +0200
@@ -111,3 +111,6 @@
   Orthanc_HttpMethod_Delete = 2,
   Orthanc_HttpMethod_Put = 3
 };
+
+
+const char* Orthanc_HttpMethod_ToString(Orthanc_HttpMethod method);