Question
· Oct 10, 2023

How could we get Query Params inside a REST Service with HealthShare?

Hello,

First of all thanks for your time reading this post, and thanks for your help with your answers, thanks.

 

We have the following doubt: We need to create a REST Service in HealthShare, to process incoming calls with the following URL's format:

https://host:port/api/studies?patientId=11473564
 

To accomplish this task, we have previously read:

https://community.intersystems.com/post/advanced-url-mapping-rest

https://community.intersystems.com/post/how-do-i-process-querystring-par...

https://community.intersystems.com/post/how-get-param-passed-get-rest-query

 

And even more, we have read deeply, Eduard Lebedyuk's answer:

https://community.intersystems.com/post/rest-how-pass-query-parameters#c...

 

So then, we have written our code as follows:

/// 		Ahora se accede mediante: 
/// 		https://host:port/api/studies?patientId=XXXX111111111111 
/// 
Class Servicios.REST.DICOM.ConsultarEstudiosVNAv01r00 Extends (EnsLib.REST.Service, Ens.BusinessService)
{

Parameter ADAPTER = "EnsLib.HTTP.InboundAdapter";
// Parameter EnsServicePrefix = "/api";
Parameter EnsServicePrefix = "|/api";
XData UrlMap
{
<Routes>
<Route Url="/:studies" Method="GET" Call="consultarEstudiosDatosPaciente"/>
</Routes>
}

/// 		un JSON con el listado de estudios que tiene el paciente + los datos demográficos del paciente 
/// (nombre, sexo, f.nacimiento, etc...)
Method consultarEstudiosDatosPaciente(pInput As %Stream.Object, Output pOutput As %Stream.Object, pStudies As %String, pPatientId As %String) As %Status
{
	$$$LOGALERT("Entra en consultarEstudiosDatosPaciente")
	Set pOutput  = ##class(%GlobalBinaryStream).%New()
	set claseAux = ##class(%ZEN.Auxiliary.jsonProvider).%New()

	$$$LOGINFO("pStudies: "_pStudies)
	$$$LOGINFO("pPatientId: "_pPatientId)
	
	set objetoEntrada = ##class(Mensajes.Request.DICOM.consultarEstudiosDatosPacienteVNARequest).%New()
	
	set objetoEntrada.identificadorPaciente 	= pPatientId
	
	set tSC      = claseAux.%ConvertJSONToObject(.req,"Mensajes.Request.DICOM.consultarEstudiosDatosPacienteVNARequest",.objetoEntrada,1)
	
	set tSC = ..SendRequestSync("EnrutadorConsultarEstudiosVNAv01r00",objetoEntrada,.objetoSalida)
	
	set tSC = claseAux.%WriteJSONStreamFromObject(.pOutput,.objetoSalida,,,,"aeloqtuw")
	
	Do:$$$ISOK(tSC) pOutput.SetAttribute("Content-Type","application/json")
	do pOutput.SetAttribute("Access-Control-Allow-Origin","*")
	do pOutput.SetAttribute("Access-Control-Allow-Credentials","true")
	do pOutput.SetAttribute("Access-Control-Allow-Methods","GET")
    do pOutput.SetAttribute("Access-Control-Allow-Headers","request,Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers")
	Quit tSC
	
	Quit $$$OK
}

}

 

However, we do not understand why it does not work as expected. We observe that when we call from POSTMAN:

https://10.136.4.141:10102/api/studies?patientId=11473564
 

The Service's Event Log's shows us:

Tipo Hora Texto  Id.
Info 2023-10-10 16:32:34.557 Closing TCP Connection Job  3552246
Info 2023-10-10 16:32:34.557 Disconnecting from 10102<-XXX/SSL=ABC  3552245
Info 2023-10-10 16:32:34.555 pStudies: studies  3552244
Alert 2023-10-10 16:32:34.555 Entra en consultarEstudiosDatosPaciente

 

As you could read from the previously posted Logs, it does enters inside our consultarEstudiosDatosPaciente method, but it print "studies" and we would like to access "11473564" which is the value part from "https://10.136.4.141:10102/api/studies?patientId=11473564"

 

Furthermore, we have rewrite the code, in a way that we thought it could obtain our patientId's value as, just simply changing the XData as follows:

XData UrlMap
{
<Routes>
<Route Url="/:studies?:patientId" Method="GET" Call="consultarEstudiosDatosPaciente"/>
</Routes>
}

 

However, we observe the following Event's Log:

Info 2023-10-10 16:44:18.596 Closing TCP Connection Job  3552612
Info 2023-10-10 16:44:18.595 Disconnecting from 10102<-XXX:53233/SSL=ABC  3552611
Info 2023-10-10 16:44:18.595 pStudies: studies  3552610
Alert 2023-10-10 16:44:18.594 Entra en consultarEstudiosDatosPaciente  3552609

 

Why does it only output "studies"?

 

Thirdly, we have in addition tried to change the URL for:

XData UrlMap
{
<Routes>
<Route Url="/:studies:patientId" Method="GET" Call="consultarEstudiosDatosPaciente"/>
</Routes>
}

 

But it stills outputting the exact same Event Log:

Info 2023-10-10 16:47:44.676 Closing TCP Connection Job  3552743
Info 2023-10-10 16:47:44.675 Disconnecting from 10102<-XYZ:53333/SSL=ABC  3552742
Info 2023-10-10 16:47:44.674 pStudies: studies  3552741
Alert 2023-10-10 16:47:44.674 Entra en consultarEstudiosDatosPaciente  3552740

 

 

