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