Mercurial > hg > orthanc
comparison OrthancServer/OrthancRestApi.cpp @ 485:bdbde1fbfab3
send resources through HTTP
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 16 Jul 2013 13:48:33 +0200 |
parents | b8ace6fc1d1f |
children | 7db04aa5104f |
comparison
equal
deleted
inserted
replaced
484:b8ace6fc1d1f | 485:bdbde1fbfab3 |
---|---|
30 **/ | 30 **/ |
31 | 31 |
32 | 32 |
33 #include "OrthancRestApi.h" | 33 #include "OrthancRestApi.h" |
34 | 34 |
35 #include "../Core/Compression/HierarchicalZipWriter.h" | |
36 #include "../Core/HttpClient.h" | |
35 #include "../Core/HttpServer/FilesystemHttpSender.h" | 37 #include "../Core/HttpServer/FilesystemHttpSender.h" |
36 #include "../Core/Uuid.h" | 38 #include "../Core/Uuid.h" |
37 #include "../Core/Compression/HierarchicalZipWriter.h" | |
38 #include "DicomProtocol/DicomUserConnection.h" | 39 #include "DicomProtocol/DicomUserConnection.h" |
39 #include "FromDcmtkBridge.h" | 40 #include "FromDcmtkBridge.h" |
40 #include "OrthancInitialization.h" | 41 #include "OrthancInitialization.h" |
41 #include "ServerToolbox.h" | 42 #include "ServerToolbox.h" |
42 | 43 |
246 | 247 |
247 call.GetOutput().AnswerJson(result); | 248 call.GetOutput().AnswerJson(result); |
248 } | 249 } |
249 | 250 |
250 | 251 |
251 static void DicomStore(RestApi::PostCall& call) | 252 static bool GetInstancesToExport(std::list<std::string>& instances, |
252 { | 253 const std::string& remote, |
253 RETRIEVE_CONTEXT(call); | 254 RestApi::PostCall& call) |
254 | 255 { |
255 std::string remote = call.GetUriComponent("id", ""); | 256 RETRIEVE_CONTEXT(call); |
257 | |
256 std::string stripped = Toolbox::StripSpaces(call.GetPostBody()); | 258 std::string stripped = Toolbox::StripSpaces(call.GetPostBody()); |
257 | 259 |
258 Json::Value request; | 260 Json::Value request; |
259 if (Toolbox::IsSHA1(stripped)) | 261 if (Toolbox::IsSHA1(stripped)) |
260 { | 262 { |
262 request = stripped; | 264 request = stripped; |
263 } | 265 } |
264 else if (!call.ParseJsonRequest(request)) | 266 else if (!call.ParseJsonRequest(request)) |
265 { | 267 { |
266 // Bad JSON request | 268 // Bad JSON request |
267 return; | 269 return false; |
268 } | 270 } |
269 | 271 |
270 std::list<std::string> instances; | |
271 if (request.isString()) | 272 if (request.isString()) |
272 { | 273 { |
273 LOG(INFO) << "Sending resource " << request.asString() << " to modality " << remote; | |
274 context.GetIndex().LogExportedResource(request.asString(), remote); | 274 context.GetIndex().LogExportedResource(request.asString(), remote); |
275 context.GetIndex().GetChildInstances(instances, request.asString()); | 275 context.GetIndex().GetChildInstances(instances, request.asString()); |
276 } | 276 } |
277 else if (request.isArray()) | 277 else if (request.isArray()) |
278 { | 278 { |
279 for (Json::Value::ArrayIndex i = 0; i < request.size(); i++) | 279 for (Json::Value::ArrayIndex i = 0; i < request.size(); i++) |
280 { | 280 { |
281 if (!request[i].isString()) | 281 if (!request[i].isString()) |
282 { | 282 { |
283 return; | 283 return false; |
284 } | 284 } |
285 | 285 |
286 std::string stripped = Toolbox::StripSpaces(request[i].asString()); | 286 std::string stripped = Toolbox::StripSpaces(request[i].asString()); |
287 if (!Toolbox::IsSHA1(stripped)) | 287 if (!Toolbox::IsSHA1(stripped)) |
288 { | 288 { |
289 return; | 289 return false; |
290 } | 290 } |
291 | 291 |
292 LOG(INFO) << "Sending resource " << stripped << " to modality " << remote; | |
293 context.GetIndex().LogExportedResource(stripped, remote); | 292 context.GetIndex().LogExportedResource(stripped, remote); |
294 | 293 |
295 std::list<std::string> tmp; | 294 std::list<std::string> tmp; |
296 context.GetIndex().GetChildInstances(tmp, stripped); | 295 context.GetIndex().GetChildInstances(tmp, stripped); |
297 instances.merge(tmp); | 296 instances.merge(tmp); |
299 } | 298 } |
300 } | 299 } |
301 else | 300 else |
302 { | 301 { |
303 // Neither a string, nor a list of strings. Bad request. | 302 // Neither a string, nor a list of strings. Bad request. |
303 return false; | |
304 } | |
305 | |
306 return true; | |
307 } | |
308 | |
309 | |
310 static void DicomStore(RestApi::PostCall& call) | |
311 { | |
312 RETRIEVE_CONTEXT(call); | |
313 | |
314 std::string remote = call.GetUriComponent("id", ""); | |
315 | |
316 std::list<std::string> instances; | |
317 if (!GetInstancesToExport(instances, remote, call)) | |
318 { | |
304 return; | 319 return; |
305 } | 320 } |
306 | 321 |
307 DicomUserConnection connection; | 322 DicomUserConnection connection; |
308 ConnectToModality(connection, remote); | 323 ConnectToModality(connection, remote); |
309 | 324 |
310 for (std::list<std::string>::const_iterator | 325 for (std::list<std::string>::const_iterator |
311 it = instances.begin(); it != instances.end(); it++) | 326 it = instances.begin(); it != instances.end(); it++) |
312 { | 327 { |
328 LOG(INFO) << "Sending resource " << *it << " to modality \"" << remote << "\""; | |
329 | |
313 std::string dicom; | 330 std::string dicom; |
314 context.ReadFile(dicom, *it, FileContentType_Dicom); | 331 context.ReadFile(dicom, *it, FileContentType_Dicom); |
315 connection.Store(dicom); | 332 connection.Store(dicom); |
316 } | 333 } |
317 | 334 |
1647 result.append("store"); | 1664 result.append("store"); |
1648 call.GetOutput().AnswerJson(result); | 1665 call.GetOutput().AnswerJson(result); |
1649 } | 1666 } |
1650 } | 1667 } |
1651 | 1668 |
1669 static void PeerStore(RestApi::PostCall& call) | |
1670 { | |
1671 RETRIEVE_CONTEXT(call); | |
1672 | |
1673 std::string remote = call.GetUriComponent("id", ""); | |
1674 | |
1675 std::list<std::string> instances; | |
1676 if (!GetInstancesToExport(instances, remote, call)) | |
1677 { | |
1678 return; | |
1679 } | |
1680 | |
1681 std::string url, username, password; | |
1682 GetOrthancPeer(remote, url, username, password); | |
1683 | |
1684 // Configure the HTTP client | |
1685 HttpClient client; | |
1686 if (username.size() != 0 && password.size() != 0) | |
1687 { | |
1688 client.SetCredentials(username.c_str(), password.c_str()); | |
1689 } | |
1690 | |
1691 client.SetUrl(url + "instances"); | |
1692 client.SetMethod(HttpMethod_Post); | |
1693 | |
1694 // Loop over the instances that are to be sent | |
1695 for (std::list<std::string>::const_iterator | |
1696 it = instances.begin(); it != instances.end(); it++) | |
1697 { | |
1698 LOG(INFO) << "Sending resource " << *it << " to peer \"" << remote << "\""; | |
1699 | |
1700 context.ReadFile(client.AccessPostData(), *it, FileContentType_Dicom); | |
1701 | |
1702 std::string answer; | |
1703 if (!client.Apply(answer)) | |
1704 { | |
1705 LOG(ERROR) << "Unable to send resource " << *it << " to peer \"" << remote << "\""; | |
1706 return; | |
1707 } | |
1708 } | |
1709 | |
1710 call.GetOutput().AnswerBuffer("{}", "application/json"); | |
1711 } | |
1712 | |
1713 | |
1652 | 1714 |
1653 | 1715 |
1654 | 1716 |
1655 // Registration of the various REST handlers -------------------------------- | 1717 // Registration of the various REST handlers -------------------------------- |
1656 | 1718 |
1735 Register("/modalities/{id}/find", DicomFind); | 1797 Register("/modalities/{id}/find", DicomFind); |
1736 Register("/modalities/{id}/store", DicomStore); | 1798 Register("/modalities/{id}/store", DicomStore); |
1737 | 1799 |
1738 Register("/peers", ListPeers); | 1800 Register("/peers", ListPeers); |
1739 Register("/peers/{id}", ListPeerOperations); | 1801 Register("/peers/{id}", ListPeerOperations); |
1802 Register("/peers/{id}/store", PeerStore); | |
1740 | 1803 |
1741 Register("/instances/{id}/modify", ModifyInstance); | 1804 Register("/instances/{id}/modify", ModifyInstance); |
1742 Register("/series/{id}/modify", ModifySeriesInplace); | 1805 Register("/series/{id}/modify", ModifySeriesInplace); |
1743 Register("/studies/{id}/modify", ModifyStudyInplace); | 1806 Register("/studies/{id}/modify", ModifyStudyInplace); |
1744 Register("/patients/{id}/modify", ModifyPatientInplace); | 1807 Register("/patients/{id}/modify", ModifyPatientInplace); |