Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

VFP using REST service and parsing JWT token

Status
Not open for further replies.

gkratnam

Programmer
Aug 9, 2007
37
US
My VFP application needs to use a REST service to connect to another application and import some data.
I am able to establish a connection and get the response back. But I don't know how to parse the JWT-token.

Here is my code.

Contacting the server

oXMLHttpRequest = CreateObject("MSXML2.XMLHTTP.6.0")

oXMLHttpRequest.open("POST", "my url", null)

oXMLHttpRequest.setRequestHeader("Content-Type", "application/x-
oXMLHttpRequest.send("username=murugu&password=mmmm")

result = oXMLHttpRequest.ResponseBody &&saved the response

?oXMLHttpRequest.status - This returned 200


Passing the returned jwt-token

oXMLHttpRequest.open("GET","my url")

oXMLHttpRequest.setRequestHeader("Content-Type", "text/xml")

oXMLHttpRequest.setRequestHeader("Content-Type", "application/json")


oXMLHttpRequest.setRequestHeader("Authorization", "AR-JWT<result>") &&passing the saved value

oXMLHttpRequest.Send()


Received "Not able to parse Authorization Header parameter." message.

I am old school, don't know much about web services. Could anyone please assist me with this?

Thanks - Ganga
 
You're very unspecific about what Webservice you're trying to use.

When the value you put into the header isn't parsed correctly, my first guess would be it's a codepage issue, or ANSI (VFP) vs. Unicode (the rest of the world). Or this needs to be JSON or whatever the specification for this REST service asks. Usually, you just have to follow the tiniest details in the description of the REST service.

Maybe it's not even expecting what you send in the HTTP request headers, but only you're able to know better as you know what REST service you want to use and know its specification or documentation. If it's the Authorization hader, the usual usage is described here: Maybe you just nede a space between AR-JWT (the type) and the <result> (corresponding to <credentials>), just like there is a space in the generic form of the Authorization header: [tt]Authorization: <type> <credentials>[/tt]



Chriss
 
Hi Chris,
Thanks for your assistance. Let me tell you what I know about the REST service I am trying to use.

1. The REST API uses JSON Web tokens. To call the API you’ll need to request a JWT with your service account credentials

2. To request a new token make an HTTP POST, in the HTTP header include Content-Type = “application/x- and include the service account’s credentials in the body in as a string with the form data name, value pairs URL encoded. username=murugu&password=mmmm be sure to put this URL encoded string in the HTTP POST body and not in URL parameters. It’ll work in the URL but not consistently.

3. If the login is successful the HTTP response code will be 200, and the body will include the JWT. If not successful the HTTP response code will be 401.

Since I got the 200, hope we are good till this point

Then I tried updating the data as per below that did not work. So, tried to use GET to troubleshoot.

4. Once you have a valid token you can make the call to update Service Request. The endpoint for updating a Service Request ticket is
a. To update a ticket make an HTTP PUT, in the HTTP header include Authorization = “AR-JWT <token>”, and "Content-Type" = "application/json".
b. In the HTTP message body include the JSON to update a service request ticket. The JSON data is an object where the values key contains the object of field name, value pairs.
c. {"values":{"Summary":"TEST For Summary Field","Details":"TEST for details field"}
d. If successful the HTTP response should contain the URL for this new entry object

I tried the space between Authorization: <type> <credentials>, did not work.

Chris, I totally agree with your comments about following even the tiny details. Since I am fairly new to this Webservices, don't know where to start and what is important or not.

I am attaching the screen shot, it may be useful.

Thanks - Ganga

 
Ganga,

So, you're getting back a dot-separated base64 serialized JSON token. What you can do with it depends on the specifications of the WS you're trying to consume. I believe that's what Chris was wondering about. It would help to know what's the WebService, and where is its access documentation.
 
1. You're asked to use a PUT request, a GET request has no body and can't be used to test, can it?
2. You're setting to Conntent-Type headers, only use the one you're asked to use.

I assume as both requests reading some data or updating it need the body, so GET requests are of no use. Read the docs, I bet they're using PUT and POST to make the distinction between PUTting new dataa and POSTing a (read) request.

Besides that, you actually just always send over "AR-JWT<result>" as "<type> <credential>", if you want to use VFPs textmerge functionality, then this needs <<result>> and depending on your VFP version TEXT..ENDTEXT or the TextMerge() function, but simply add result this way:

Code:
oXMLHttpRequest.setRequestHeader("Authorization", "AR-JWT "+result) &&passing the saved value


Chriss
 
I am slowly getting the concepts here. Thank you for your time and all the explanations.

The docs only have the info I have posted above. I masked the URL for security.

Chris, your details are very useful and making sense. I tried the HTTP PUT.

This is what the documentation says:
Once you have a valid token you can make the call to update Service Request. The endpoint for updating a Service Request ticket is Here is a fullt URL you can use for testing:
a. To update a ticket make an HTTP PUT, in the HTTP header include Authorization = “AR-JWT <token>”, and "Content-Type" = "application/json".
b. In the HTTP message body include the JSON to update a service request ticket. The JSON data is an object where the values key contains the object of field name, value pairs.
c. {"values":{"Summary":"TEST For Summary Field","Details":"TEST for details field","New Note":"This is a new note to Ticket"}}
d. If successful the HTTP response should contain the URL for this new entry object, and you can use that URL to do additional read, and update operations on the entry.

This is my code. Seems Authentication worked using your code. But, I am not sure how to do the last line.

Code:
oXMLHttpRequest.open("PUT","[URL unfurl="true"]http://********/api/arsys/v1/entry/sprt_Service%20Request/RQST00004225459")[/URL]

oXMLHttpRequest.setRequestHeader("Authorization", "AR-JWT "+result) 

oXMLHttpRequest.setRequestHeader("Content-Type","application/json") && Added this to avoid the 415 HTTP code

oXMLHttpRequest.send("{'values':{'Summary':'TEST For Summary Field','Details':'TEST for details field','New Note':'This is a new note to Remedy Ticket'}}") && Returned 500 HTTP code

I am using VFP 9. How do I send the values in the HTTP message body?

One more question please. Is there a way to combine both setRequestHeader into one?


Thanks - Ganga
 
The message body is what you send with oXMLHttpReuest.send("body") and that has to be valid JSON. There are several JSON libraries available for VFP, sarch the forum, they were mentioned in recent posts.

I'd not put that body sending into a one-liner, prepare the body valu with TEXT..ENDTEXT into a variable and send that.

Chriss
 
Chriss, thanks for your guidance!

I found JSONFox library.


Code:
*****Prepare body in JSON
Do LocFile("JSONFox", "app")

Text To lcJsonStr NoShow
   {
   	"values": {
	    "Summary":"TEST For Summary Field",
	    "Details": "TEST for details field",
	    "New Note":"This is a new note"
	    }
   }
 ENDTEXT
 
 If _Screen.Json.lError
   MessageBox(_Screen.Json.LastErrorText, 48, "Something went wrong")
   Return
 EndIf  ***No error returned
 
 body = _Screen.Json.Parse(lcJsonStr)

Code:
 ******Open connection and send the JSON from above
oXMLHttpRequest.open("PUT","[URL unfurl="true"]http://********/api/arsys/v1/entry/sprt_Service%20Request/RQST00004225459")[/URL]

oXMLHttpRequest.setRequestHeader("Authorization", "AR-JWT "+result) &&passing the saved value 

oXMLHttpRequest.setRequestHeader("Content-Type","application/json")

oXMLHttpRequest.send("body")

As per the documentation this is what we need to pass.
The JSON data is an object where the values key contains the object of field name, value pairs.
{"values":{"Summary":"TEST For Summary Field","Details":"TEST for details field","New Note":"This is a new note"}}


Please let me know what am I missing here. Please see the screen shot for the below test.
?body.values
?body.values.summary
?oXMLHttpRequest.status

Thanks - Ganga
 
You create an object from JSON with .Json.Parse(lcJsonStr), that's not what you need, you can just use the JSON as you write it into your TEXT statement.

And to send a variable named body, you need send(body), not send("body"). When you send("body" you literally just send the string "body" as your body.

I also recommend you use a tool to record HTTP traffic. Wireshark, for example.
So you can record and see literally what you send and what's the response.





Chriss
 
You almost had it..
json uses double quotation marks to denote property names,
so just change last line:

Code:
with oXMLHttpRequest as msxml.httprequest 

   .open("PUT","[URL unfurl="true"]http://********/api/arsys/v1/entry/sprt_Service%20Request/RQST00004225459")[/URL]
   .setRequestHeader("Authorization", "AR-JWT "+result) 
   .setRequestHeader("Content-Type","application/json") && Added this to avoid the 415 HTTP code

   *// changed:

   cJson = '{"values":{"Summary":"TEST For Summary Field","Details":"TEST for details field","New Note":"This is a new note to Remedy Ticket"}}'
   .send(m.cJson)

endwith



Marco Plaza
@nfoxProject
 
Chriss, you are truly awesome!

Yes, that did it. I got a 404, seems like a different issue, may need to talk to the API developer. Please see the screen shot.

Just to clarify, I can't pass in an "object" as per the documentation, correct? It has to be a JSON string.

Yeah, that's silly just passing string "body". Good catch.


To trace HTTP request and response, what tool would you recommend that is VFP friendly. I heard about Postman and Fiddler.

I wouldn't be able to reach this far without your guidance. I truly appreciate your help.

Thanks - Ganga
 
 https://files.engineering.com/getfile.aspx?folder=98545683-7eee-4873-af7d-6d5be4d17ea0&file=WebserviceJsonmessage.png
Hi Marco,
Just saw your message. Yes, that worked too! Thanks for teaching me a second way.

Thanks - Ganga
 
Indeed JSON was invented as a way to serialize javascript objects as a string which (in javascript) is the definition of the object,i runnable code that produces such an object. JSON libraries for VFP allow you to convert JSON to an object and vice versa, to send a request you'd either turn a VFP object to JSON or create the JSON string from scratch. In your example, a problem would be the "New Note" property, as VFP property names can't have spaces. Just a sidenote.

More important: Wireshark, Fiddler, Postman. You run such tools in parallel and they can write logs, text files. You don't need a VFP inteation, whatever you send by HTTP gets noted by them and vice versa whatever comes in as network traffic is recorded. You can filter this, as you only are interested in http prtocol messages and likely only from or to the domain of this REST service. A good thing would be to let VFP start a network traffic recording and stop it after the response came back. But if you go as far, you could also simply log the body you send and the responsebody you get back within VFP without any such tool. The best benfit is you get a full recording of details that might be of interest to get things working. I actually never needed this tight integration into VFP. If you filter the traffic very selective you can also manually start a recording right before starting your VFP code and don't have to do this from VFP.

Enough words, throw yourself into the cold water, you'll get to know and appreciate what the tools can do for you even without integrating them to VFP.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top