How can I pass multiple parameters to an Ensemble REST service and return an authorization token as a response JSON message

This question came on the Ensemble in Healthcare email list. It's a great question. I'm working on an answer, but am posting it here to get any other input. I'll also address the option of using %CSP.REST.

Hello everyone,

 

Using Intersystems Healthshare/Ensemble, I am trying to make a RESTful Interface between Android/iOS app and Cache database. I have some queries and I am unable to find where exactly I can get any resources on them.

 

1. By extending the EnsLib.REST.Service class, I have so far made some basic methods like if the interface receives and email ID via a GET request, it checks if its exists in the database and pulls out the password for the account. However, I want to know if we can send back some sort of authorization token or api key as part of the JSON response packet, as a way of notifying the user that his account is authenticated? Also, the key or token will be stored in the mobile cache and used for further calls from the app.

 

2.  Till now, to test the service I so far developed, I am calling the interface by a URL as follows - 

http://localhost:57772/myDemo/myService/myApp/UserAccounts/abc@gmail.com

But as you can see I am able to pass only one parameter (which is the email ID at last). I wanted to ask what if I have multiple parameters?

I guess I can restructure the URL something like this ->

http://localhost:57772/myDemo/myService/myApp/UserAccounts/:emailID/:password/:signInType/:socialNetID

But is there any alternative to this? For example, what if I want to receive a JSON request packet (which will have these parameters) and then parse it to extract these parameters and then call my service appropriately? Can this be done?

 

3. I want to provide this basic interface to the app developers, just for testing purposes. I want to know if there exists some kind of testing environment, so that I can share the URL with developers and they can make the calls to test it. The developers would be accessing the interface remotely (not from the same network which I am connected to).

 

Any help would be appreciated. Thanks!

  • + 2
  • 0
  • 6991
  • 7
  • 5

Answers

The above queries are from me. Let me know if any additional information is required.

Thanks Joshua for the support.

For your second question, you might find this post at Stack Overflow useful.

For query parameters you'd use the syntax <url>?param=value, e.g. 

/appName/customers?lastName=Slagman&gender=M

In your <route> the url would be: 

<Route Url="/customers" Method="GET" ...

And in your method you'd use:

Set lastName=%request.Get("lastName")

 

Hi Herman,

I tried to modify my code as per your suggestions. The URLinside route is set to /UserAccounts. But, it didn't work. I have added trace elements to check what I receive.

The _tEmailID element for which I used the %request.Get, it does not receive the parameter passed to it.

The Event log for service shows that _tEmailID is empty.

 Can you have a look at my method and suggest anything if I have missed? Is it required to add any library to use %request?

Method retrieveAccount(pInput As %Library.AbstractStream, Output pOutput As %Stream.Object) As %Status
{
set status = $$$OK
try{
  SET tEmailID = %request.Get("account")
  $$$TRACE("tEmaildID = "_tEmailID)
ZNSpace "INSTATEMPNS"
&sql(SELECT EmailID,Password INTO :email,:pwd FROM InstaTemp.ISAccounts WHERE EmailID = :tEmailID )

$$$TRACE("email = "_email)
set tProxy = ##class(%ZEN.proxyObject).%New()
  IF SQLCODE'=0
 
  set tProxy.Email = tEmailID
  set tProxy.Pwd = "no password"
  set tProxy.SqlCode = SQLCODE
       }
       ELSE 
       {  
    set tProxy.Email = email
  set tProxy.Pwd = pwd
  set tProxy.SqlCode = SQLCODE 
    }
 
  //set tProxy = ##class(%ZEN.proxyObject).%New()
  //set tProxy.Email = email
  //set tProxy.Pwd = pwd
 
  // You could just write the output manually or use helper methods like ..ObjectToJSONStream() to generate JSON
  do pOutput.SetAttribute("Content-Type","application/json")
  do pOutput.Write("[")
 
  Set tOut=##class(%IO.StringStream).%New()
  do ..ObjectToJSONStream(tProxy,.tOut)
 
  do tOut.Rewind()
  do pOutput.Write( tOut.Read() )
  do pOutput.Write("]"_$C(13,10))
 
catch (e) {
set status = e.AsStatus()
}
      quit status
}

