[mapguide-commits] r9688 - sandbox/jng/ogc_viewer_representation/Web/src/DevHttpServer

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Tue Jul 28 05:12:15 PDT 2020


Author: jng
Date: 2020-07-28 05:12:15 -0700 (Tue, 28 Jul 2020)
New Revision: 9688

Modified:
   sandbox/jng/ogc_viewer_representation/Web/src/DevHttpServer/main.cpp
Log:
When using MgDevHttpServer with Maestro, it blows up running certain operations. Further analysis shows that our POST handler needed to be able to take and process a content reader if given one, otherwise the routing engine treats this as no handler being matched and returns HTTP 400 back to the client.

Modified: sandbox/jng/ogc_viewer_representation/Web/src/DevHttpServer/main.cpp
===================================================================
--- sandbox/jng/ogc_viewer_representation/Web/src/DevHttpServer/main.cpp	2020-07-28 10:39:16 UTC (rev 9687)
+++ sandbox/jng/ogc_viewer_representation/Web/src/DevHttpServer/main.cpp	2020-07-28 12:12:15 UTC (rev 9688)
@@ -28,10 +28,11 @@
 #include <malloc.h>
 #endif
 
-#include "MapAgentCommon.h"
 #include "MapGuideCommon.h"
 #include "HttpHandler.h"
 #include "WebSupport.h"
+#include "MapAgentCommon.h"
+#include "MapAgentStrings.h"
 #include "Base64.h"
 
 int port = 8000;
@@ -162,35 +163,104 @@
     }
 }
 
-void PopulatePostRequest(MgHttpRequestParam* param, const httplib::Request& req)
+bool StrEndsWith(std::string const& fullString, std::string const& ending)
 {
-    for (const auto& p : req.params)
+    if (fullString.length() >= ending.length())
     {
-        STRING key = MgUtil::MultiByteToWideChar(p.first);
-        STRING value = MgUtil::MultiByteToWideChar(p.second);
-        param->AddParameter(key, value);
+        return (0 == fullString.compare(fullString.length() - ending.length(), ending.length(), ending));
     }
+    else
+    {
+        return false;
+    }
+}
 
