PDA

View Full Version : Working with web services and SOAP in Lianja



barrymavin
2012-10-20, 02:39
In Lianja Beta10 we have added an additional (optional) parameter to the GETURL( ) function to read a file from a remote web server and store its contents into a local file.



// perform a query against a remote server and return a chunk of JSON into a file
filename = geturl("http://www.myserver.com/getsomepage.rsp?name=smith&month=10", 30, array(), "myfilename.json")
if len(filename) = 0
// no data was returned
endif


We have also ddded a new function POSTURL( ) that operates in the same way as GETURL( ) but sends an HTTP POST request to the specified URI. By default the data is just sent as "text/plain" in the HTTP body but you can add custom headers to the "headers" associative array and POST SOAP requests and read the response from the remote server which is returned as a string of text. The last parameter can either be a filename or a character expression that will be sent as the POST body.



// send a soap request
response = posturl("http://www.myserver.com/somewebservice.aspx", ;
30, ;
array("type" => "Content-Type: text/xml"), ;
"somefilename.xml")

if len(response) = 0
// no data was returned
endif

// submit a form
response = posturl("http://www.myserver.com/someformsubmission.rsp", ;
30, ;
array("type" => "Content-Type: application/x-www-form-urlencoded"), ;
"name=barry&product=lianja")
if len(response) = 0
// no data was returned
endif

hmischel@diligentsystems.com
2013-09-22, 13:02
Hi,

I am trying to get an address from the free google service.
I am passing in an address.

filename = geturl("http://maps.googleapis.com/maps/api/geocode/xml?address=100 valentine street 08904&sensor=false", 30, array(), "myfilename.xml")
myobject = xml_decode_file(filename, "GeocodeResponse", "Status")

In my example, I am trying to get the status.
I am sure it is simple. but I am missing it.


This is a partial response that I copied from my browser.


This XML file does not appear to have any style information associated with it. The document tree is shown below.
<GeocodeResponse>
<status>OK</status>
<result>
<type>street_address</type>
<formatted_address>100 Valentine Street, Highland Park, NJ 08904, USA</formatted_address>
<address_component>


Thanks.

Herb

yvonne.milne
2013-09-30, 10:53
Hi Herb,

This will get you the file:


oRequest = createObject("networkrequest")
oRequest.getfile("http://maps.googleapis.com/maps/api/geocode/xml?address=100 valentine street 08904&sensor=false","myfilename.xml")

and this will display the status:


myobject = xml_decode_file("myfilename.xml", "GeocodeResponse")
? myobject['status']

I'm just looking into using the third parameter on xml_decode_file - I believe you should be able to specify 'status', but will check.

Regards,

Yvonne

hmischel@diligentsystems.com
2013-09-30, 12:50
Thanks Yvonne,

I had the option of getting the results as a json and that is working fine for me using geturl.
Is one method preferred over the other?

Meaning geturl vs networkrequest?

Thanks.

Herb

yvonne.milne
2013-09-30, 13:01
Hi Herb,

For larger/more complex amounts of data I would go with NetworkRequest.

Regards,

Yvonne

hmischel@diligentsystems.com
2013-10-05, 22:32
Hi,

I am using networkrequest for an HTTPS request.
I am having some difficulty traversing the XML output.

Here is the output of my file.

