# HG changeset patch # User Alain Mazy # Date 1704797417 -3600 # Node ID ab270400aae1e808f9ee7314fd9cc2aea27209d3 # Parent 34f30ddc0decd6fd671ca83a2f723d4108245ade python: overriding core API diff -r 34f30ddc0dec -r ab270400aae1 .hgignore --- a/.hgignore Mon Jan 08 13:39:15 2024 +0100 +++ b/.hgignore Tue Jan 09 11:50:17 2024 +0100 @@ -4,3 +4,4 @@ .vscode/ *~ *.orig +*.pyc \ No newline at end of file diff -r 34f30ddc0dec -r ab270400aae1 Sphinx/source/plugins/python.rst --- a/Sphinx/source/plugins/python.rst Mon Jan 08 13:39:15 2024 +0100 +++ b/Sphinx/source/plugins/python.rst Tue Jan 09 11:50:17 2024 +0100 @@ -281,6 +281,31 @@ ok +Overriding the core REST API +............................ + +You may also use a python plugin to replace an existing REST API route: + +.. literalinclude:: python/extending-rest-api-2.py + :language: python + + + +When calling the REST API from a python plugin, you may use e.g. +``RestApiPost`` to call the native Orthanc REST API and must +call ``RestApiPostAfterPlugin`` to call the REST API from plugins. + + +Note however, that, as of Orthanc 1.12.2, the Orthanc plugin SDK +does not support multiple plugins implementing the same route. +Orthanc will actually accept e.g a Python plugin that overrides +a DICOMWeb route but it is impossible to tell which route +will be called in the end since this depends on the registration +order of the plugins that is not deterministic. + + + + .. _python-changes: Listening to changes diff -r 34f30ddc0dec -r ab270400aae1 Sphinx/source/plugins/python/extending-rest-api-2.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sphinx/source/plugins/python/extending-rest-api-2.py Tue Jan 09 11:50:17 2024 +0100 @@ -0,0 +1,46 @@ +import orthanc +import pprint +import json + +# override the /instances POST route +def OnInstances(output, uri, **request): + + # for POST, replace the core API route by your own implementation + if request['method'] == 'POST': + orthanc.LogWarning('I have received an instance') + # implement your own logic here + output.AnswerBuffer(json.dumps({"MyAnswer": "Instance Ignored"}), "application/json") + else: + # for GET, simply forward the call to the core API. + # Note that you should not use RestApiGetAfterPlugins here since + # this would call the /instances route from this python plugin + # and end up in an infinite loop. + instances = orthanc.RestApiGet(uri) + output.AnswerBuffer(instances, "application/json") + +# reimplement a DICOMWeb /studies/../metadata route +def OnDicomWebStudiesMetadata(output, uri, **request): + + orthanc.LogWarning("My DICOMWEB /studies/../metadata") + + # since we are calling a route from a plugin, we must use RestApiGetAfterPlugins + metadata = json.loads(orthanc.RestApiGetAfterPlugins(uri.replace('/my-dicom-web/', '/dicom-web/'))) + + # transform the metadata (remove all tags from group 0009) + for m in metadata: + tags_to_remove = [k for k in m if k.startswith('0009')] + for k in tags_to_remove: + del m[k] + + output.AnswerBuffer(json.dumps(metadata), "application/json") + + +# override the /instances route from the core API +orthanc.RegisterRestCallback('/instances', OnInstances) + +# The code below should be avoided since you actually don't know which route will finally be called: +# the one from the DICOMWeb plugin or the one from this python plugin +# orthanc.RegisterRestCallback('/dicom-web/studies/(.*)/metadata', OnDicomWebStudiesMetadata) + +# Therefore, you should use another base route to differentiate it from the DICOMWeb plugin route +orthanc.RegisterRestCallback('/my-dicom-web/studies/(.*)/metadata', OnDicomWebStudiesMetadata)