parsing xml response

Hello!

I'm sending http resuest to the web service :

Set httpRequest=##class(%Net.HttpRequest).%New()
Set httpRequest.Server="177.127.120.10"
Set httpRequest.ContentType="text/xml" 
Set httpRequest.Https=1
Set httpRequest.ContentCharset="UTF-8"
Do httpRequest.SetHeader("Accept","text/xml")
Set httpRequest.Timeout=300     

Set xml="<CheckContractRequest><IIN>"_IINPay_"</IIN>"
_"<FirstName>"_name_"</FirstName>"
_"<LastName>"_surname_"</LastName>"
_"<MiddleName>"_middlename_"</MiddleName>"
_"<BirthDate>"_birthDate_"</BirthDate>"
_"<ContractType>CONST</ContractType></CheckContractRequest>"

do httpRequest.EntityBody.Write(xml)

set httpResponse = ##class(%Net.HttpResponse).%New()
Set httpResponse = httpRequest.Post("/sample/", 2)

set resp=httpRequest.HttpResponse
zw resp

if $zObjState(httpRequest.HttpResponse)
{
resp=httpRequest.HttpResponse.Data
len=32767,resptext=""
if $isObject(httpRequest.HttpResponse.Data) {
for  {
q:httpRequest.HttpResponse.Data.AtEnd
resptext=resptext_httpRequest.HttpResponse.Data.Read(.len) q:len<0
}
^tk(2)=resptext
response=..getXMLValue(resptext, "message")
}
elseif ($l(resp.Data)>0 ) {
resptext=resp.Data
}

}

response:

<CheckContractRequest>
    <IIN>891299300335</IIN>
    <FirstName>Ivan</FirstName>
    <LastName>Ivanov</LastName>
    <MiddleName>Ivanovich</MiddleName>
    <BirthDate>01.01.1987</BirthDate>
    <ContractType>CONST</ContractType>
</CheckContractRequest>

The response :

<?xml version="1.0" encoding="UTF-8"?>
<CheckContractResponse>
    <code>0</code>
    <message>OK</message>
</CheckContractResponse>

the question:

1) how to know that request was sent succesfully to web service?

how I can get data from stream bellow ?

resp=<OBJECT REFERENCE>[121@%Net.HttpResponse]
+----------------- general information ---------------
|      oref value: 121
|      class name: %Net.HttpResponse
| reference count: 3
+----------------- attribute values ------------------
|    ContentBoundary = ""
|        ContentInfo = ""
|      ContentLength = ""
|        ContentType = ""
|               Data = "122@%Stream.GlobalBinary"
|        HttpVersion = ""
|       ReasonPhrase = ""
|         StatusCode = ""
|         StatusLine = ""

  • 0
  • 0
  • 142
  • 12
  • 1

Answers

Usually response does contain status information in StatusCode and StatusLine properties.

You need to change this line

Set httpResponse = httpRequest.Post("/sample/", 2)

to

#dim sc As %Status = $$$OK
Set sc = httpRequest.Post("/sample/", 2)
Write $System.Status.GetErrorText(sc)

As Post method returns status.

After debugging you can use

write $$$ISERR(sc)

macro to check if result of some operation is an error.

Hi Eduard!

Thank you for your response.  I have change the code,  method return output status=0. 

I have sent the request using Postman utility and receive the response after 30 seconds. 

how i can know that request was sent sussecfully and how to get readable response? Thank you.

Compare output of

Set sc = httpRequest.Post("/sample/", 1)

with what Postman sends.

Also, what does

Set sc = httpRequest.Post("/sample/")
zw sc

show?

Set sc = httpRequest.Post("/sample/", 1)

The output:

set sc=##class(Example.TEST).xmlRequest("891208300335","Ivan","Ivanov","Ivanovich","08.12.1989","ОПВ")
POST /sample/ HTTP/1.1
User-Agent: IBM-APIConnect/5.0
Host: 172.27.139.151
Accept-Encoding: gzip
Accept: text/xml
x-ibm-client-id: adsad-adsadsa-asdsad
x-ibm-client-secret: 13213213asdsadsadsad
Content-Length: 251
Content-Type: text/xml; charset=UTF-8
 
<CheckContractRequest><IIN>891208300335</IIN><FirstName>Ivan</FirstName>
<LastName>Ivanov</LastName><MiddleName>Ivanovich</MiddleName>
<BirthDate>08.12.1989</BirthDate><ContractType>ОПВ</ContractType></CheckContractRequest>0