-    for (const auto& f : req.files)
+void PopulatePostRequest(MgHttpRequestParam* param, const httplib::Request& req, const httplib::ContentReader* contentReader = nullptr)
+{
+    if (contentReader != nullptr)
     {
-        STRING key = MgUtil::MultiByteToWideChar(f.first);
-        auto file = f.second;
-        if (file.filename.empty())
+        if (req.is_multipart_form_data())
         {
-            STRING value = MgUtil::MultiByteToWideChar(file.content);
-            param->AddParameter(key, value);
+            httplib::MultipartFormDataItems files;
+            (*contentReader)(
+                [&](const httplib::MultipartFormData& file) {
+                    files.push_back(file);
+                    return true;
+                },
+                [&](const char* data, size_t data_length) {
+                    files.back().content.append(data, data_length);
+                    return true;
+                });
+            for (const auto& f : files)
+            {
+                STRING key;
+                if (StrEndsWith(f.name, "\";"))
+                {
+                    key = MgUtil::MultiByteToWideChar(f.name.substr(0, f.name.length() - 2));
+                }
+                else
+                {
+                    key = MgUtil::MultiByteToWideChar(f.name);
+                }
+                if (f.filename.empty())
+                {
+                    STRING value = MgUtil::MultiByteToWideChar(f.content);
+                    param->AddParameter(key, value);
+                }
+                else
+                {
+                    STRING fileName = MgFileUtil::GenerateTempFileName();
+                    Ptr<MgByteSource> byteSource = new MgByteSource((BYTE_ARRAY_IN)f.content.c_str(), (INT32)f.content.length());
+                    Ptr<MgByteReader> reader = byteSource->GetReader();
+                    Ptr<MgByteSink> sink = new MgByteSink(reader);
+                    sink->ToFile(fileName);
+
+                    param->AddParameter(key, fileName);
+                    //tempfile is a hint to the MgHttpRequest for it to create a MgByteSource from it
+                    param->SetParameterType(key, MapAgentStrings::TempfileKey);
+                }
+            }
         }
         else
         {
-            STRING fileName = MgFileUtil::GenerateTempFileName();
-            Ptr<MgByteSource> byteSource = new MgByteSource((BYTE_ARRAY_IN)file.content.c_str(), (INT32)file.content.length());
-            Ptr<MgByteReader> reader = byteSource->GetReader();
-            Ptr<MgByteSink> sink = new MgByteSink(reader);
-            sink->ToFile(fileName);
+            std::string body;
+            (*contentReader)([&](const char* data, size_t data_length) {
+                body.append(data, data_length);
+                return true;
+                });
+            param->SetXmlPostData(body.c_str());
+        }
+    }
+    else
+    {
+        for (const auto& p : req.params)
+        {
+            STRING key = MgUtil::MultiByteToWideChar(p.first);
+            STRING value = MgUtil::MultiByteToWideChar(p.second);
+            param->AddParameter(key, value);
+        }
 
-            param->AddParameter(key, fileName);
-            //tempfile is a hint to the MgHttpRequest for it to create a MgByteSource from it
-            param->SetParameterType(key, L"tempfile");
+        for (const auto& f : req.files)
+        {
+            STRING key = MgUtil::MultiByteToWideChar(f.first);
+            auto file = f.second;
+            if (file.filename.empty())
+            {
+                STRING value = MgUtil::MultiByteToWideChar(file.content);
+                param->AddParameter(key, value);
+            }
+            else
+            {
+                STRING fileName = MgFileUtil::GenerateTempFileName();
+                Ptr<MgByteSource> byteSource = new MgByteSource((BYTE_ARRAY_IN)file.content.c_str(), (INT32)file.content.length());
+                Ptr<MgByteReader> reader = byteSource->GetReader();
+                Ptr<MgByteSink> sink = new MgByteSink(reader);
+                sink->ToFile(fileName);
+
+                param->AddParameter(key, fileName);
+                //tempfile is a hint to the MgHttpRequest for it to create a MgByteSource from it
+                param->SetParameterType(key, MapAgentStrings::TempfileKey);
+            }
         }
     }
 }
@@ -272,7 +342,7 @@
     return result->GetStatusCode();
 }
 
-void MapAgentHandler(const httplib::Request& req, httplib::Response& res)
+void MapAgentHandlerInternal(const httplib::Request& req, httplib::Response& res, const httplib::ContentReader* contentReader = nullptr)
 {
     std::string logStr;
     bool bLoggedStatus = false;
@@ -314,7 +384,7 @@
     }
     else if (isPost)
     {
-        PopulatePostRequest(param, req);
+        PopulatePostRequest(param, req, contentReader);
     }
 
     //Extract any parameters from the http authentication header if there is one
@@ -369,6 +439,16 @@
     printf("%s\n", logStr.c_str());
 }
 
+void MapAgentHandlerWithContentReader(const httplib::Request& req, httplib::Response& res, const httplib::ContentReader& content_reader)
+{
+    MapAgentHandlerInternal(req, res, &content_reader);
+}
+
+void MapAgentHandlerWithoutContentReader(const httplib::Request& req, httplib::Response& res)
+{
+    MapAgentHandlerInternal(req, res);
+}
+
 int main(int argc, char** argv)
 {
 #ifdef _WIN32
@@ -404,8 +484,9 @@
 
     g_server->set_mount_point("/mapguide", "./wwwroot");
 
-    g_server->Post("/mapguide/mapagent/mapagent.fcgi", MapAgentHandler);
-    g_server->Get("/mapguide/mapagent/mapagent.fcgi", MapAgentHandler);
+    g_server->Post("/mapguide/mapagent/mapagent.fcgi", MapAgentHandlerWithContentReader);
+    g_server->Post("/mapguide/mapagent/mapagent.fcgi", MapAgentHandlerWithoutContentReader);
+    g_server->Get("/mapguide/mapagent/mapagent.fcgi", MapAgentHandlerWithoutContentReader);
 
     printf("Listening on port %d\n", port);
 



More information about the mapguide-commits mailing list