B4J Question REST web service POST request, need help

Paul_

Member
Licensed User
I have zero experience of sending POST requests to a REST api so first I tried sending the whole xml/text payload including the headers and body as a string by reading it from the File.DirAssets folder (very optimistic I know!), when I did this the remote server responds with "Unauthorized" error.

The Basic login and password string (format login:password in base64) is correct as I converted it myself using B4J code and when it didn't work I then used Fiddler to capture the real packet sent from the browser and it matches my own string so the login credentials are correct. I am using the jOKHttpUtils2 library.

This is the full REST payload that I captured and this works when sent from a web based test utility:

B4X:
POST https://ifc.int.hot-sos.net/api/service.svc/rest/serviceorder HTTP/1.1
Host: ifc.int.hot-sos.net
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0
Accept: text/plain, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://ifc.int.hot-sos.net/api/pages/test/
Content-Type: text/xml; charset=UTF-8
Authorization: Basic RWxlY29uaW50X1N5c3RlbTp0ZXN0aW5nMTIz
X-Requested-With: XMLHttpRequest
Content-Length: 329
Connection: keep-alive

<ServiceOrder xmlns="urn:serviceorder.api.m-tech.com" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
     <Issue xmlns:a="urn:issue.api.m-tech.com">
         <ID xmlns="urn:api.m-tech.com">10744</ID>
     </Issue>
     <Location xmlns:a="urn:room.api.m-tech.com">
         <ID xmlns="urn:api.m-tech.com">600</ID>
     </Location>
</ServiceOrder>

But I cannot figure out how to emulate the same thing using B4J.

I then used the following simple B4J code to send the header login and password separately and just the body packet as "requestREST.xml":

B4X:
Sub REST_Job

    Dim j As HttpJob
    j.Initialize("j", Me)
    Dim msg As String
    msg = File.ReadString(File.DirAssets, "requestREST.xml")
    Log(msg)

    j.Username="xxxxxxxxxxx"
    j.Password="xxxxxxxxxxx"

    j.PostString("https://ifc.int.hot-sos.net/api/service.svc/rest/serviceorder", msg)

End Sub

Sub JobDone (Job As HttpJob)

    Log("JobName = " & Job.JobName & ", Success = " & Job.Success)
    If Job.Success = True Then
        Log(Job.GetString)
    Else
        Log("Error: " & Job.ErrorMessage)
    End If
    Job.Release

End Sub

Instead of an "Unauthorized" error this time I get the error: "Internal Server Error"

I know I must be making some very simple mistake somewhere, any advice would be really appreciated?
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Upvote 0

Paul_

Member
Licensed User
In the second example I did use the job.username and job.password and I only sent the body starting with <ServiceOrder... but I still got an error in return.

I will study the link you sent about the header content type.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Upvote 0

Paul_

Member
Licensed User
Thank you Oliver, you saved my life! That works.

Forgive me for saying this but it doesn't seem very intuitive to have to send this header content type after sending the PostString o_O
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Forgive me for saying this but it doesn't seem very intuitive to have to send this header content type after sending the PostString
Have you seen this link (I posted in my previous answer): https://www.b4x.com/android/forum/threads/set-http-request-header-with-okhttputils2.39413/#content
?

It is a bit confusing as it seems that the header is set after the request was sent. However internally HttpJob uses CallSubDelayed to send the request. So the request will only be sent after the current code execution completes.
 
Upvote 0

Paul_

Member
Licensed User
Yes, thank you Erel.

It's interesting in my case that only setting the "content-type" made the POST work, I see your note saying that sometimes the "user-agent" also has to be set or the server will reject the GET/POST.

Looking at my opening post I had captured many headers on the original POST using Fiddler, without experience it's difficult to know what is essential and what headers can be left out. I had previously asked an "api guru" who works for the company whose REST api I am calling to confirm which headers are required, but sadly I got no response.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
It's interesting in my case that only setting the "content-type" made the POST work,
I get the error: "Internal Server Error"
As you can see, without proper content-type, the server trips up. This has nothing to do with B4J's HttpJob implementation, it's just the server expects certain headers (in this case, a proper Content-Type) or else it errors out.
Looking at my opening post I had captured many headers on the original POST using Fiddler, without experience it's difficult to know what is essential and what headers can be left out.
whose REST api I am calling
All the requirements should be part of an API's documentation. That you are having difficulties has nothing to do with B4J, but with the API you are trying to access. B4J gives you the tools to fulfill the requirements of most API's out there. If you look at the solution you came to, the B4J code is actually very compact.
 
Upvote 0
Top