Mercurial > hg > orthanc
comparison Plugins/Samples/Common/OrthancPluginCppWrapper.h @ 3415:2a821deece64
refactoring to handle "not allowed" HTTP status 405
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 11 Jun 2019 21:06:57 +0200 |
parents | b9cba6a91780 |
children | 541c787e2230 |
comparison
equal
deleted
inserted
replaced
3414:b9cba6a91780 | 3415:2a821deece64 |
---|---|
552 | 552 |
553 | 553 |
554 namespace Internals | 554 namespace Internals |
555 { | 555 { |
556 template <RestCallback Callback> | 556 template <RestCallback Callback> |
557 OrthancPluginErrorCode Protect(OrthancPluginRestOutput* output, | 557 static OrthancPluginErrorCode Protect(OrthancPluginRestOutput* output, |
558 const char* url, | 558 const char* url, |
559 const OrthancPluginHttpRequest* request) | 559 const OrthancPluginHttpRequest* request) |
560 { | 560 { |
561 try | 561 try |
562 { | 562 { |
563 Callback(output, url, request); | 563 Callback(output, url, request); |
564 return OrthancPluginErrorCode_Success; | 564 return OrthancPluginErrorCode_Success; |
932 | 932 |
933 virtual void Execute(OrthancPluginRestOutput* output) = 0; | 933 virtual void Execute(OrthancPluginRestOutput* output) = 0; |
934 }; | 934 }; |
935 | 935 |
936 | 936 |
937 typedef IChunkedRequestReader* (*ChunkedRestCallback) (OrthancPluginRestOutput* output, | 937 typedef IChunkedRequestReader* (*ChunkedRestCallback) (const char* url, |
938 const char* url, | |
939 const OrthancPluginHttpRequest* request); | 938 const OrthancPluginHttpRequest* request); |
940 | 939 |
941 | 940 |
942 namespace Internals | 941 namespace Internals |
943 { | 942 { |
943 inline void NullRestCallback(OrthancPluginRestOutput* output, | |
944 const char* url, | |
945 const OrthancPluginHttpRequest* request) | |
946 { | |
947 } | |
948 | |
949 inline IChunkedRequestReader *NullChunkedRestCallback(const char* url, | |
950 const OrthancPluginHttpRequest* request) | |
951 { | |
952 return NULL; | |
953 } | |
954 | |
955 | |
944 #if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1 | 956 #if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1 |
945 template <ChunkedRestCallback Callback> | 957 template <ChunkedRestCallback Callback> |
946 OrthancPluginErrorCode Protect(OrthancPluginRestOutput* output, | 958 static OrthancPluginErrorCode Protect(OrthancPluginServerChunkedRequestReader** reader, |
947 OrthancPluginServerChunkedRequestReader** reader, | 959 const char* url, |
948 const char* url, | 960 const OrthancPluginHttpRequest* request) |
949 const OrthancPluginHttpRequest* request) | |
950 { | |
951 try | |
952 { | |
953 switch (request->method) | |
954 { | |
955 case OrthancPluginHttpMethod_Get: | |
956 case OrthancPluginHttpMethod_Delete: | |
957 if (output == NULL || | |
958 reader != NULL || | |
959 Callback(output, url, request) != NULL) | |
960 { | |
961 return OrthancPluginErrorCode_InternalError; | |
962 } | |
963 | |
964 return OrthancPluginErrorCode_Success; | |
965 | |
966 case OrthancPluginHttpMethod_Post: | |
967 case OrthancPluginHttpMethod_Put: | |
968 if (output != NULL || | |
969 reader == NULL) | |
970 { | |
971 return OrthancPluginErrorCode_InternalError; | |
972 } | |
973 else | |
974 { | |
975 *reader = reinterpret_cast<OrthancPluginServerChunkedRequestReader*>(Callback(NULL, url, request)); | |
976 if (*reader == NULL) | |
977 { | |
978 return OrthancPluginErrorCode_Plugin; | |
979 } | |
980 } | |
981 | |
982 return OrthancPluginErrorCode_Success; | |
983 | |
984 default: | |
985 return OrthancPluginErrorCode_InternalError; | |
986 } | |
987 } | |
988 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) | |
989 { | |
990 #if HAS_ORTHANC_EXCEPTION == 1 && HAS_ORTHANC_PLUGIN_EXCEPTION_DETAILS == 1 | |
991 if (HasGlobalContext() && | |
992 e.HasDetails()) | |
993 { | |
994 // The "false" instructs Orthanc not to log the detailed | |
995 // error message. This is to avoid duplicating the details, | |
996 // because "OrthancException" already does it on construction. | |
997 OrthancPluginSetHttpErrorDetails | |
998 (GetGlobalContext(), output, e.GetDetails(), false); | |
999 } | |
1000 #endif | |
1001 | |
1002 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); | |
1003 } | |
1004 catch (boost::bad_lexical_cast&) | |
1005 { | |
1006 return OrthancPluginErrorCode_BadFileFormat; | |
1007 } | |
1008 catch (...) | |
1009 { | |
1010 return OrthancPluginErrorCode_Plugin; | |
1011 } | |
1012 } | |
1013 | |
1014 static OrthancPluginErrorCode ChunkedRequestReaderAddChunk( | |
1015 OrthancPluginServerChunkedRequestReader* reader, | |
1016 const void* data, | |
1017 uint32_t size) | |
1018 { | 961 { |
1019 try | 962 try |
1020 { | 963 { |
1021 if (reader == NULL) | 964 if (reader == NULL) |
1022 { | 965 { |
1023 return OrthancPluginErrorCode_InternalError; | 966 return OrthancPluginErrorCode_InternalError; |
1024 } | 967 } |
1025 | 968 else |
1026 reinterpret_cast<IChunkedRequestReader*>(reader)->AddChunk(data, size); | 969 { |
1027 return OrthancPluginErrorCode_Success; | 970 *reader = reinterpret_cast<OrthancPluginServerChunkedRequestReader*>(Callback(url, request)); |
971 if (*reader == NULL) | |
972 { | |
973 return OrthancPluginErrorCode_Plugin; | |
974 } | |
975 else | |
976 { | |
977 return OrthancPluginErrorCode_Success; | |
978 } | |
979 } | |
1028 } | 980 } |
1029 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) | 981 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) |
1030 { | 982 { |
1031 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); | 983 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); |
1032 } | 984 } |
1038 { | 990 { |
1039 return OrthancPluginErrorCode_Plugin; | 991 return OrthancPluginErrorCode_Plugin; |
1040 } | 992 } |
1041 } | 993 } |
1042 | 994 |
1043 static OrthancPluginErrorCode ChunkedRequestReaderExecute( | 995 static inline OrthancPluginErrorCode ChunkedRequestReaderAddChunk( |
1044 OrthancPluginServerChunkedRequestReader* reader, | 996 OrthancPluginServerChunkedRequestReader* reader, |
1045 OrthancPluginRestOutput* output) | 997 const void* data, |
998 uint32_t size) | |
1046 { | 999 { |
1047 try | 1000 try |
1048 { | 1001 { |
1049 if (reader == NULL) | 1002 if (reader == NULL) |
1050 { | 1003 { |
1051 return OrthancPluginErrorCode_InternalError; | 1004 return OrthancPluginErrorCode_InternalError; |
1052 } | 1005 } |
1053 | 1006 |
1007 reinterpret_cast<IChunkedRequestReader*>(reader)->AddChunk(data, size); | |
1008 return OrthancPluginErrorCode_Success; | |
1009 } | |
1010 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) | |
1011 { | |
1012 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); | |
1013 } | |
1014 catch (boost::bad_lexical_cast&) | |
1015 { | |
1016 return OrthancPluginErrorCode_BadFileFormat; | |
1017 } | |
1018 catch (...) | |
1019 { | |
1020 return OrthancPluginErrorCode_Plugin; | |
1021 } | |
1022 } | |
1023 | |
1024 static inline OrthancPluginErrorCode ChunkedRequestReaderExecute( | |
1025 OrthancPluginServerChunkedRequestReader* reader, | |
1026 OrthancPluginRestOutput* output) | |
1027 { | |
1028 try | |
1029 { | |
1030 if (reader == NULL) | |
1031 { | |
1032 return OrthancPluginErrorCode_InternalError; | |
1033 } | |
1034 | |
1054 reinterpret_cast<IChunkedRequestReader*>(reader)->Execute(output); | 1035 reinterpret_cast<IChunkedRequestReader*>(reader)->Execute(output); |
1055 return OrthancPluginErrorCode_Success; | 1036 return OrthancPluginErrorCode_Success; |
1056 } | 1037 } |
1057 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) | 1038 catch (ORTHANC_PLUGINS_EXCEPTION_CLASS& e) |
1058 { | 1039 { |
1066 { | 1047 { |
1067 return OrthancPluginErrorCode_Plugin; | 1048 return OrthancPluginErrorCode_Plugin; |
1068 } | 1049 } |
1069 } | 1050 } |
1070 | 1051 |
1071 static void ChunkedRequestReaderFinalize( | 1052 static inline void ChunkedRequestReaderFinalize( |
1072 OrthancPluginServerChunkedRequestReader* reader) | 1053 OrthancPluginServerChunkedRequestReader* reader) |
1073 { | 1054 { |
1074 if (reader != NULL) | 1055 if (reader != NULL) |
1075 { | 1056 { |
1076 delete reinterpret_cast<IChunkedRequestReader*>(reader); | 1057 delete reinterpret_cast<IChunkedRequestReader*>(reader); |
1077 } | 1058 } |
1078 } | 1059 } |
1079 | 1060 |
1080 #else | 1061 #else |
1081 | 1062 |
1082 template <ChunkedRestCallback Callback> | 1063 template< |
1083 void ChunkedRestCompatibility(OrthancPluginRestOutput* output, | 1064 RestCallback GetHandler, |
1084 const char* url, | 1065 ChunkedRestCallback PostHandler, |
1085 const OrthancPluginHttpRequest* request) | 1066 RestCallback DeleteHandler, |
1086 { | 1067 ChunkedRestCallback PutHandler |
1068 > | |
1069 static void ChunkedRestCompatibility(OrthancPluginRestOutput* output, | |
1070 const char* url, | |
1071 const OrthancPluginHttpRequest* request) | |
1072 { | |
1073 std::string allowed; | |
1074 | |
1075 if (GetHandler != Internals::NullRestCallback) | |
1076 { | |
1077 allowed += "GET"; | |
1078 } | |
1079 | |
1080 if (PostHandler != Internals::NullChunkedRestCallback) | |
1081 { | |
1082 if (!allowed.empty()) | |
1083 { | |
1084 allowed += ","; | |
1085 } | |
1086 | |
1087 allowed += "POST"; | |
1088 } | |
1089 | |
1090 if (DeleteHandler != Internals::NullRestCallback) | |
1091 { | |
1092 if (!allowed.empty()) | |
1093 { | |
1094 allowed += ","; | |
1095 } | |
1096 | |
1097 allowed += "DELETE"; | |
1098 } | |
1099 | |
1100 if (PutHandler != Internals::NullChunkedRestCallback) | |
1101 { | |
1102 if (!allowed.empty()) | |
1103 { | |
1104 allowed += ","; | |
1105 } | |
1106 | |
1107 allowed += "PUT"; | |
1108 } | |
1109 | |
1087 switch (request->method) | 1110 switch (request->method) |
1088 { | 1111 { |
1089 case OrthancPluginHttpMethod_Get: | 1112 case OrthancPluginHttpMethod_Get: |
1090 case OrthancPluginHttpMethod_Delete: | 1113 { |
1091 if (Callback(output, url, request) != NULL) | 1114 if (GetHandler == Internals::NullRestCallback) |
1092 { | 1115 { |
1093 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); | 1116 OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowed.c_str()); |
1094 } | 1117 } |
1095 else | 1118 else |
1096 { | 1119 { |
1097 return; | 1120 GetHandler(output, url, request); |
1098 } | 1121 } |
1122 return; | |
1123 } | |
1099 | 1124 |
1100 case OrthancPluginHttpMethod_Post: | 1125 case OrthancPluginHttpMethod_Post: |
1101 case OrthancPluginHttpMethod_Put: | |
1102 { | 1126 { |
1103 std::auto_ptr<IChunkedRequestReader> reader(Callback(NULL, url, request)); | 1127 if (PostHandler == Internals::NullChunkedRestCallback) |
1104 if (reader.get() == NULL) | |
1105 { | 1128 { |
1106 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); | 1129 OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowed.c_str()); |
1107 } | 1130 } |
1108 else | 1131 else |
1109 { | 1132 { |
1110 if (request->bodySize != 0) | 1133 std::auto_ptr<IChunkedRequestReader> reader(PostHandler(url, request)); |
1134 if (reader.get() == NULL) | |
1135 { | |
1136 ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin); | |
1137 } | |
1138 else | |
1111 { | 1139 { |
1112 reader->AddChunk(request->body, request->bodySize); | 1140 reader->AddChunk(request->body, request->bodySize); |
1141 reader->Execute(output); | |
1113 } | 1142 } |
1114 reader->Execute(output); | |
1115 } | 1143 } |
1116 return; | 1144 return; |
1117 } | 1145 } |
1118 | 1146 |
1147 case OrthancPluginHttpMethod_Delete: | |
1148 { | |
1149 if (DeleteHandler == Internals::NullRestCallback) | |
1150 { | |
1151 OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowed.c_str()); | |
1152 } | |
1153 else | |
1154 { | |
1155 DeleteHandler(output, url, request); | |
1156 } | |
1157 return; | |
1158 } | |
1159 | |
1160 case OrthancPluginHttpMethod_Put: | |
1161 { | |
1162 if (PutHandler == Internals::NullChunkedRestCallback) | |
1163 { | |
1164 OrthancPluginSendMethodNotAllowed(GetGlobalContext(), output, allowed.c_str()); | |
1165 } | |
1166 else | |
1167 { | |
1168 std::auto_ptr<IChunkedRequestReader> reader(PutHandler(url, request)); | |
1169 if (reader.get() == NULL) | |
1170 { | |
1171 ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin); | |
1172 } | |
1173 else | |
1174 { | |
1175 reader->AddChunk(request->body, request->bodySize); | |
1176 reader->Execute(output); | |
1177 } | |
1178 } | |
1179 return; | |
1180 } | |
1181 | |
1119 default: | 1182 default: |
1120 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); | 1183 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError); |
1121 } | 1184 } |
1122 } | 1185 } |
1123 #endif | 1186 #endif |
1124 } | 1187 } |
1125 | 1188 |
1126 | 1189 |
1127 template <ChunkedRestCallback Callback> | 1190 |
1191 template< | |
1192 RestCallback GetHandler = Internals::NullRestCallback, | |
1193 ChunkedRestCallback PostHandler = Internals::NullChunkedRestCallback, | |
1194 RestCallback DeleteHandler = Internals::NullRestCallback, | |
1195 ChunkedRestCallback PutHandler = Internals::NullChunkedRestCallback | |
1196 > | |
1128 void RegisterChunkedRestCallback(const std::string& uri) | 1197 void RegisterChunkedRestCallback(const std::string& uri) |
1129 { | 1198 { |
1130 #if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1 | 1199 #if HAS_ORTHANC_PLUGIN_CHUNKED_HTTP_SERVER == 1 |
1131 OrthancPluginRegisterChunkedRestCallback( | 1200 OrthancPluginRegisterChunkedRestCallback( |
1132 GetGlobalContext(), uri.c_str(), Internals::Protect<Callback>, | 1201 GetGlobalContext(), uri.c_str(), |
1202 GetHandler == Internals::NullRestCallback ? NULL : Internals::Protect<GetHandler>, | |
1203 PostHandler == Internals::NullChunkedRestCallback ? NULL : Internals::Protect<PostHandler>, | |
1204 DeleteHandler == Internals::NullRestCallback ? NULL : Internals::Protect<DeleteHandler>, | |
1205 PutHandler == Internals::NullChunkedRestCallback ? NULL : Internals::Protect<PutHandler>, | |
1133 Internals::ChunkedRequestReaderAddChunk, | 1206 Internals::ChunkedRequestReaderAddChunk, |
1134 Internals::ChunkedRequestReaderExecute, | 1207 Internals::ChunkedRequestReaderExecute, |
1135 Internals::ChunkedRequestReaderFinalize); | 1208 Internals::ChunkedRequestReaderFinalize); |
1136 #else | 1209 #else |
1137 LogWarning("Performance warning: The plugin was compiled against a pre-1.5.7 version " | 1210 LogWarning("Performance warning: The plugin was compiled against a pre-1.5.7 version " |
1138 "of the Orthanc SDK. Multipart transfers will be entirely stored in RAM."); | 1211 "of the Orthanc SDK. Multipart transfers will be entirely stored in RAM."); |
1139 OrthancPluginRegisterRestCallback( | 1212 OrthancPluginRegisterRestCallback( |
1140 GetGlobalContext(), uri.c_str(), | 1213 GetGlobalContext(), uri.c_str(), |
1141 Internals::Protect< Internals::ChunkedRestCompatibility<Callback> >); | 1214 Internals::Protect< Internals::ChunkedRestCompatibility< |
1215 GetHandler, PostHandler, DeleteHandler, PutHandler> >); | |
1142 #endif | 1216 #endif |
1143 } | 1217 } |
1144 } | 1218 } |