Set sc = httpRequest.Post("/sample/", 2)
zw sc

output: sc=1

When you get sc=1 , what about:

set resp=httpRequest.HttpResponse
zw resp
do resp.Data.OutputToDevice()

sc=1
0

resp=<OBJECT REFERENCE>[138@%Net.HttpResponse]
+----------------- general information ---------------
|      oref value: 138
|      class name: %Net.HttpResponse
| reference count: 3
+----------------- attribute values ------------------
|    ContentBoundary = ""
|        ContentInfo = ""
|      ContentLength = ""
|        ContentType = ""
|               Data = "139@%Stream.GlobalBinary"
|        HttpVersion = ""
|       ReasonPhrase = ""
|         StatusCode = ""
|         StatusLine = ""
 
 

Interesting. Check this article - I think you'll need either HTTP Debugging proxy (probably) or Packet analyzer (maybe) to debug this further.

As you have reference implementation (Postman) you can start by comparing Postman request/response and Ensemble request/response using HTTP Debugging proxy.

Hello Eduard!

Now I'm getting error: 415 Unsupported Media Type.  In the code i set:

Do httpRequest.SetHeader("accept","text/xml")
Set httpRequest.ContentType="text/xml"   

HTTP/1.1 415 Unsupported Media Type
ACCESS-CONTROL-ALLOW-CREDENTIALS: false
ACCESS-CONTROL-ALLOW-METHODS: POST
ACCESS-CONTROL-ALLOW-ORIGIN: *
ACCESS-CONTROL-EXPOSE-HEADERS: APIm-Debug-Trans-Id, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-Global-Transaction-ID
CONNECTION: Keep-Alive
CONTENT-ENCODING: gzip
CONTENT-TYPE: text/plain
DATE: Thu, 13 Sep 2018 13:55:03 GMT
TRANSFER-ENCODING: chunked
USER-AGENT: IBM-APIConnect/5.0
X-BACKSIDE-TRANSPORT: OK OK
X-GLOBAL-TRANSACTION-ID: 2956707581
 
Unsupported Media Type
str=<OBJECT REFERENCE>[19@%Stream.FileCharacterGzip]
+----------------- general information ---------------
|      oref value: 19
|      class name: %Stream.FileCharacterGzip
|           %%OID: $lb("C:\InterSystems\Ensemble2016\mgr\Temp\VqdL7hXdFahzDg.http","%Stream.FileCharacterGzip","")
| reference count: 3
+----------------- attribute values ------------------
|     (%Concurrency) = 1
|          %Location = ""  <Set>
|         (%LockRef) = ""
|          (%Locked) = 0
|              AtEnd = 0
|                BOM = ""
|         (CurrFile) = ""
|                 Id = "C:\InterSystems\Ensemble2016\mgr\Temp\VqdL7hXdFahzDg.http"  <Set>
|     LineTerminator = $c(13,10)  <Set>
|      (MakePermLoc) = 0
|             (Mode) = 1
|(NormalizedDirectory) = "C:\InterSystems\Ensemble2016\mgr\Temp\"
|(OidTranslateTable) = "RAW"
|         (ReadMode) = 0
|           ReadSize = 48
|      RemoveOnClose = 1
|        (StoreFile) = "VqdL7hXdFahzDg.http"
|  StreamFormatWrite = 1
|         (TempFile) = ""
|     TranslateTable = "RAW"  <Set>
|      UseVMSVersion = 0
|   (VariableRecord) = 0

Try application/xml instead of text/xml for content type.

If it does not help, check API docs for correct type.

For accept try */*.

compare headers between postman and cache I found the difference in content type.  

In postman : Content-Type: text/xml

In cache: Content-Type: text/xml; charset=UTF-8

How I can remove charset=UTF-8 from header in cache ?

Thanks a lot Eduard! It's working. But another problem has occured: the response is non readable: 

<?xml version="1.0" encoding="UTF-8"?>
 <CheckContractResponse><code>-1</code><message>Неверный тип договора</message></CheckContractResp>

As a direct solution you can do

write $zcvt("<CheckContractResponse><code>-1</code><message>ÐевеÑнÑй Ñип договоÑа</message></CheckContractResp>","I","UTF8")
<CheckContractResponse><code>-1</code><message>Неверный тип договора</message></CheckContractResp>