comparison Plugins/Samples/Common/OrthancPluginCppWrapper.cpp @ 3414:b9cba6a91780

simplification
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 11 Jun 2019 19:44:10 +0200
parents f09bfdea3fc3
children 541c787e2230
comparison
equal deleted inserted replaced
3413:f09bfdea3fc3 3414:b9cba6a91780
31 **/ 31 **/
32 32
33 33
34 #include "OrthancPluginCppWrapper.h" 34 #include "OrthancPluginCppWrapper.h"
35 35
36 #if HAS_ORTHANC_PLUGIN_HTTP_MULTIPART_SERVER == 0
37 # if ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 5, 7)
38 # define HAS_ORTHANC_FRAMEWORK_MULTIPART_READER 1
39 # include "../../../Core/HttpServer/MultipartStreamReader.h"
40 # include <boost/thread/shared_mutex.hpp>
41 # else
42 # define HAS_ORTHANC_FRAMEWORK_MULTIPART_READER 0
43 # endif
44 #endif
45
46
47 #include <boost/algorithm/string/predicate.hpp> 36 #include <boost/algorithm/string/predicate.hpp>
48 #include <json/reader.h> 37 #include <json/reader.h>
49 #include <json/writer.h> 38 #include <json/writer.h>
50 39
51 40
2613 } 2602 }
2614 #endif 2603 #endif
2615 } 2604 }
2616 2605
2617 #endif /* HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1 */ 2606 #endif /* HAS_ORTHANC_PLUGIN_HTTP_CLIENT == 1 */
2618
2619
2620
2621
2622
2623 /******************************************************************
2624 ** MULTIPART REST SERVER
2625 ******************************************************************/
2626
2627 #if HAS_ORTHANC_PLUGIN_HTTP_MULTIPART_SERVER == 1
2628 static OrthancPluginMultipartRestHandler* MultipartRestFactory(
2629 OrthancPluginMultipartRestFactory* factory,
2630 OrthancPluginErrorCode* errorCode,
2631 OrthancPluginHttpMethod method,
2632 const char* url,
2633 const char* contentType,
2634 const char* subType,
2635 uint32_t groupsCount,
2636 const char* const* groups,
2637 uint32_t headersCount,
2638 const char* const* headersKeys,
2639 const char* const* headersValues)
2640 {
2641 *errorCode = OrthancPluginErrorCode_Success;
2642
2643 try
2644 {
2645 assert(factory != NULL);
2646 MultipartRestCallback& that = *reinterpret_cast<MultipartRestCallback*>(factory);
2647
2648 std::vector<std::string> g;
2649 g.resize(groupsCount);
2650
2651 for (uint32_t i = 0; i < groupsCount; i++)
2652 {
2653 g[i] = groups[i];
2654 }
2655
2656 std::map<std::string, std::string> headers;
2657 for (uint32_t i = 0; i < headersCount; i++)
2658 {
2659 headers[headersKeys[i]] = headersValues[i];
2660 }
2661
2662 return reinterpret_cast<OrthancPluginMultipartRestHandler*>(
2663 that.CreateHandler(method, url, contentType,
2664 subType == NULL ? "" : subType, g, headers));
2665 }
2666 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
2667 {
2668 LogError("Exception while creating a multipart handler");
2669 *errorCode = static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
2670 return NULL;
2671 }
2672 catch (...)
2673 {
2674 LogError("Native exception while creating a multipart handler");
2675 *errorCode = OrthancPluginErrorCode_Plugin;
2676 return NULL;
2677 }
2678 }
2679
2680 static OrthancPluginErrorCode MultipartRestAddPart(
2681 OrthancPluginMultipartRestHandler* handler,
2682 const char* contentType,
2683 uint32_t headersCount,
2684 const char* const* headersKeys,
2685 const char* const* headersValues,
2686 const void* data,
2687 uint32_t size)
2688 {
2689 try
2690 {
2691 assert(handler != NULL);
2692 std::map<std::string, std::string> headers;
2693 for (uint32_t i = 0; i < headersCount; i++)
2694 {
2695 headers[headersKeys[i]] = headersValues[i];
2696 }
2697
2698 return reinterpret_cast<MultipartRestCallback::IHandler*>(handler)->
2699 AddPart(contentType, headers, data, size);
2700 }
2701 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
2702 {
2703 LogError("Exception while adding a part to a multipart handler");
2704 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
2705 }
2706 catch (...)
2707 {
2708 LogError("Native exception while adding a part to a multipart handler");
2709 return OrthancPluginErrorCode_Plugin;
2710 }
2711 }
2712
2713 static OrthancPluginErrorCode MultipartRestExecute(
2714 OrthancPluginMultipartRestHandler* handler,
2715 OrthancPluginRestOutput* output)
2716 {
2717 try
2718 {
2719 assert(handler != NULL);
2720 return reinterpret_cast<MultipartRestCallback::IHandler*>(handler)->Execute(output);
2721 }
2722 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
2723 {
2724 LogError("Exception while executing a multipart handler");
2725 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode());
2726 }
2727 catch (...)
2728 {
2729 LogError("Native exception while executing a multipart handler");
2730 return OrthancPluginErrorCode_Plugin;
2731 }
2732 }
2733
2734 static void MultipartRestFinalize(OrthancPluginMultipartRestHandler* handler)
2735 {
2736 try
2737 {
2738 assert(handler != NULL);
2739 delete reinterpret_cast<MultipartRestCallback::IHandler*>(handler);
2740 }
2741 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e)
2742 {
2743 LogError("Exception while finalizing a multipart handler");
2744 }
2745 catch (...)
2746 {
2747 LogError("Native exception while finalizing a multipart handler");
2748 }
2749 }
2750
2751 void MultipartRestCallback::Register(const std::string& regularExpression)
2752 {
2753 OrthancPluginRegisterMultipartRestCallback(
2754 GetGlobalContext(), regularExpression.c_str(),
2755 reinterpret_cast<OrthancPluginMultipartRestFactory*>(this),
2756 MultipartRestFactory, MultipartRestAddPart, MultipartRestExecute, MultipartRestFinalize);
2757 }
2758
2759 #elif HAS_ORTHANC_FRAMEWORK_MULTIPART_READER == 1
2760
2761 namespace
2762 {
2763 class CompatibilityPartHandler : public Orthanc::MultipartStreamReader::IHandler
2764 {
2765 private:
2766 MultipartRestCallback::IHandler& handler_;
2767
2768 public:
2769 CompatibilityPartHandler(MultipartRestCallback::IHandler& handler) :
2770 handler_(handler)
2771 {
2772 }
2773
2774 virtual void HandlePart(const Orthanc::MultipartStreamReader::HttpHeaders& headers,
2775 const void* part,
2776 size_t size)
2777 {
2778 std::string contentType;
2779 if (!Orthanc::MultipartStreamReader::GetMainContentType(contentType, headers))
2780 {
2781 contentType.clear();
2782 }
2783
2784 OrthancPluginErrorCode code = handler_.AddPart(contentType, headers, part, size);
2785
2786 if (code != OrthancPluginErrorCode_Success)
2787 {
2788 ORTHANC_PLUGINS_THROW_PLUGIN_ERROR_CODE(code);
2789 }
2790 }
2791 };
2792 }
2793
2794 static boost::shared_mutex compatibilityMultipartMutex_;
2795 static std::set<MultipartRestCallback*> compatibilityMultipartCallbacks_;
2796
2797
2798 namespace
2799 {
2800 void CompatibilityMultipartRestCallback(OrthancPluginRestOutput* output,
2801 const char* url,
2802 const OrthancPluginHttpRequest* request)
2803 {
2804 std::map<std::string, std::string> headers;
2805 for (uint32_t i = 0; i < request->headersCount; i++)
2806 {
2807 headers[request->headersKeys[i]] = request->headersValues[i];
2808 }
2809
2810 std::string mainContentType;
2811 if (!Orthanc::MultipartStreamReader::GetMainContentType(mainContentType, headers))
2812 {
2813 LogError("Missing Content-Type HTTP header, prevents streaming the body");
2814 ORTHANC_PLUGINS_THROW_EXCEPTION(UnsupportedMediaType);
2815 }
2816
2817 std::string contentType, subType, boundary;
2818 if (!Orthanc::MultipartStreamReader::ParseMultipartContentType
2819 (contentType, subType, boundary, mainContentType))
2820 {
2821 LogError("Invalid Content-Type HTTP header, prevents streaming the body: \"" +
2822 mainContentType + "\"");
2823 ORTHANC_PLUGINS_THROW_EXCEPTION(UnsupportedMediaType);
2824 }
2825
2826 std::vector<std::string> groups;
2827 groups.reserve(request->groupsCount);
2828 for (uint32_t i = 0; i < request->groupsCount; i++)
2829 {
2830 groups[i] = request->groups[i];
2831 }
2832
2833 std::auto_ptr<MultipartRestCallback::IHandler> handler;
2834
2835 {
2836 boost::shared_lock<boost::shared_mutex> lock(compatibilityMultipartMutex_);
2837
2838 for (std::set<MultipartRestCallback*>::const_iterator
2839 it = compatibilityMultipartCallbacks_.begin();
2840 it != compatibilityMultipartCallbacks_.end(); ++it)
2841 {
2842 assert(*it != NULL);
2843 handler.reset((*it)->CreateHandler(request->method, url, contentType, subType, groups, headers));
2844 if (handler.get() != NULL)
2845 {
2846 break;
2847 }
2848 }
2849 }
2850
2851 if (handler.get() != NULL)
2852 {
2853 {
2854 CompatibilityPartHandler wrapper(*handler);
2855 Orthanc::MultipartStreamReader reader(boundary);
2856 reader.SetHandler(wrapper);
2857 reader.AddChunk(request->body, request->bodySize);
2858 reader.CloseStream();
2859 }
2860
2861 handler->Execute(output);
2862 }
2863 }
2864 }
2865
2866 void MultipartRestCallback::Register(const std::string& regularExpression)
2867 {
2868 LogWarning("Performance warning: The plugin was compiled against a pre-1.5.7 version "
2869 "of the Orthanc SDK. Multipart transfers will be entirely stored in RAM.");
2870
2871 {
2872 boost::unique_lock<boost::shared_mutex> lock(compatibilityMultipartMutex_);
2873 compatibilityMultipartCallbacks_.insert(this);
2874 }
2875
2876 OrthancPluginRegisterRestCallback(GetGlobalContext(), regularExpression.c_str(),
2877 Internals::Protect<CompatibilityMultipartRestCallback>);
2878 }
2879
2880 #else
2881
2882 void MultipartRestCallback::Register(const std::string& regularExpression)
2883 {
2884 /**
2885 * Version >= 1.5.7 of the Orthanc framework must be
2886 * available. Make sure that macros "HAS_ORTHANC_FRAMEWORK=1",
2887 * "ORTHANC_FRAMEWORK_VERSION_MAJOR",
2888 * "ORTHANC_FRAMEWORK_VERSION_MINOR" and
2889 * "ORTHANC_FRAMEWORK_VERSION_REVISION" are properly set.
2890 **/
2891 LogError("The compatibility wrappers for multipart transfers is not available, stopping now.");
2892 ORTHANC_PLUGINS_THROW_EXCEPTION(NotImplemented);
2893 }
2894
2895 #endif
2896
2897 } 2607 }