Dynarray (refcnt=0)
(
[status] => OK
[result] => <type>street_address</type> <formatted_address>100 Valentine Street, Highland Park, NJ 08904, USA</formatted_address> <address_component> <long_name>100</long_name> <short_name>100</short_name> <type>street_number</type> </address_component> <address_component> <long_name>Valentine Street</long_name> <short_name>Valentine St</short_name> <type>route</type> </address_component> <address_component> <long_name>Highland Park</long_name> <short_name>Highland Park</short_name> <type>locality</type> <type>political</type> </address_component> <address_component> <long_name>Middlesex</long_name> <short_name>Middlesex</short_name> <type>administrative_area_level_2</type> <type>political</type> </address_component> <address_component> <long_name>New Jersey</long_name> <short_name>NJ</short_name> <type>administrative_area_level_1</type> <type>political</type> </address_component> <address_component> <long_name>United States</long_name> <short_name>US</short_name> <type>country</type> <type>political</type> </address_component> <address_component> <long_name>08904</long_name> <short_name>08904</short_name> <type>postal_code</type> </address_component> <geometry> <location> <lat>40.4910198</lat> <lng>-74.4298371</lng> </location> <location_type>RANGE_INTERPOLATED</location_type> <viewport> <southwest> <lat>40.4896776</lat> <lng>-74.4311887</lng> </southwest> <northeast> <lat>40.4923755</lat> <lng>-74.4284908</lng> </northeast> </viewport> <bounds> <southwest> <lat>40.4910198</lat> <lng>-74.4298424</lng> </southwest> <northeast> <lat>40.4910333</lat> <lng>-74.4298371</lng> </northeast> </bounds> </geometry> )

I can get status and result, but cant seem to figure out how to get beyond that point to my individual values under the result node.
I have tried to reference the values using different array techniques - dot notation and direct names ie ['long_name']

It's probably simple, but I cant figure it out.
Thanks.
Herb

barrymavin
2013-10-06, 00:26
Hi Herb,

I am intending to add two new classes in v1.1 "xmlreader" and "xmlwriter" but at the moment the xml_decode() function won't handle a structure it does not understand.

Can you let me see the complete xml that is returned. Looking at what you have posted its not properly formed as an xml tree. Just looks like a stream of xml tags with no proper document structure.

hmischel@diligentsystems.com
2013-10-07, 14:36
Hi,

Does networkrequest expect a certain file format?
Meaning, can I get back a json data set or an XML data set?

Thanks.

Herb

yvonne.milne
2013-10-08, 05:05
Hi Herb,

I don't think the type of file matters to NetworkRequest.getfile() - you just need to handle the file appropriately once you've 'got' it. You could use FOPEN() (http://www.lianja.com/doc/index.php/FOPEN()), FGETS() (http://www.lianja.com/doc/index.php/FGETS()) etc. for customized handling if required, e.g.


oRequest = createObject("networkrequest")
oRequest.getfile("http://maps.googleapis.com/maps/api/geocode/xml?address=100 valentine street 08904&sensor=false","myfilename.xml")
fd = fopen("myfilename.xml")
do while not feof(fd)
m_string = fgets(fd)
if at("<lat>",m_string) > 0
? strextract(m_string,"<lat>","</lat>")
endif
enddo
fclose(fd)

Regards,

Yvonne

hmischel@diligentsystems.com
2013-10-08, 10:55
Thanks Yvonne,

I must admit that I was not aware of the strextract function.
That is very helpful.

Herb

SpringBox
2014-01-16, 14:19
Hi Guys

Our existing VFP Apps consume many different web services from banks, finance houses, insurance companies etc and we use West-Wind to fill in the gaps very effectively.

We have tried & tried to use our existing West-Wind setups in Lianja but they just don't seem compatible. None of the prgs or classes will run and the #INCLUDE statements don't seem to work etc etc. and there are lots of creashes.

So we are trying to use Lianja for simple HTTP GETs but struggling with that too. For instance our existing UK parameterised postcode lookup code of :


lpostcode = "CW82BA" && valid UK postcode
lidentifier = "41.42.43.44" && relevant IP
lusername = "someusername"
lpassword = "somepassword")


loSOAP.AddParameter("postcode",lpostcode)
loSOAP.AddParameter("identifier",lidentifier)
loSOAP.AddParameter("username", lusername)
loSOAP.AddParameter("password", lpassword)

lcXML = loSOAP.CallWSDLMethod("getThrfareAddresses") && calls getThrfareAddresses method & works great

should work in Lianja as :

