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
}
}
ObjectScriptObjectScript
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>
}
ObjectScriptObjectScript
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:
{
<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. 👁️👁️🛠️🔍👁️👁️
Again thanks for your time reading and answering this question, that could be repeated, however I think it is needed. Thanks:
Hi Yone! Your patientId is a param of the URL, you don't need to include it into the router map, to get the value you only need
set patid = %request.Get("patientid")
Try this.png)
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:
However, unfortunately, it only shows the logs before:
So then, if we observe the logs it shows us:
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?
Hi Yone! You can follow step by step the following article to create a REST web service from scratch:
https://community.intersystems.com/post/creating-rest-service-iris
As you can see this web service is not a Business Service, it's a web application that invoke a Business Service, I suggest you to use that way.
HI,
I tried another way of writing, maybe it's what you need
Thanks @Shanshan Yu
It worked fine.
The line which you have written does it take the Query Parameter as needed and as exepected:
set pPatientId = pInput.Attributes("Params","patientId",1)
Thanks for your help.
💡 This question is considered a Key Question. More details here.