# HG changeset patch # User Sebastien Jodogne # Date 1542299295 -3600 # Node ID aee3d7941c9b80c01e8d68100f544199838670e6 # Parent c0589c3173fd5bc5d3ee60a4e5b4f3ed3cc9237a preparing to load images using DICOMweb diff -r c0589c3173fd -r aee3d7941c9b Applications/Generic/NativeStoneApplicationRunner.cpp --- a/Applications/Generic/NativeStoneApplicationRunner.cpp Tue Nov 13 10:36:53 2018 +0100 +++ b/Applications/Generic/NativeStoneApplicationRunner.cpp Thu Nov 15 17:28:15 2018 +0100 @@ -193,7 +193,7 @@ { OracleWebService webService(broker_, oracle, webServiceParameters, context); - context.SetWebService(webService); + context.Initialize(broker_, webService, webServiceParameters.GetUrl()); application_.Initialize(&context, statusBar, parameters); diff -r c0589c3173fd -r aee3d7941c9b Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp --- a/Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp Tue Nov 13 10:36:53 2018 +0100 +++ b/Applications/Samples/SimpleViewer/SimpleViewerApplication.cpp Thu Nov 15 17:28:15 2018 +0100 @@ -61,10 +61,8 @@ mainLayout_->AddWidget(thumbnailsLayout_); mainLayout_->AddWidget(mainWidget_); - orthancApiClient_.reset(new OrthancApiClient(IObserver::GetBroker(), context_->GetWebService())); - // sources - smartLoader_.reset(new SmartLoader(IObserver::GetBroker(), *orthancApiClient_)); + smartLoader_.reset(new SmartLoader(IObserver::GetBroker(), context->GetOrthancApiClient())); smartLoader_->SetImageQuality(SliceImageQuality_FullPam); mainLayout_->SetTransmitMouseOver(true); @@ -80,7 +78,7 @@ if (parameters.count("studyId") < 1) { LOG(WARNING) << "The study ID is missing, will take the first studyId found in Orthanc"; - orthancApiClient_->GetJsonAsync("/studies", new Callable(*this, &SimpleViewerApplication::OnStudyListReceived)); + context->GetOrthancApiClient().GetJsonAsync("/studies", new Callable(*this, &SimpleViewerApplication::OnStudyListReceived)); } else { @@ -118,7 +116,7 @@ { for (size_t i=0; i < response["Series"].size(); i++) { - orthancApiClient_->GetJsonAsync("/series/" + response["Series"][(int)i].asString(), new Callable(*this, &SimpleViewerApplication::OnSeriesReceived)); + context_->GetOrthancApiClient().GetJsonAsync("/series/" + response["Series"][(int)i].asString(), new Callable(*this, &SimpleViewerApplication::OnSeriesReceived)); } } } @@ -168,7 +166,7 @@ void SimpleViewerApplication::SelectStudy(const std::string& studyId) { - orthancApiClient_->GetJsonAsync("/studies/" + studyId, new Callable(*this, &SimpleViewerApplication::OnStudyReceived)); + context_->GetOrthancApiClient().GetJsonAsync("/studies/" + studyId, new Callable(*this, &SimpleViewerApplication::OnStudyReceived)); } void SimpleViewerApplication::OnWidgetGeometryChanged(const SliceViewerWidget::GeometryChangedMessage& message) diff -r c0589c3173fd -r aee3d7941c9b Applications/Samples/SimpleViewer/SimpleViewerApplication.h --- a/Applications/Samples/SimpleViewer/SimpleViewerApplication.h Tue Nov 13 10:36:53 2018 +0100 +++ b/Applications/Samples/SimpleViewer/SimpleViewerApplication.h Thu Nov 15 17:28:15 2018 +0100 @@ -104,7 +104,6 @@ IStatusBar* statusBar_; std::auto_ptr smartLoader_; - std::auto_ptr orthancApiClient_; Orthanc::Font font_; diff -r c0589c3173fd -r aee3d7941c9b Applications/Samples/SimpleViewerApplicationSingleFile.h --- a/Applications/Samples/SimpleViewerApplicationSingleFile.h Tue Nov 13 10:36:53 2018 +0100 +++ b/Applications/Samples/SimpleViewerApplicationSingleFile.h Thu Nov 15 17:28:15 2018 +0100 @@ -247,7 +247,6 @@ IStatusBar* statusBar_; std::auto_ptr smartLoader_; - std::auto_ptr orthancApiClient_; Orthanc::Font font_; @@ -304,10 +303,8 @@ mainLayout_->AddWidget(thumbnailsLayout_); mainLayout_->AddWidget(mainWidget_); - orthancApiClient_.reset(new OrthancApiClient(GetBroker(), context_->GetWebService())); - // sources - smartLoader_.reset(new SmartLoader(GetBroker(), *orthancApiClient_)); + smartLoader_.reset(new SmartLoader(GetBroker(), context->GetOrthancApiClient())); smartLoader_->SetImageQuality(SliceImageQuality_FullPam); mainLayout_->SetTransmitMouseOver(true); @@ -323,7 +320,7 @@ if (parameters.count("studyId") < 1) { LOG(WARNING) << "The study ID is missing, will take the first studyId found in Orthanc"; - orthancApiClient_->GetJsonAsync( + context->GetOrthancApiClient().GetJsonAsync( "/studies", new Callable (*this, &SimpleViewerApplication::OnStudyListReceived)); @@ -353,7 +350,7 @@ { for (size_t i=0; i < response["Series"].size(); i++) { - orthancApiClient_->GetJsonAsync( + context_->GetOrthancApiClient().GetJsonAsync( "/series/" + response["Series"][(int)i].asString(), new Callable (*this, &SimpleViewerApplication::OnSeriesReceived)); @@ -405,7 +402,9 @@ void SelectStudy(const std::string& studyId) { LOG(INFO) << "Selecting study: " << studyId; - orthancApiClient_->GetJsonAsync("/studies/" + studyId, new Callable(*this, &SimpleViewerApplication::OnStudyReceived)); + context_->GetOrthancApiClient().GetJsonAsync( + "/studies/" + studyId, new Callable + (*this, &SimpleViewerApplication::OnStudyReceived)); } void OnWidgetGeometryChanged(const SliceViewerWidget::GeometryChangedMessage& message) diff -r c0589c3173fd -r aee3d7941c9b Applications/Samples/SingleFrameApplication.h --- a/Applications/Samples/SingleFrameApplication.h Tue Nov 13 10:36:53 2018 +0100 +++ b/Applications/Samples/SingleFrameApplication.h Thu Nov 15 17:28:15 2018 +0100 @@ -197,7 +197,6 @@ } std::auto_ptr mainWidgetInteractor_; - std::auto_ptr orthancApiClient_; const DicomSeriesVolumeSlicer* source_; unsigned int slice_; @@ -243,10 +242,9 @@ std::string instance = parameters["instance"].as(); int frame = parameters["frame"].as(); - orthancApiClient_.reset(new OrthancApiClient(GetBroker(), context_->GetWebService())); mainWidget_ = new SliceViewerWidget(GetBroker(), "main-widget"); - std::auto_ptr layer(new DicomSeriesVolumeSlicer(GetBroker(), *orthancApiClient_)); + std::auto_ptr layer(new DicomSeriesVolumeSlicer(GetBroker(), context->GetOrthancApiClient())); source_ = layer.get(); layer->LoadFrame(instance, frame); layer->RegisterObserverCallback(new Callable(*this, &SingleFrameApplication::OnMainWidgetGeometryReady)); diff -r c0589c3173fd -r aee3d7941c9b Applications/Samples/SingleFrameEditorApplication.h --- a/Applications/Samples/SingleFrameEditorApplication.h Tue Nov 13 10:36:53 2018 +0100 +++ b/Applications/Samples/SingleFrameEditorApplication.h Thu Nov 15 17:28:15 2018 +0100 @@ -61,8 +61,9 @@ }; - UndoRedoStack undoRedoStack_; - Tool tool_; + StoneApplicationContext* context_; + UndoRedoStack undoRedoStack_; + Tool tool_; static double GetHandleSize() @@ -74,9 +75,15 @@ public: RadiographyEditorInteractor(MessageBroker& broker) : IObserver(broker), + context_(NULL), tool_(Tool_Move) { } + + void SetContext(StoneApplicationContext& context) + { + context_ = &context; + } virtual IWorldSceneMouseTracker* CreateMouseTracker(WorldSceneWidget& worldWidget, const ViewportGeometry& view, @@ -292,8 +299,13 @@ tags.SetValue(Orthanc::DICOM_TAG_STUDY_ID, "STUDY", false); tags.SetValue(Orthanc::DICOM_TAG_VIEW_POSITION, "", false); - widget.GetScene().ExportDicom(tags, 0.1, 0.1, widget.IsInverted(), - widget.GetInterpolation(), EXPORT_USING_PAM); + if (context_ != NULL) + { + widget.GetScene().ExportDicom(context_->GetOrthancApiClient(), + tags, 0.1, 0.1, widget.IsInverted(), + widget.GetInterpolation(), EXPORT_USING_PAM); + } + break; } @@ -367,7 +379,6 @@ public IObserver { private: - std::auto_ptr orthancApiClient_; std::auto_ptr scene_; RadiographyEditorInteractor interactor_; @@ -403,6 +414,7 @@ using namespace OrthancStone; context_ = context; + interactor_.SetContext(*context); statusBar.SetMessage("Use the key \"a\" to reinitialize the layout"); statusBar.SetMessage("Use the key \"c\" to crop"); @@ -427,15 +439,14 @@ std::string instance = parameters["instance"].as(); int frame = parameters["frame"].as(); - orthancApiClient_.reset(new OrthancApiClient(GetBroker(), context_->GetWebService())); - Orthanc::FontRegistry fonts; fonts.AddFromResource(Orthanc::EmbeddedResources::FONT_UBUNTU_MONO_BOLD_16); - scene_.reset(new RadiographyScene(GetBroker(), *orthancApiClient_)); - scene_->LoadDicomFrame(instance, frame, false); //.SetPan(200, 0); - //scene_->LoadDicomFrame("61f3143e-96f34791-ad6bbb8d-62559e75-45943e1b", 0, false); - + scene_.reset(new RadiographyScene(GetBroker())); + //scene_->LoadDicomFrame(instance, frame, false); //.SetPan(200, 0); + scene_->LoadDicomFrame(context->GetOrthancApiClient(), "61f3143e-96f34791-ad6bbb8d-62559e75-45943e1b", 0, false); + //scene_->LoadDicomWebFrame(context->GetWebService()); + { RadiographyLayer& layer = scene_->LoadText(fonts.GetFont(0), "Hello\nworld"); layer.SetResizeable(true); diff -r c0589c3173fd -r aee3d7941c9b Applications/StoneApplicationContext.cpp --- a/Applications/StoneApplicationContext.cpp Tue Nov 13 10:36:53 2018 +0100 +++ b/Applications/StoneApplicationContext.cpp Thu Nov 15 17:28:15 2018 +0100 @@ -21,6 +21,35 @@ #include "StoneApplicationContext.h" +#include + namespace OrthancStone { + IWebService& StoneApplicationContext::GetWebService() + { + if (webService_ == NULL) + { + throw Orthanc::ErrorCode_BadSequenceOfCalls; + } + + return *webService_; + } + + OrthancApiClient& StoneApplicationContext::GetOrthancApiClient() + { + if (orthanc_.get() == NULL) + { + throw Orthanc::ErrorCode_BadSequenceOfCalls; + } + + return *orthanc_; + } + + void StoneApplicationContext::Initialize(MessageBroker& broker, + IWebService& webService, + const std::string& orthancBaseUrl) + { + webService_ = &webService; + orthanc_.reset(new OrthancApiClient(broker, webService, orthancBaseUrl)); + } } diff -r c0589c3173fd -r aee3d7941c9b Applications/StoneApplicationContext.h --- a/Applications/StoneApplicationContext.h Tue Nov 13 10:36:53 2018 +0100 +++ b/Applications/StoneApplicationContext.h Thu Nov 15 17:28:15 2018 +0100 @@ -22,6 +22,7 @@ #pragma once #include "../Framework/Toolbox/IWebService.h" +#include "../Framework/Toolbox/OrthancApiClient.h" #include "../Framework/Viewport/WidgetViewport.h" #include @@ -34,25 +35,31 @@ // the StoneApplication can perform HTTP requests. In a WASM environment, // the WebService is provided by the browser while, in a native environment, // the WebService is provided by the OracleWebService (a C++ Http client) + class StoneApplicationContext : public boost::noncopyable { + protected: + // TODO ADD THE MessageBroker HERE + + IWebService* webService_; + std::auto_ptr orthanc_; - protected: - IWebService* webService_; public: - StoneApplicationContext() - : webService_(NULL) + StoneApplicationContext() : + webService_(NULL) { } - IWebService& GetWebService() {return *webService_;} - void SetWebService(IWebService& webService) - { - webService_ = &webService; - } - virtual ~StoneApplicationContext() { } + + IWebService& GetWebService(); + + OrthancApiClient& GetOrthancApiClient(); + + void Initialize(MessageBroker& broker, + IWebService& webService, + const std::string& orthancBaseUrl); }; } diff -r c0589c3173fd -r aee3d7941c9b Framework/Radiography/RadiographyScene.cpp --- a/Framework/Radiography/RadiographyScene.cpp Tue Nov 13 10:36:53 2018 +0100 +++ b/Framework/Radiography/RadiographyScene.cpp Thu Nov 15 17:28:15 2018 +0100 @@ -423,11 +423,9 @@ } - RadiographyScene::RadiographyScene(MessageBroker& broker, - OrthancApiClient& orthanc) : + RadiographyScene::RadiographyScene(MessageBroker& broker) : IObserver(broker), IObservable(broker), - orthanc_(orthanc), countLayers_(0), hasWindowing_(false), windowingCenter_(0), // Dummy initialization @@ -523,17 +521,18 @@ } - RadiographyLayer& RadiographyScene::LoadDicomFrame(const std::string& instance, + RadiographyLayer& RadiographyScene::LoadDicomFrame(OrthancApiClient& orthanc, + const std::string& instance, unsigned int frame, bool httpCompression) { RadiographyLayer& layer = RegisterLayer(new DicomLayer); { - IWebService::Headers headers; + IWebService::HttpHeaders headers; std::string uri = "/instances/" + instance + "/tags"; - orthanc_.GetBinaryAsync( + orthanc.GetBinaryAsync( uri, headers, new Callable (*this, &RadiographyScene::OnTagsReceived), NULL, @@ -541,7 +540,7 @@ } { - IWebService::Headers headers; + IWebService::HttpHeaders headers; headers["Accept"] = "image/x-portable-arbitrarymap"; if (httpCompression) @@ -552,7 +551,7 @@ std::string uri = ("/instances/" + instance + "/frames/" + boost::lexical_cast(frame) + "/image-uint16"); - orthanc_.GetBinaryAsync( + orthanc.GetBinaryAsync( uri, headers, new Callable (*this, &RadiographyScene::OnFrameReceived), NULL, @@ -562,6 +561,16 @@ return layer; } + + RadiographyLayer& RadiographyScene::LoadDicomWebFrame(IWebService& web) + { + RadiographyLayer& layer = RegisterLayer(new DicomLayer); + + + return layer; + } + + void RadiographyScene::OnTagsReceived(const OrthancApiClient::BinaryResponseReadyMessage& message) { @@ -728,7 +737,8 @@ // Export using PAM is faster than using PNG, but requires Orthanc // core >= 1.4.3 - void RadiographyScene::ExportDicom(const Orthanc::DicomMap& dicom, + void RadiographyScene::ExportDicom(OrthancApiClient& orthanc, + const Orthanc::DicomMap& dicom, double pixelSpacingX, double pixelSpacingY, bool invert, @@ -830,7 +840,7 @@ std::string(usePam ? Orthanc::MIME_PAM : Orthanc::MIME_PNG) + ";base64," + base64); - orthanc_.PostJsonAsyncExpectJson( + orthanc.PostJsonAsyncExpectJson( "/tools/create-dicom", json, new Callable (*this, &RadiographyScene::OnDicomExported), @@ -840,7 +850,14 @@ void RadiographyScene::OnDicomExported(const OrthancApiClient::JsonResponseReadyMessage& message) { - LOG(INFO) << "DICOM export was successful:" + LOG(INFO) << "DICOM export was successful: " << message.GetJson().toStyledString(); } + + + void RadiographyScene::OnDicomWebReceived(const IWebService::HttpRequestSuccessMessage& message) + { + LOG(INFO) << "DICOMweb WADO-RS received: " << message.GetAnswerSize() << " bytes"; + } + } diff -r c0589c3173fd -r aee3d7941c9b Framework/Radiography/RadiographyScene.h --- a/Framework/Radiography/RadiographyScene.h Tue Nov 13 10:36:53 2018 +0100 +++ b/Framework/Radiography/RadiographyScene.h Thu Nov 15 17:28:15 2018 +0100 @@ -74,12 +74,11 @@ typedef std::map Layers; - OrthancApiClient& orthanc_; - size_t countLayers_; - bool hasWindowing_; - float windowingCenter_; - float windowingWidth_; - Layers layers_; + size_t countLayers_; + bool hasWindowing_; + float windowingCenter_; + float windowingWidth_; + Layers layers_; RadiographyLayer& RegisterLayer(RadiographyLayer* layer); @@ -89,9 +88,10 @@ void OnDicomExported(const OrthancApiClient::JsonResponseReadyMessage& message); + void OnDicomWebReceived(const IWebService::HttpRequestSuccessMessage& message); + public: - RadiographyScene(MessageBroker& broker, - OrthancApiClient& orthanc); + RadiographyScene(MessageBroker& broker); virtual ~RadiographyScene(); @@ -110,10 +110,13 @@ RadiographyLayer& LoadTestBlock(unsigned int width, unsigned int height); - RadiographyLayer& LoadDicomFrame(const std::string& instance, + RadiographyLayer& LoadDicomFrame(OrthancApiClient& orthanc, + const std::string& instance, unsigned int frame, bool httpCompression); + RadiographyLayer& LoadDicomWebFrame(IWebService& web); + Extent2D GetSceneExtent() const; void Render(Orthanc::ImageAccessor& buffer, @@ -133,7 +136,8 @@ // Export using PAM is faster than using PNG, but requires Orthanc // core >= 1.4.3 - void ExportDicom(const Orthanc::DicomMap& dicom, + void ExportDicom(OrthancApiClient& orthanc, + const Orthanc::DicomMap& dicom, double pixelSpacingX, double pixelSpacingY, bool invert, diff -r c0589c3173fd -r aee3d7941c9b Framework/Toolbox/IWebService.h --- a/Framework/Toolbox/IWebService.h Tue Nov 13 10:36:53 2018 +0100 +++ b/Framework/Toolbox/IWebService.h Thu Nov 15 17:28:15 2018 +0100 @@ -43,7 +43,7 @@ MessageBroker& broker_; public: - typedef std::map Headers; + typedef std::map HttpHeaders; class HttpRequestSuccessMessage : public BaseMessage { @@ -51,16 +51,19 @@ const std::string& uri_; const void* answer_; size_t answerSize_; + const HttpHeaders& answerHeaders_; const Orthanc::IDynamicObject* payload_; public: HttpRequestSuccessMessage(const std::string& uri, const void* answer, size_t answerSize, + const HttpHeaders& answerHeaders, const Orthanc::IDynamicObject* payload) : uri_(uri), answer_(answer), answerSize_(answerSize), + answerHeaders_(answerHeaders), payload_(payload) { } @@ -80,6 +83,11 @@ return answerSize_; } + const HttpHeaders& GetAnswerHttpHeaders() const + { + return answerHeaders_; + } + bool HasPayload() const { return payload_ != NULL; @@ -129,14 +137,14 @@ virtual void GetAsync(const std::string& uri, - const Headers& headers, + const HttpHeaders& headers, Orthanc::IDynamicObject* payload /* takes ownership */, MessageHandler* successCallback, MessageHandler* failureCallback = NULL, unsigned int timeoutInSeconds = 60) = 0; virtual void PostAsync(const std::string& uri, - const Headers& headers, + const HttpHeaders& headers, const std::string& body, Orthanc::IDynamicObject* payload /* takes ownership */, MessageHandler* successCallback, @@ -144,7 +152,7 @@ unsigned int timeoutInSeconds = 60) = 0; virtual void DeleteAsync(const std::string& uri, - const Headers& headers, + const HttpHeaders& headers, Orthanc::IDynamicObject* payload /* takes ownership */, MessageHandler* successCallback, MessageHandler* failureCallback = NULL, diff -r c0589c3173fd -r aee3d7941c9b Framework/Toolbox/OrthancApiClient.cpp --- a/Framework/Toolbox/OrthancApiClient.cpp Tue Nov 13 10:36:53 2018 +0100 +++ b/Framework/Toolbox/OrthancApiClient.cpp Thu Nov 15 17:28:15 2018 +0100 @@ -168,10 +168,12 @@ OrthancApiClient::OrthancApiClient(MessageBroker& broker, - IWebService& orthanc) : + IWebService& web, + const std::string& baseUrl) : IObservable(broker), IObserver(broker), - orthanc_(orthanc) + web_(web), + baseUrl_(baseUrl) { } @@ -182,12 +184,13 @@ MessageHandler* failureCallback, Orthanc::IDynamicObject* payload) { - orthanc_.GetAsync(uri, IWebService::Headers(), - new WebServicePayload(successCallback, failureCallback, payload), - new Callable - (*this, &OrthancApiClient::NotifyHttpSuccess), - new Callable - (*this, &OrthancApiClient::NotifyHttpError)); + web_.GetAsync(baseUrl_ + uri, + IWebService::HttpHeaders(), + new WebServicePayload(successCallback, failureCallback, payload), + new Callable + (*this, &OrthancApiClient::NotifyHttpSuccess), + new Callable + (*this, &OrthancApiClient::NotifyHttpError)); } @@ -198,7 +201,7 @@ MessageHandler* failureCallback, Orthanc::IDynamicObject* payload) { - IWebService::Headers headers; + IWebService::HttpHeaders headers; headers["Accept"] = contentType; GetBinaryAsync(uri, headers, successCallback, failureCallback, payload); } @@ -206,17 +209,17 @@ void OrthancApiClient::GetBinaryAsync( const std::string& uri, - const IWebService::Headers& headers, + const IWebService::HttpHeaders& headers, MessageHandler* successCallback, MessageHandler* failureCallback, Orthanc::IDynamicObject* payload) { - orthanc_.GetAsync(uri, headers, - new WebServicePayload(successCallback, failureCallback, payload), - new Callable - (*this, &OrthancApiClient::NotifyHttpSuccess), - new Callable - (*this, &OrthancApiClient::NotifyHttpError)); + web_.GetAsync(baseUrl_ + uri, headers, + new WebServicePayload(successCallback, failureCallback, payload), + new Callable + (*this, &OrthancApiClient::NotifyHttpSuccess), + new Callable + (*this, &OrthancApiClient::NotifyHttpError)); } @@ -227,12 +230,12 @@ MessageHandler* failureCallback, Orthanc::IDynamicObject* payload) { - orthanc_.PostAsync(uri, IWebService::Headers(), body, - new WebServicePayload(successCallback, failureCallback, payload), - new Callable - (*this, &OrthancApiClient::NotifyHttpSuccess), - new Callable - (*this, &OrthancApiClient::NotifyHttpError)); + web_.PostAsync(baseUrl_ + uri, IWebService::HttpHeaders(), body, + new WebServicePayload(successCallback, failureCallback, payload), + new Callable + (*this, &OrthancApiClient::NotifyHttpSuccess), + new Callable + (*this, &OrthancApiClient::NotifyHttpError)); } @@ -256,12 +259,12 @@ MessageHandler* failureCallback, Orthanc::IDynamicObject* payload) { - orthanc_.DeleteAsync(uri, IWebService::Headers(), - new WebServicePayload(successCallback, failureCallback, payload), - new Callable - (*this, &OrthancApiClient::NotifyHttpSuccess), - new Callable - (*this, &OrthancApiClient::NotifyHttpError)); + web_.DeleteAsync(baseUrl_ + uri, IWebService::HttpHeaders(), + new WebServicePayload(successCallback, failureCallback, payload), + new Callable + (*this, &OrthancApiClient::NotifyHttpSuccess), + new Callable + (*this, &OrthancApiClient::NotifyHttpError)); } diff -r c0589c3173fd -r aee3d7941c9b Framework/Toolbox/OrthancApiClient.h --- a/Framework/Toolbox/OrthancApiClient.h Tue Nov 13 10:36:53 2018 +0100 +++ b/Framework/Toolbox/OrthancApiClient.h Thu Nov 15 17:28:15 2018 +0100 @@ -150,13 +150,14 @@ private: class WebServicePayload; - protected: - IWebService& orthanc_; + IWebService& web_; + std::string baseUrl_; public: OrthancApiClient(MessageBroker& broker, - IWebService& orthanc); + IWebService& web, + const std::string& baseUrl); virtual ~OrthancApiClient() { @@ -177,7 +178,7 @@ // schedule a GET request expecting a binary response. void GetBinaryAsync(const std::string& uri, - const IWebService::Headers& headers, + const IWebService::HttpHeaders& headers, MessageHandler* successCallback, MessageHandler* failureCallback = NULL, Orthanc::IDynamicObject* payload = NULL /* takes ownership */); diff -r c0589c3173fd -r aee3d7941c9b Framework/Toolbox/OrthancSlicesLoader.cpp --- a/Framework/Toolbox/OrthancSlicesLoader.cpp Tue Nov 13 10:36:53 2018 +0100 +++ b/Framework/Toolbox/OrthancSlicesLoader.cpp Thu Nov 15 17:28:15 2018 +0100 @@ -879,7 +879,7 @@ { std::string uri = ("/instances/" + slice.GetOrthancInstanceId() + "/frames/" + boost::lexical_cast(slice.GetFrame()) + "/raw.gz"); - orthanc_.GetBinaryAsync(uri, IWebService::Headers(), + orthanc_.GetBinaryAsync(uri, IWebService::HttpHeaders(), new Callable(*this, &OrthancSlicesLoader::ParseSliceRawImage), new Callable(*this, &OrthancSlicesLoader::OnSliceImageError), Operation::DownloadSliceRawImage(index, slice)); diff -r c0589c3173fd -r aee3d7941c9b Platforms/Generic/OracleWebService.h --- a/Platforms/Generic/OracleWebService.h Tue Nov 13 10:36:53 2018 +0100 +++ b/Platforms/Generic/OracleWebService.h Thu Nov 15 17:28:15 2018 +0100 @@ -53,7 +53,7 @@ } virtual void GetAsync(const std::string& uri, - const Headers& headers, + const HttpHeaders& headers, Orthanc::IDynamicObject* payload, // takes ownership MessageHandler* successCallback, // takes ownership MessageHandler* failureCallback = NULL,// takes ownership @@ -63,7 +63,7 @@ } virtual void PostAsync(const std::string& uri, - const Headers& headers, + const HttpHeaders& headers, const std::string& body, Orthanc::IDynamicObject* payload, // takes ownership MessageHandler* successCallback, // takes ownership @@ -74,7 +74,7 @@ } virtual void DeleteAsync(const std::string& uri, - const Headers& headers, + const HttpHeaders& headers, Orthanc::IDynamicObject* payload, MessageHandler* successCallback, MessageHandler* failureCallback = NULL, diff -r c0589c3173fd -r aee3d7941c9b Platforms/Generic/WebServiceCommandBase.cpp --- a/Platforms/Generic/WebServiceCommandBase.cpp Tue Nov 13 10:36:53 2018 +0100 +++ b/Platforms/Generic/WebServiceCommandBase.cpp Thu Nov 15 17:28:15 2018 +0100 @@ -29,8 +29,8 @@ MessageHandler* successCallback, MessageHandler* failureCallback, const Orthanc::WebServiceParameters& parameters, - const std::string& uri, - const IWebService::Headers& headers, + const std::string& url, + const IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, Orthanc::IDynamicObject* payload /* takes ownership */, NativeStoneApplicationContext& context) : @@ -38,7 +38,7 @@ successCallback_(successCallback), failureCallback_(failureCallback), parameters_(parameters), - uri_(uri), + url_(url), headers_(headers), payload_(payload), context_(context), @@ -56,12 +56,13 @@ if (success_ && successCallback_.get() != NULL) { - IWebService::HttpRequestSuccessMessage message(uri_, answer_.c_str(), answer_.size(), payload_.get()); + IWebService::HttpRequestSuccessMessage message + (url_, answer_.c_str(), answer_.size(), answerHeaders_, payload_.get()); successCallback_->Apply(message); } else if (!success_ && failureCallback_.get() != NULL) { - IWebService::HttpRequestErrorMessage message(uri_, payload_.get()); + IWebService::HttpRequestErrorMessage message(url_, payload_.get()); failureCallback_->Apply(message); } } diff -r c0589c3173fd -r aee3d7941c9b Platforms/Generic/WebServiceCommandBase.h --- a/Platforms/Generic/WebServiceCommandBase.h Tue Nov 13 10:36:53 2018 +0100 +++ b/Platforms/Generic/WebServiceCommandBase.h Thu Nov 15 17:28:15 2018 +0100 @@ -40,11 +40,12 @@ std::auto_ptr > successCallback_; std::auto_ptr > failureCallback_; Orthanc::WebServiceParameters parameters_; - std::string uri_; - std::map headers_; + std::string url_; + IWebService::HttpHeaders headers_; std::auto_ptr payload_; bool success_; std::string answer_; + IWebService::HttpHeaders answerHeaders_; NativeStoneApplicationContext& context_; unsigned int timeoutInSeconds_; @@ -53,8 +54,8 @@ MessageHandler* successCallback, // takes ownership MessageHandler* failureCallback, // takes ownership const Orthanc::WebServiceParameters& parameters, - const std::string& uri, - const std::map& headers, + const std::string& url, + const IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, Orthanc::IDynamicObject* payload /* takes ownership */, NativeStoneApplicationContext& context diff -r c0589c3173fd -r aee3d7941c9b Platforms/Generic/WebServiceDeleteCommand.cpp --- a/Platforms/Generic/WebServiceDeleteCommand.cpp Tue Nov 13 10:36:53 2018 +0100 +++ b/Platforms/Generic/WebServiceDeleteCommand.cpp Thu Nov 15 17:28:15 2018 +0100 @@ -29,27 +29,28 @@ MessageHandler* successCallback, // takes ownership MessageHandler* failureCallback, // takes ownership const Orthanc::WebServiceParameters& parameters, - const std::string& uri, - const IWebService::Headers& headers, + const std::string& url, + const IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, Orthanc::IDynamicObject* payload /* takes ownership */, NativeStoneApplicationContext& context) : - WebServiceCommandBase(broker, successCallback, failureCallback, parameters, uri, headers, timeoutInSeconds, payload, context) + WebServiceCommandBase(broker, successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context) { } void WebServiceDeleteCommand::Execute() { - Orthanc::HttpClient client(parameters_, uri_); + Orthanc::HttpClient client(parameters_, "/"); + client.SetUrl(url_); client.SetTimeout(timeoutInSeconds_); client.SetMethod(Orthanc::HttpMethod_Delete); - for (IWebService::Headers::const_iterator it = headers_.begin(); it != headers_.end(); it++ ) + for (IWebService::HttpHeaders::const_iterator it = headers_.begin(); it != headers_.end(); it++ ) { client.AddHeader(it->first, it->second); } - success_ = client.Apply(answer_); + success_ = client.Apply(answer_, answerHeaders_); } } diff -r c0589c3173fd -r aee3d7941c9b Platforms/Generic/WebServiceDeleteCommand.h --- a/Platforms/Generic/WebServiceDeleteCommand.h Tue Nov 13 10:36:53 2018 +0100 +++ b/Platforms/Generic/WebServiceDeleteCommand.h Thu Nov 15 17:28:15 2018 +0100 @@ -32,8 +32,8 @@ MessageHandler* successCallback, // takes ownership MessageHandler* failureCallback, // takes ownership const Orthanc::WebServiceParameters& parameters, - const std::string& uri, - const IWebService::Headers& headers, + const std::string& url, + const IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, Orthanc::IDynamicObject* payload /* takes ownership */, NativeStoneApplicationContext& context); diff -r c0589c3173fd -r aee3d7941c9b Platforms/Generic/WebServiceGetCommand.cpp --- a/Platforms/Generic/WebServiceGetCommand.cpp Tue Nov 13 10:36:53 2018 +0100 +++ b/Platforms/Generic/WebServiceGetCommand.cpp Thu Nov 15 17:28:15 2018 +0100 @@ -30,28 +30,29 @@ MessageHandler* successCallback, // takes ownership MessageHandler* failureCallback, // takes ownership const Orthanc::WebServiceParameters& parameters, - const std::string& uri, - const IWebService::Headers& headers, + const std::string& url, + const IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, Orthanc::IDynamicObject* payload /* takes ownership */, NativeStoneApplicationContext& context) : - WebServiceCommandBase(broker, successCallback, failureCallback, parameters, uri, headers, timeoutInSeconds, payload, context) + WebServiceCommandBase(broker, successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context) { } void WebServiceGetCommand::Execute() { - Orthanc::HttpClient client(parameters_, uri_); + Orthanc::HttpClient client(parameters_, "/"); + client.SetUrl(url_); client.SetTimeout(timeoutInSeconds_); client.SetMethod(Orthanc::HttpMethod_Get); - for (IWebService::Headers::const_iterator it = headers_.begin(); it != headers_.end(); it++ ) + for (IWebService::HttpHeaders::const_iterator it = headers_.begin(); it != headers_.end(); it++ ) { client.AddHeader(it->first, it->second); } - success_ = client.Apply(answer_); + success_ = client.Apply(answer_, answerHeaders_); } } diff -r c0589c3173fd -r aee3d7941c9b Platforms/Generic/WebServiceGetCommand.h --- a/Platforms/Generic/WebServiceGetCommand.h Tue Nov 13 10:36:53 2018 +0100 +++ b/Platforms/Generic/WebServiceGetCommand.h Thu Nov 15 17:28:15 2018 +0100 @@ -32,8 +32,8 @@ MessageHandler* successCallback, // takes ownership MessageHandler* failureCallback, // takes ownership const Orthanc::WebServiceParameters& parameters, - const std::string& uri, - const IWebService::Headers& headers, + const std::string& url, + const IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, Orthanc::IDynamicObject* payload /* takes ownership */, NativeStoneApplicationContext& context); diff -r c0589c3173fd -r aee3d7941c9b Platforms/Generic/WebServicePostCommand.cpp --- a/Platforms/Generic/WebServicePostCommand.cpp Tue Nov 13 10:36:53 2018 +0100 +++ b/Platforms/Generic/WebServicePostCommand.cpp Thu Nov 15 17:28:15 2018 +0100 @@ -29,30 +29,30 @@ MessageHandler* successCallback, // takes ownership MessageHandler* failureCallback, // takes ownership const Orthanc::WebServiceParameters& parameters, - const std::string& uri, - const IWebService::Headers& headers, + const std::string& url, + const IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, const std::string& body, Orthanc::IDynamicObject* payload /* takes ownership */, NativeStoneApplicationContext& context) : - WebServiceCommandBase(broker, successCallback, failureCallback, parameters, uri, headers, timeoutInSeconds, payload, context), + WebServiceCommandBase(broker, successCallback, failureCallback, parameters, url, headers, timeoutInSeconds, payload, context), body_(body) { } void WebServicePostCommand::Execute() { - Orthanc::HttpClient client(parameters_, uri_); + Orthanc::HttpClient client(parameters_, "/"); + client.SetUrl(url_); client.SetTimeout(timeoutInSeconds_); client.SetMethod(Orthanc::HttpMethod_Post); client.GetBody().swap(body_); - for (IWebService::Headers::const_iterator it = headers_.begin(); it != headers_.end(); it++ ) + for (IWebService::HttpHeaders::const_iterator it = headers_.begin(); it != headers_.end(); it++ ) { client.AddHeader(it->first, it->second); } - success_ = client.Apply(answer_); + success_ = client.Apply(answer_, answerHeaders_); } - } diff -r c0589c3173fd -r aee3d7941c9b Platforms/Generic/WebServicePostCommand.h --- a/Platforms/Generic/WebServicePostCommand.h Tue Nov 13 10:36:53 2018 +0100 +++ b/Platforms/Generic/WebServicePostCommand.h Thu Nov 15 17:28:15 2018 +0100 @@ -28,15 +28,15 @@ class WebServicePostCommand : public WebServiceCommandBase { protected: - std::string body_; + std::string body_; public: WebServicePostCommand(MessageBroker& broker, MessageHandler* successCallback, // takes ownership MessageHandler* failureCallback, // takes ownership const Orthanc::WebServiceParameters& parameters, - const std::string& uri, - const IWebService::Headers& headers, + const std::string& url, + const IWebService::HttpHeaders& headers, unsigned int timeoutInSeconds, const std::string& body, Orthanc::IDynamicObject* payload /* takes ownership */, diff -r c0589c3173fd -r aee3d7941c9b Platforms/Wasm/Defaults.cpp --- a/Platforms/Wasm/Defaults.cpp Tue Nov 13 10:36:53 2018 +0100 +++ b/Platforms/Wasm/Defaults.cpp Thu Nov 15 17:28:15 2018 +0100 @@ -93,7 +93,7 @@ startupParametersBuilder.GetStartupParameters(parameters, options); context.reset(new OrthancStone::StoneApplicationContext()); - context->SetWebService(OrthancStone::WasmWebService::GetInstance()); + context->Initialize(broker, OrthancStone::WasmWebService::GetInstance(), ""); application->Initialize(context.get(), statusBar_, parameters); application->InitializeWasm(); diff -r c0589c3173fd -r aee3d7941c9b Platforms/Wasm/WasmWebService.cpp --- a/Platforms/Wasm/WasmWebService.cpp Tue Nov 13 10:36:53 2018 +0100 +++ b/Platforms/Wasm/WasmWebService.cpp Thu Nov 15 17:28:15 2018 +0100 @@ -49,6 +49,7 @@ const char* uri, const void* body, size_t bodySize, + const char* answerHeaders, void* payload) { if (successCallable == NULL) @@ -57,9 +58,15 @@ } else { + OrthancStone::IWebService::HttpHeaders headers; + + // TODO - Parse "answerHeaders" + printf("[%s]\n", answerHeaders); + reinterpret_cast*>(successCallable)-> - Apply(OrthancStone::IWebService::HttpRequestSuccessMessage(uri, body, bodySize, reinterpret_cast(payload))); - } + Apply(OrthancStone::IWebService::HttpRequestSuccessMessage(uri, body, bodySize, headers, + reinterpret_cast(payload))); + } } void EMSCRIPTEN_KEEPALIVE WasmWebService_SetBaseUri(const char* baseUri) @@ -91,10 +98,10 @@ } } - void ToJsonString(std::string& output, const IWebService::Headers& headers) + void ToJsonString(std::string& output, const IWebService::HttpHeaders& headers) { Json::Value jsonHeaders; - for (IWebService::Headers::const_iterator it = headers.begin(); it != headers.end(); it++ ) + for (IWebService::HttpHeaders::const_iterator it = headers.begin(); it != headers.end(); it++ ) { jsonHeaders[it->first] = it->second; } @@ -108,7 +115,7 @@ } void WasmWebService::PostAsync(const std::string& relativeUri, - const Headers& headers, + const HttpHeaders& headers, const std::string& body, Orthanc::IDynamicObject* payload, MessageHandler* successCallable, @@ -119,11 +126,11 @@ std::string headersInJsonString; ToJsonString(headersInJsonString, headers); WasmWebService_PostAsync(successCallable, failureCallable, uri.c_str(), headersInJsonString.c_str(), - body.c_str(), body.size(), payload, timeoutInSeconds); + body.c_str(), body.size(), payload, timeoutInSeconds); } void WasmWebService::DeleteAsync(const std::string& relativeUri, - const Headers& headers, + const HttpHeaders& headers, Orthanc::IDynamicObject* payload, MessageHandler* successCallable, MessageHandler* failureCallable, @@ -137,16 +144,15 @@ } void WasmWebService::GetAsync(const std::string& relativeUri, - const Headers& headers, - Orthanc::IDynamicObject* payload, - MessageHandler* successCallable, - MessageHandler* failureCallable, - unsigned int timeoutInSeconds) + const HttpHeaders& headers, + Orthanc::IDynamicObject* payload, + MessageHandler* successCallable, + MessageHandler* failureCallable, + unsigned int timeoutInSeconds) { std::string uri = baseUri_ + relativeUri; std::string headersInJsonString; ToJsonString(headersInJsonString, headers); WasmWebService_GetAsync(successCallable, failureCallable, uri.c_str(), headersInJsonString.c_str(), payload, timeoutInSeconds); } - } diff -r c0589c3173fd -r aee3d7941c9b Platforms/Wasm/WasmWebService.h --- a/Platforms/Wasm/WasmWebService.h Tue Nov 13 10:36:53 2018 +0100 +++ b/Platforms/Wasm/WasmWebService.h Thu Nov 15 17:28:15 2018 +0100 @@ -38,14 +38,14 @@ void SetBaseUri(const std::string baseUri); virtual void GetAsync(const std::string& uri, - const Headers& headers, + const HttpHeaders& headers, Orthanc::IDynamicObject* payload, MessageHandler* successCallable, MessageHandler* failureCallable = NULL, unsigned int timeoutInSeconds = 60); virtual void PostAsync(const std::string& uri, - const Headers& headers, + const HttpHeaders& headers, const std::string& body, Orthanc::IDynamicObject* payload, MessageHandler* successCallable, @@ -53,7 +53,7 @@ unsigned int timeoutInSeconds = 60); virtual void DeleteAsync(const std::string& uri, - const Headers& headers, + const HttpHeaders& headers, Orthanc::IDynamicObject* payload, MessageHandler* successCallable, MessageHandler* failureCallable = NULL, diff -r c0589c3173fd -r aee3d7941c9b Platforms/Wasm/WasmWebService.js --- a/Platforms/Wasm/WasmWebService.js Tue Nov 13 10:36:53 2018 +0100 +++ b/Platforms/Wasm/WasmWebService.js Thu Nov 15 17:28:15 2018 +0100 @@ -17,11 +17,15 @@ xhr.onreadystatechange = function() { if (this.readyState == XMLHttpRequest.DONE) { if (xhr.status === 200) { + var s = xhr.getAllResponseHeaders(); + var headers = _malloc(s.length + 1); + writeStringToMemory(s, headers); + // TODO - Is "new Uint8Array()" necessary? This copies the // answer to the WebAssembly stack, hence necessitating // increasing the TOTAL_STACK parameter of Emscripten WasmWebService_NotifySuccess(callableSuccess, url_, new Uint8Array(this.response), - this.response.byteLength, payload); + this.response.byteLength, headers, payload); } else { WasmWebService_NotifyError(callableFailure, url_, payload); } @@ -48,8 +52,12 @@ xhr.onreadystatechange = function() { if (this.readyState == XMLHttpRequest.DONE) { if (xhr.status === 200) { + var s = xhr.getAllResponseHeaders(); + var headers = _malloc(s.length + 1); + writeStringToMemory(s, headers); + WasmWebService_NotifySuccess(callableSuccess, url_, new Uint8Array(this.response), - this.response.byteLength, payload); + this.response.byteLength, headers, payload); } else { WasmWebService_NotifyError(callableFailure, url_, payload); } @@ -76,8 +84,12 @@ xhr.onreadystatechange = function() { if (this.readyState == XMLHttpRequest.DONE) { if (xhr.status === 200) { + var s = xhr.getAllResponseHeaders(); + var headers = _malloc(s.length + 1); + writeStringToMemory(s, headers); + WasmWebService_NotifySuccess(callableSuccess, url_, new Uint8Array(this.response), - this.response.byteLength, payload); + this.response.byteLength, headers, payload); } else { WasmWebService_NotifyError(callableFailure, url_, payload); }