response = posturl("http://www.postcoderwebsoap.co.uk/websoap/websoap.php/getThrfareAddresses", 30,array("type" => "Content-Type: application/x-www-form-urlencoded"), ;
"postcode=lpostcode&identifier=lidentifier"&username=lusername&password=lpassword")

returns nothing but no error

Also tried

response = posturl("http://www.postcoderwebsoap.co.uk/websoap/websoap.php/getThrfareAddresses", 30, ;
array("type" => "Content-Type: text/xml"), ;
"PostcodeSend.xml")

where PostCodeSend has all the parameters in an xml file or a variable.

Same answer - returns nothing....

This is about as simple as it gets - what are we missing?

Thanks in advance

SprinBox

yvonne.milne
2014-01-17, 08:07
Hi SpringBox,

I'd need to look further into the SOAP scenario, but if you use the REST version of the service along with the search key, the geturl() function and the network request object getfile() and getdata() methods return the data in JSON format. e.g.


mykey = "<postcoder search key>"
mypostcode = "CW82BA"

//// REST geturl()
? geturl("http://ws.postcoder.com/pcw/&mykey/address/uk/&mypostcode")

//// REST network request object getfile() and getdata()
oRequest = createObject("networkrequest")
oRequest.getfile("http://ws.postcoder.com/pcw/&mykey/address/uk/&mypostcode","myfile.json")

jstring = oRequest.getdata("http://ws.postcoder.com/pcw/&mykey/address/uk/&mypostcode")
? jstring

Regards,

Yvonne

SpringBox
2014-01-17, 10:13
Hi Yvonne

THANK YOU !! :))

Still don't quite understand why ours did not work but now have a working solution. Were the extra parameters causing the issue?

These web service calls are vital for so many apps (the problem is there is no such thing as standard xml - every service provider seems to do their own thing !!).

Thanks for your help

Simon

SpringBox
2019-10-07, 12:15
Hi Guys

Working with calling web services

response = geturl("http://ws.postcoder.com/pcw/&mykey/street/uk/&mypostcode")

works fine but now takes 60 seconds to return anything.

The same string entered in to a browser returns an instant response.

Is there any reason why it is taking so long?

Thanks

Simon

barrymavin
2019-10-07, 12:26
Normally issues like this are related to the fact that you do not have dns setup properly for your machine.

Look back on this thread and use the network request object which may help.

barrymavin
2019-10-07, 13:12
Submit a ticket containing your key and I will test it on my machine.

SpringBox
2019-10-07, 14:24
Thanks Barry

Networkrequest solved issue (very fast now) but guys beware of the extra square brackets preventing json_decode() from working !!

Cheers

Simon

SpringBox
2019-10-07, 15:07
We are migrating lots of web calls to Lianja and it is SO much easier than using a 3rd party library - WestWind seems best.

However there is one SOAP service that we are struggling with.

This is existing code was ported over from a VFP application which we know works well ie URLs etc

We are using :

oRequest = createObject("networkrequest")
oRequest.async = .f.

oRequest.putFile("https://soap.xxxxxxxxxx.co.uk/tradeservice/servlet/messagerouter", "xxxxxSend.xml")


returns "unknown URL" but we know the url is correct.

The xxxxSend.xml contains all the passwords etc in an xml file format and there are no headers that have to be set.

We have tried putFile() and postFile() and have tried replacing the filename in inverted commas with a variable containing the same.


Just for info, the VFP that works is a WestWind call.

oHTTP.nHttpPostMode = 4 && type = xml & must be called prior to AddPostKey()
oHTTP.AddPostKey() && Clear POST buffer
oHTTP.AddPostKey(lcHPISendString) && text not object

lcResult = oHTTP.HttpGet("https://soap.xxxxxxxxxx.co.uk/tradeservice/servlet/messagerouter")


Any thoughts?

Cheers

Simon

barrymavin
2019-10-07, 16:25
You are using putfile() where you should probably be using postfile().

See the doc.
https://www.lianja.com/doc/index.php/NetworkRequest