I'm sorry, I missed the Ensemble part.
I was referring to the %CSP.REST class.
I don't know what version of Ensemble you use, but at least in 2015.1 it seems that the Enslib.REST.Service doesn't copy the %request.Data values (the query parameter values) into the attributes of the pInput stream.


But at least they should be available to you in the %request.Data array (accessible by %request.Get(var)), why that is the case in your situation I can't see, it has got nothing to do with your method, but somewhere 'upstream'.

Hi Herman,

I also tried SET tEmailID = $Get(%request.Data("account",1)). But even then, tEmailID comes up empty in the trace.

I am using HealthShare 2015.2.1

Any ideas?

I'm afraid this will have to be a WRC call: how to get to query parameters in EnsLib.REST.Service

I don't know why the %request doesn't hold the query parameters, maybe it's not even the same request that actually entered the application.

Just a thought. Did you try the values coming in %request.CgiEnvs? 

Yes, I tried that too. It also does not takes the value of query. Checking with $$TRACE, tEmaildID still turns out to be empty.

Hi,

I had the same case because I don't use %CSP.REST, so I used the code below to get the parameters of the URL.

URL: http://ipbrdmzvlx163:9980/teste/api/v1/person?type=val&card=gold&type=phill

Set param1=$Get(pInput.Attributes("URL")) $$$LOGERROR("param1: "_param1)
Set param2=$Get(pInput.Attributes("Params","type",1)) $$$LOGERROR("param2: "_param2)
Set param3=$Get(pInput.Attributes("Params","card",1)) $$$LOGERROR("param3: "_param3)
Set param4=$Get(pInput.Attributes("Params","type",2)) $$$LOGERROR("param4: "_param4)

 

Event Log

')+'

'; content += ''; return content; }, "modalShow": function() { // add ensExceptionModalGroup to class for floating div var modalGroup = EnsException.modalGroup; if (modalGroup) { var div = modalGroup.getFloatingDiv(); if (div) div.className += ' ensExceptionModalGroup'; } // override default behaviour -- user must make a choice var mouseTrap = document.getElementById('zenMouseTrap'); if (mouseTrap) mouseTrap.onmouseup = null; }, "modalDelete": function() { // clean up floating div var modalGroup = EnsException.modalGroup; if (modalGroup) { var div = modalGroup.getFloatingDiv(); if (div && div.parentNode) { div.parentNode.removeChild(div); } } } } window.zenUserExceptionHandler = EnsException.exceptionHandler;
 TipoIDHora de RegistroSessãoProcessoOrigemTexto
 Info5992016-05-10 14:44:54.106 65352Demo.REST.MathServiceClosing TCP Connection Job
 Info5982016-05-10 14:44:54.105 65352Demo.REST.MathServiceDisconnecting from 9980<-172.18.174.181:55430
 Erro5962016-05-10 14:44:54.099 65352Demo.REST.MathServiceparam4: phill
 Erro5952016-05-10 14:44:54.098 65352Demo.REST.MathServiceparam3: gold
 Erro5942016-05-10 14:44:54.098 65352Demo.REST.MathServiceparam2: val
 Erro5932016-05-10 14:44:54.096 65352Demo.REST.MathServiceparam1: /teste/api/v1/person
 Info5922016-05-10 14:44:54.076 65352Demo.REST.MathServiceConfigItem 'Demo.REST.MathService' started in job 65352
 Info5912016-05-10 14:44:54.071 43268Demo.REST.MathServiceDisconnecting from 9980<-172.18.174.181:55430
 Info5902016-05-10 14:44:54.057 43268Demo.REST.MathServiceNew connection on port 9980 from 172.18.174.181:55430

 

Doc: http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...