Written by

Learning Services Documentation Ensemble and Caché at InterSystems
Question Joshua Goldman · Mar 16, 2016

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!

Comments

Ohm Trivedi · Mar 16, 2016

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

Thanks Joshua for the support.

0
John Murray  Mar 16, 2016 to Scott Beeson

Great link Scott. Thanks!

0
Ohm Trivedi  Mar 16, 2016 to Scott Beeson

Hi Scott,

I am a newbie here, so my queries are a little basic.

I tried to change the format of URL like this http://localhost:57772/myDemo/myService/UserAccounts?email=abc@gmail.com

But, then I get an error in my service which is s follows:

ERROR <Ens>ErrGeneral: Unsupported REST URL: /UserAccounts%3Femail%3Dabc%40gmail.com for HTTP command GET

Can you tell me why this didn't work?

Thanks

0
Herman Slagman · Mar 17, 2016

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")

0
Ohm Trivedi  Mar 17, 2016 to Herman Slagman

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
}

0
Herman Slagman  Mar 18, 2016 to Ohm Trivedi

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'.

0
Ohm Trivedi  Mar 18, 2016 to Herman Slagman

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?

0
Herman Slagman  Mar 19, 2016 to Ohm Trivedi

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.

0
Ramesh Ramachandran · Mar 25, 2016

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

0
Ohm Trivedi  Mar 25, 2016 to Ramesh Ramachandran

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

0
Valdeir Silva · May 10, 2016

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;

  Tipo ID Hora de Registro Sessão Processo Origem Texto
  Info 599 2016-05-10 14:44:54.106   65352 Demo.REST.MathService Closing TCP Connection Job
  Info 598 2016-05-10 14:44:54.105   65352 Demo.REST.MathService Disconnecting from 9980<-172.18.174.181:55430
  Erro 596 2016-05-10 14:44:54.099   65352 Demo.REST.MathService param4: phill
  Erro 595 2016-05-10 14:44:54.098   65352 Demo.REST.MathService param3: gold
  Erro 594 2016-05-10 14:44:54.098   65352 Demo.REST.MathService param2: val
  Erro 593 2016-05-10 14:44:54.096   65352 Demo.REST.MathService param1: /teste/api/v1/person
  Info 592 2016-05-10 14:44:54.076   65352 Demo.REST.MathService ConfigItem 'Demo.REST.MathService' started in job 65352
  Info 591 2016-05-10 14:44:54.071   43268 Demo.REST.MathService Disconnecting from 9980<-172.18.174.181:55430
  Info 590 2016-05-10 14:44:54.057   43268 Demo.REST.MathService New connection on port 9980 from 172.18.174.181:55430

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

0