You are also uploading a file with no authentication. I.e. no username and password.

Please stop cross posting in this forum. Choose a more suitable forum such as Lianja Application Framework.

SpringBox
2019-10-07, 18:19
Hi Barry


Sorry - was trying to do the right thing by extending an existing web service post - will do so in future.

In this case all the authenticaton is contained within the xml file itself.

postfile() produces the same result as putfile() - returns .F.

Does it need to be run in runtime mode, rather than development mode to work?

Cheers

Simon

barrymavin
2019-10-08, 01:14
No it’s not runtime only.

You can SET DEBUG ON before issuing it in the console then quit Lianja and look in the debug file which may help you

or

Submit a ticket requesting assistance. Provide the url and an xml file that you know works.

SpringBox
2019-10-08, 06:38
That was really useful - thanks

Looks like this needs to be an HTTPGET.

Is there a way to preload the HTTPGET request with a parameter (data)?

Thank

Simon

HankFay
2019-10-08, 12:43
Simon,

Do you really have a user who uses unsecured transfer protocols?

If you need secured transfers (https, ftps, sftp) take a look at Chilkat controls, which do these things (among others) in strict conformance with web standards, made easy for developers (with loads of examples), and provide intelligible "lasterror" results (which can be enhanced beyond that with a settable flag). And they are integrated as a Chilkat extension.

Hank

SpringBox
2019-10-10, 14:40
Thanks Hank

Will look at that

There is a (Lianja) HTTPS Upload File to Web Server which looks promising.

Cheers

Simon

SpringBox
2019-10-14, 10:51
Hi Guys

Finally solved it; as we thought, it was Headers..

Thanks Hank - whilst looking through the Chillcat documentation, I thought I would give the same headers a go in Lianja et voila :


oRequest.setHeader("SOAPAction", "https://xxxxxxxxxxxx.co.uk/xxxxxxxxxxx")
oRequest.setHeader("Content-Type","text/xml; charset=utf-8")

Now works great.



Also the behaviour of postfile() is different from the documentation.


When you call :

lretval = oRequest.postfile("https://xxxxxx.com/xxxxxxxx", "DataSend.xml")

The data in DataSend.xml is sent with the request as expected and then the response overwrites the file DataSend.xml. In other calls you have a send file and a result file. Just one to be aware of. Here lretval evaluates to T/F.

Thanks everyone for their input.

Cheers


Simon





Maybe the above could be included in the documentation so others can find it too.

pauln
2019-10-14, 22:24
Thanks for sharing Simon...
Regards Paul.

barrymavin
2019-10-15, 02:19
Hi Simon,

In the next build I have added an additional argument to postFile() and putFile() i.e. the outfilename that receives the result of the post and put operations.

See Doc.
https://www.lianja.com/doc/index.php/NetworkRequest

SpringBox
2019-10-16, 18:41
Thanks Barry

That's great - makes perfect sense. Code amended.

Cheers

Simon

SpringBox
2019-10-16, 19:21
Hi Barry

Not sure the new feature has yet been added to the Cloud Server as the newest version available is still

library/LianjaWebFramework/LianjaHtmlClient-5.0RC71.min.js

By the way - app runs really well on HTML5 web server.

Thanks


Simon

barrymavin
2019-10-16, 21:13
Hi Simon,

I am not sure what yiu are referring to.

The Lianja Web Framework library is generated when you run an app in a browser. Which you always will do before deployment to test it.

That library has nothing to do with the networkrequest functionality which is server-side handled by the Lianja Cloud Server.

HankFay
2019-10-17, 09:40
Hi Simon,

When you set the App to Release mode, the uncompressed version of the LianjaHtmlClient.js gets minified on the first such run, and that's what gets pushed to the client.

So if you haven't deployed an app in Release mode since 73 was released, you won't see the minified version.

Hank

SpringBox
2019-10-20, 10:26
Thanks Hank

Yes got our heads around that now.

Cheers

Simon