Why does it works as it works?

Why it does not show us patientId's value?

How could we fix it?

How could we improve it to be able to process https://host:port/api/studies?patientId=11473564
 

 

Again thanks for your help and time.

 

To summarize it: This post discusses creating a HealthShare REST service but encounters issues with extracting Query Parameter "patientId" from the URL in a GET REST method. We've tried various URL configurations and codes but we haven't succeeded. We seek advice on fixing and improving the service. 👁️👁️🛠️🔍👁️👁️

Product version: HealthShare 2020.1
$ZV: IRIS for UNIX (Red Hat Enterprise Linux for x86-64) 2020.1.1 (Build 408U) Sun Mar 21 2021 22:21:14 EDT
Discussion (9)2
Log in or sign up to continue

hello @Yone Moreno 

You don't need to include the query params in the Url. That's is basically available in %request CSP object. You can take the query parameter values like below. And :studies represents it's a dynamic URL parameter value.

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<Route Url="/:studies" Method="GET" Call="consultarEstudiosDatosPaciente"/>
</Routes>
}

ClassMethod consultarEstudiosDatosPaciente(studies As %String="") As %Status
{
    
    set patientId = %request.Get("patientId")
    /// or 
    set patientId = %request.Data("patientId", 1)
    return $$$OK
}

Thanks for your time and help.

I have tried you approach @Luis Angel Pérez Ramos and @Shanshan Yu and @Ashok Kumar 
, we have written the following code for our REST Service, following your advices and suggestions:

/// 		Ahora se accede mediante: 
/// 		https://host:port/api/studies?patientId=XXXX111111111111 
/// 
Class Servicios.REST.DICOM.ConsultarEstudiosVNAv01r00 Extends (%CSP.REST, EnsLib.REST.Service, Ens.BusinessService)
{

Parameter ADAPTER = "EnsLib.HTTP.InboundAdapter";

Parameter EnsServicePrefix = "|/api";

XData UrlMap
{
<Routes>
<Route Url="/:studies" Method="GET" Call="consultarEstudiosDatosPaciente"/>
</Routes>
}

/// 		un JSON con el listado de estudios que tiene el paciente + los datos demográficos del paciente 
/// (nombre, sexo, f.nacimiento, etc...)
Method consultarEstudiosDatosPaciente(pInput As %Stream.Object, Output pOutput As %Stream.Object, pStudies As %String) As %Status
{
	$$$LOGALERT("Entra en consultarEstudiosDatosPaciente")
	Set pOutput  = ##class(%GlobalBinaryStream).%New()
	set claseAux = ##class(%ZEN.Auxiliary.jsonProvider).%New()

	$$$LOGWARNING("Antes de pPatientId")
	set pPatientId = %request.Get("patientId")
	
	$$$LOGINFO("pStudies: "_pStudies)
	$$$LOGINFO("pPatientId: "_pPatientId)
	
	set objetoEntrada = ##class(Mensajes.Request.DICOM.consultarEstudiosDatosPacienteVNARequest).%New()
	
	set objetoEntrada.identificadorPaciente 	= pPatientId
	
	set tSC      = claseAux.%ConvertJSONToObject(.req,"Mensajes.Request.DICOM.consultarEstudiosDatosPacienteVNARequest",.objetoEntrada,1)
	
	set tSC = ..SendRequestSync("EnrutadorConsultarEstudiosVNAv01r00",objetoEntrada,.objetoSalida)
	
	set tSC = claseAux.%WriteJSONStreamFromObject(.pOutput,.objetoSalida,,,,"aeloqtuw")
	
	Do:$$$ISOK(tSC) pOutput.SetAttribute("Content-Type","application/json")
	do pOutput.SetAttribute("Access-Control-Allow-Origin","*")
	do pOutput.SetAttribute("Access-Control-Allow-Credentials","true")
	do pOutput.SetAttribute("Access-Control-Allow-Methods","GET")
    do pOutput.SetAttribute("Access-Control-Allow-Headers","request,Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers")
	Quit tSC
	
	Quit $$$OK
}

}


Where the important part is that we have written the XData UrlMap Route Url as you have written:
XData UrlMap { <Routes> <Route Url="/:studies" Method="GET" Call="consultarEstudiosDatosPaciente"/> </Routes> }
 

In addition we have also added to get the patientId from %request as:

set pPatientId = %request.Get("patientId")

However, unfortunately, it only shows the logs before:

set pPatientId = %request.Get("patientId")

So then, if we observe the logs it shows us:

Tipo Hora Texto  Id.
Info 2023-10-11 06:58:03.070 Closing TCP Connection Job  3577763
Info 2023-10-11 06:58:03.069 Disconnecting from 10102<-ABC:XYZ/SSL=CBA  3577762
Warning 2023-10-11 06:58:03.067 Antes de pPatientId  3577761
Alert 2023-10-11 06:58:03.066 Entra en consultarEstudiosDatosPaciente

Why it fails when tries to retrieve the patientId from %request object via the Get method?

Besides, we have added "%CSP.REST" in the extends' class list, because w ehave read that %request variable is a special one inside %CSP.REST, as it states in the documentation below:

https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls...

How could we really retrieve the patientId as query parameter?

How could we fix this issue?

Agan thanks for your time, help, and answers:

How could we debug and fix / improve this issue to get the Query Parameter as needed?