Mercurial > hg > orthanc
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 } |