Mercurial > hg > orthanc
changeset 4416:0b27841950d5
openapi about creation of zip/media archives
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 28 Dec 2020 16:49:17 +0100 |
parents | b50410d0e98c |
children | a4518adede59 |
files | OrthancServer/Sources/OrthancRestApi/OrthancRestArchive.cpp OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp |
diffstat | 2 files changed, 139 insertions(+), 36 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestArchive.cpp Mon Dec 28 15:32:01 2020 +0100 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestArchive.cpp Mon Dec 28 16:49:17 2020 +0100 @@ -194,11 +194,56 @@ } } + + static void DocumentPostArguments(RestApiPostCall& call, + bool isMedia, + bool defaultExtended) + { + call.GetDocumentation() + .SetRequestField("Synchronous", RestApiCallDocumentation::Type_Boolean, + "If `true`, create the archive in synchronous mode, which means that the HTTP answer will directly " + "contain the ZIP file. This is the default, easy behavior, but it is *not* be desirable to archive " + "large amount of data, as it might lead to network timeouts.", false) + .SetRequestField("Asynchronous", RestApiCallDocumentation::Type_Boolean, + "If `true`, create the archive in asynchronous mode, which means that a job is submitted to create " + "the archive in background. Prefer this flavor wherever possible.", false) + .SetRequestField(KEY_TRANSCODE, RestApiCallDocumentation::Type_String, + "If present, the DICOM files in the archive will be transcoded to the provided " + "transfer syntax: https://book.orthanc-server.com/faq/transcoding.html", false) + .SetRequestField("Priority", RestApiCallDocumentation::Type_Number, + "In asynchronous mode, the priority of the job. The lower the value, the higher the priority.", false) + .AddAnswerType(MimeType_Zip, "In synchronous mode, the ZIP file containing the archive") + .AddAnswerType(MimeType_Json, "In asynchronous mode, information about the job that has been submitted to " + "generate the archive: https://book.orthanc-server.com/users/advanced-rest.html#jobs"); + + if (isMedia) + { + call.GetDocumentation().SetRequestField( + KEY_EXTENDED, RestApiCallDocumentation::Type_Boolean, "If `true`, will include additional " + "tags such as `SeriesDescription`, leading to a so-called *extended DICOMDIR*. Default value is " + + std::string(defaultExtended ? "`true`" : "`false`") + ".", false); + } + } + template <bool IS_MEDIA, bool DEFAULT_IS_EXTENDED /* only makes sense for media (i.e. not ZIP archives) */ > static void CreateBatch(RestApiPostCall& call) { + if (call.IsDocumentation()) + { + DocumentPostArguments(call, IS_MEDIA, DEFAULT_IS_EXTENDED); + std::string m = (IS_MEDIA ? "DICOMDIR media" : "ZIP archive"); + call.GetDocumentation() + .SetTag("System") + .SetSummary("Create " + m) + .SetDescription("Create a " + m + " containing the DICOM resources (patients, studies, series, or instances) " + "whose Orthanc identifiers are provided in the body") + .SetRequestField("Resources", RestApiCallDocumentation::Type_JsonListOfStrings, + "The list of Orthanc identifiers of interest.", false); + return; + } + ServerContext& context = OrthancRestApi::GetContext(call); Json::Value body; @@ -228,10 +273,35 @@ } - template <bool IS_MEDIA, - bool DEFAULT_IS_EXTENDED /* only makes sense for media (i.e. not ZIP archives) */ > + template <bool IS_MEDIA> static void CreateSingleGet(RestApiGetCall& call) { + if (call.IsDocumentation()) + { + ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); + std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); + std::string m = (IS_MEDIA ? "DICOMDIR media" : "ZIP archive"); + call.GetDocumentation() + .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) + .SetSummary("Create " + m) + .SetDescription("Synchronously create a " + m + " containing the DICOM " + r + + " whose Orthanc identifier is provided in the URL. This flavor is synchronous, " + "which might *not* be desirable to archive large amount of data, as it might " + "lead to network timeouts. Prefer the asynchronous version using `POST` method.") + .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") + .SetHttpGetArgument("transcode", RestApiCallDocumentation::Type_String, + "If present, the DICOM files in the archive will be transcoded to the provided " + "transfer syntax: https://book.orthanc-server.com/faq/transcoding.html", false) + .AddAnswerType(MimeType_Zip, "ZIP file containing the archive"); + if (IS_MEDIA) + { + call.GetDocumentation().SetHttpGetArgument( + "extended", RestApiCallDocumentation::Type_String, + "If present, will include additional tags such as `SeriesDescription`, leading to a so-called *extended DICOMDIR*", false); + } + return; + } + ServerContext& context = OrthancRestApi::GetContext(call); std::string id = call.GetUriComponent("id", ""); @@ -260,10 +330,24 @@ } - template <bool IS_MEDIA, - bool DEFAULT_IS_EXTENDED /* only makes sense for media (i.e. not ZIP archives) */ > + template <bool IS_MEDIA> static void CreateSinglePost(RestApiPostCall& call) { + if (call.IsDocumentation()) + { + DocumentPostArguments(call, IS_MEDIA, false /* not extended by default */); + ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); + std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); + std::string m = (IS_MEDIA ? "DICOMDIR media" : "ZIP archive"); + call.GetDocumentation() + .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) + .SetSummary("Create " + m) + .SetDescription("Create a " + m + " containing the DICOM " + r + + " whose Orthanc identifier is provided in the URL") + .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest"); + return; + } + ServerContext& context = OrthancRestApi::GetContext(call); std::string id = call.GetUriComponent("id", ""); @@ -275,7 +359,7 @@ DicomTransferSyntax transferSyntax; int priority; GetJobParameters(synchronous, extended, transcode, transferSyntax, - priority, body, DEFAULT_IS_EXTENDED); + priority, body, false /* by default, not extented */); std::unique_ptr<ArchiveJob> job(new ArchiveJob(context, IS_MEDIA, extended)); job->AddResource(id); @@ -296,33 +380,18 @@ void OrthancRestApi::RegisterArchive() { - Register("/patients/{id}/archive", - CreateSingleGet<false /* ZIP */, false /* extended makes no sense in ZIP */>); - Register("/studies/{id}/archive", - CreateSingleGet<false /* ZIP */, false /* extended makes no sense in ZIP */>); - Register("/series/{id}/archive", - CreateSingleGet<false /* ZIP */, false /* extended makes no sense in ZIP */>); - - Register("/patients/{id}/archive", - CreateSinglePost<false /* ZIP */, false /* extended makes no sense in ZIP */>); - Register("/studies/{id}/archive", - CreateSinglePost<false /* ZIP */, false /* extended makes no sense in ZIP */>); - Register("/series/{id}/archive", - CreateSinglePost<false /* ZIP */, false /* extended makes no sense in ZIP */>); - - Register("/patients/{id}/media", - CreateSingleGet<true /* media */, false /* not extended by default */>); - Register("/studies/{id}/media", - CreateSingleGet<true /* media */, false /* not extended by default */>); - Register("/series/{id}/media", - CreateSingleGet<true /* media */, false /* not extended by default */>); - - Register("/patients/{id}/media", - CreateSinglePost<true /* media */, false /* not extended by default */>); - Register("/studies/{id}/media", - CreateSinglePost<true /* media */, false /* not extended by default */>); - Register("/series/{id}/media", - CreateSinglePost<true /* media */, false /* not extended by default */>); + Register("/patients/{id}/archive", CreateSingleGet<false /* ZIP */>); + Register("/patients/{id}/archive", CreateSinglePost<false /* ZIP */>); + Register("/patients/{id}/media", CreateSingleGet<true /* media */>); + Register("/patients/{id}/media", CreateSinglePost<true /* media */>); + Register("/series/{id}/archive", CreateSingleGet<false /* ZIP */>); + Register("/series/{id}/archive", CreateSinglePost<false /* ZIP */>); + Register("/series/{id}/media", CreateSingleGet<true /* media */>); + Register("/series/{id}/media", CreateSinglePost<true /* media */>); + Register("/studies/{id}/archive", CreateSingleGet<false /* ZIP */>); + Register("/studies/{id}/archive", CreateSinglePost<false /* ZIP */>); + Register("/studies/{id}/media", CreateSingleGet<true /* media */>); + Register("/studies/{id}/media", CreateSinglePost<true /* media */>); Register("/tools/create-archive", CreateBatch<false /* ZIP */, false /* extended makes no sense in ZIP */>);
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Mon Dec 28 15:32:01 2020 +0100 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Mon Dec 28 16:49:17 2020 +0100 @@ -249,7 +249,7 @@ call.GetDocumentation() .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */)) .SetSummary("Get information about some " + resource) - .SetDescription("Get detailed information about the DICOM " + resource + " of interest whose Orthanc identifier is provided in the URL") + .SetDescription("Get detailed information about the DICOM " + resource + " whose Orthanc identifier is provided in the URL") .SetUriArgument("id", "Orthanc identifier of the " + resource + " of interest") .AddAnswerType(MimeType_Json, "Information about the DICOM " + resource) .SetHttpGetSample(GetDocumentationSampleResource(resourceType), true); @@ -272,7 +272,7 @@ call.GetDocumentation() .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */)) .SetSummary("Delete some " + resource) - .SetDescription("Delete the DICOM " + resource + " of interest whose Orthanc identifier is provided in the URL") + .SetDescription("Delete the DICOM " + resource + " whose Orthanc identifier is provided in the URL") .SetUriArgument("id", "Orthanc identifier of the " + resource + " of interest"); return; } @@ -435,6 +435,8 @@ .SetSummary("Get human-readable tags") .SetDescription("Get the DICOM tags in human-readable format") .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest") + .SetHttpGetArgument("ignore-length", RestApiCallDocumentation::Type_JsonListOfStrings, + "Also include the DICOM tags that are provided in this list, even if their associated value is long", false) .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value") .SetTruncatedJsonHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/simplified-tags", 10); return; @@ -2077,6 +2079,21 @@ static void GetSharedTags(RestApiGetCall& call) { + if (call.IsDocumentation()) + { + ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); + std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); + call.GetDocumentation() + .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) + .SetSummary("Get shared tags") + .SetDescription("Extract the DICOM tags whose value is constant across all the child instances of " + "the DICOM " + r + " whose Orthanc identifier is provided in the URL") + .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") + .AddAnswerType(MimeType_Json, "JSON object containing the values of the DICOM tags") + .SetTruncatedJsonHttpGetSample(GetDocumentationSampleResource(t) + "/shared-tags", 5); + return; + } + ServerContext& context = OrthancRestApi::GetContext(call); std::string publicId = call.GetUriComponent("id", ""); @@ -2385,7 +2402,7 @@ .SetTag(GetResourceTypeText(start, true /* plural */, true /* upper case */)) .SetSummary("Get child " + children) .SetDescription("Get detailed information about the child " + children + " of the DICOM " + - resource + " of interest whose Orthanc identifier is provided in the URL") + resource + " whose Orthanc identifier is provided in the URL") .SetUriArgument("id", "Orthanc identifier of the " + resource + " of interest") .AddAnswerType(MimeType_Json, "JSON array containing information about the child DICOM " + children) .SetTruncatedJsonHttpGetSample(GetDocumentationSampleResource(start) + "/" + children, 5); @@ -2434,6 +2451,23 @@ static void GetChildInstancesTags(RestApiGetCall& call) { + if (call.IsDocumentation()) + { + ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); + std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); + call.GetDocumentation() + .SetTag(GetResourceTypeText(t, true /* plural */, true /* upper case */)) + .SetSummary("Get tags of instances") + .SetDescription("Get the tags of all the child instances of the DICOM " + r + + " whose Orthanc identifier is provided in the URL") + .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest") + .SetHttpGetArgument("ignore-length", RestApiCallDocumentation::Type_JsonListOfStrings, + "Also include the DICOM tags that are provided in this list, even if their associated value is long", false) + .AddAnswerType(MimeType_Json, "JSON object associating the Orthanc identifiers of the instances, with the values of their DICOM tags") + .SetTruncatedJsonHttpGetSample(GetDocumentationSampleResource(t) + "/instances-tags", 5); + return; + } + ServerContext& context = OrthancRestApi::GetContext(call); std::string publicId = call.GetUriComponent("id", ""); DicomToJsonFormat format = GetDicomFormat(call); @@ -2486,7 +2520,7 @@ .SetTag(GetResourceTypeText(start, true /* plural */, true /* upper case */)) .SetSummary("Get parent " + parent) .SetDescription("Get detailed information about the parent " + parent + " of the DICOM " + - resource + " of interest whose Orthanc identifier is provided in the URL") + resource + " whose Orthanc identifier is provided in the URL") .SetUriArgument("id", "Orthanc identifier of the " + resource + " of interest") .AddAnswerType(MimeType_Json, "Information about the parent DICOM " + parent) .SetTruncatedJsonHttpGetSample(GetDocumentationSampleResource(start) + "/" + parent, 10);