Viewing httprequest in Enslib.Rest.Operation and setting pwd

The REST webservice works perfectly when run on SOAP UI. This end point server is an https site that uses basic authentication (uname and pwd).  But when I run the request through an Enslib.Rest.Operation using a configured SSL and stored credentials, I get an "unauthorized" error, unless I explicitly hard code the password in the operation class. HS Version is 2014.1 .

I have 2 questions. Pardon me, they are both related!!

1: How can the httprequest object be viewed in Ensemble? It took a long time for me to actually troubleshoot this because I had no way to see the httprequest object before it was submitted. I tried using a custom outbound adapter with a DEBUG=2 but I had no idea where the request and response are written. I did not see them in the HTTP Trace log of the CSP gateway after turning on the TRACE.

2: How is the Adapter password set? I tried the following 3 ways and they all returned an "unauthorized" error.

Did not work:-

Set tCredentials = ##class(Ens.Config.Credentials).%OpenId("myCredentials")
Set ..Adapter.%CredentialsObj.Username = tCredentials.Username
Set ..Adapter.%CredentialsObj.Password = tCredentials.Password

Set tSC = ..Adapter.PostURL(..Adapter.URL,.tHttpResponse,"",pRequest.ContentStream)

Did not work:-

Set tCredentials = ##class(Ens.Config.Credentials).%OpenId("myCredentials")
Set ..Adapter.%CredentialsObj = tCredentials

Set tSC = ..Adapter.PostURL(..Adapter.URL,.tHttpResponse,"",pRequest.ContentStream)

Did not work:-

Set ..Adapter.Credentials = "myCredentials"

Set tSC = ..Adapter.PostURL(..Adapter.URL,.tHttpResponse,"",pRequest.ContentStream)

Did not work

Setting the credentials in the "Credentials" basic setting of the Operation in the Production=myCredentials. 

Worked
Set tCredentials = ##class(Ens.Config.Credentials).%OpenId("myCredentials")
Set ..Adapter.%CredentialsObj.Username = tCredentials.Username
Set ..Adapter.%CredentialsObj.Password = "ACTUAL PASSWORD"

There is no way this last line can get through code review! How is this done in the real world?
        
        
 

  • 0
  • 0
  • 360
  • 2
  • 2

Answers

1: How can the httprequest object be viewed in Ensemble?

You can use DEBUG=2, to see the output you need to start your BH in Debugging mode.

Another option would be to install Debugging proxy such as Fiddler and specify ProxyServer/ProxyPort settings in your BH.

Finally, you can install packer sniffer such as WireShark and see the raw packets.

These options are discussed more in detail in my series of articles Debugging Web: part1, part2.

2: How is the Adapter password set?

No need to write code for that, just set Credentials setting in your BH.

Thanks for the debug answer.

Setting the credentials on the Operation did not work.

When I put a $$$HTRACE to write its value to UtilTrace, it is blank.

I had already tried that.

Setting the credentials on the Operation did not work.

Do you redefine request object in your own code? It really should and does work. Please consider posting an example.

Not sure if it will help but there are 2 examples below.

The first uses the EnsLib.HTTP.OutboundAdapter to perform a GET on a REST service. This has had the credentials and the SSL configuration specified in the operation properties.

The second uses the %Net.HttpRequest to perform a POST to a REST service. This is more of a manual process.

Example #1:

set ..Adapter.URL = ..QueryURL
set status = ..Adapter.Get(.HttpResponse,"subjectId,subjectNamespace",objRequest.SubjectId,..Namespace)
if status {
     set objResponse.StatusCode = HttpResponse.StatusCode
     if HttpResponse.StatusCode = 200 {
          do HttpResponse.Data.Rewind()
          set string = HttpResponse.Data.Read()
          set objDyn = ##class(%DynamicAbstractObject).%FromJSON(string)
          set objItr = objDyn.%GetIterator()
          while objItr.%GetNext(.key,.value) {
               if key = "patId" set objResponse.PatId = value quit
          }
     }
}
quit status

Example #2

set objHttp = ##class(%Net.HttpRequest).%New()
set objHttp.Server = ..Server
set objHttp.Port = ..Port
set objHttp.Https = 1
set objHttp.SSLConfiguration = ..SSLConfiguration
set objCred = ##class(Ens.Config.Credentials).%OpenId(..Credentials)
set objHttp.Password = objCred.Password
set objHttp.Username = objCred.Username
set objHttp.WriteRawMode = 1
set objHttp.ContentType = "application/json"

do objHttp.SetHeader("Cache-Control","no-cache")

// Parameters. These are in the request message as an array of %String where the key in the array is the name of the parameter
set key = ""
for  {
     set data = pRequest.Headers.GetNext(.key)
     if key = "" quit
     if data '= "" do objHttp.SetParam(key,data)
}

// Form data. This is an array of stringsin the request message. Written directly to the entity body as name/value pairs in a JSON stream

set first = 1

do objHttp.EntityBody.Write("{")
for  {
     set data = pRequest.FormData.GetNext(.key)
     if key = "" quit
     if data '="" {

          if 'first do objHttp.EntityBody.Write(", ")

          do objHttp.EntityBody.Write(""""_key_"""")
          do objHttp.EntityBody.Write(": ")
          do objHttp.EntityBody.Write(""""_data_"""")
          set first = 0
     }
}

do objHttp.EntityBody.Write("}")
set status = objHttp.Post(..URL)
if status {
     set pResponse.StatusCode = objHttp.HttpResponse.StatusCode
     set pResponse.StatusLine = objHttp.HttpResponse.StatusLine
}

quit status