Results 1 to 5 of 5

Thread: [Answers] Web service

  1. #1
    Lianja MVP
    Join Date
    Dec 2012
    Location
    Croatia, Zagreb
    Posts
    1,135

    [Answers] Web service

    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.
    Code:
    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


    Code:
    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:

    Code:
    myobject = xml_decode_file("myfilename.xml", "GeocodeResponse")
    ? myobject['status']
    For larger/more complex amounts of data I would go with NetworkRequest.



    Q:
    I'm using posturl() to test a webservice written in Lianja. When going through a firewall, I'm getting a rejection because there is no host header. So, I added the host header like so:
    Still no joy: before I start sniffing, I thought I'd ask whether posturl can handle multiple header items.

    Code:
    headers = array("type" => "Content-type: application/json","host" => "yyyyyy.xxxxxx.com:8001")
    A:
    Yes it can.
    The host should not contain the port number and it should be resolvable by DNS on the target system, Typically I just use localhost for that.
    Also You must be careful to define the HTTP headers correctly. e.g.

    Code:
    headers = array("type" => "Content-type: application/json","host" => "Host: localhost")
    Notice that the dynamic array "headers" is enumerated and each element sent in the HTTP headers. The names of the elements in the dynamic array are not important.
    Some HTTP servers can be "picky" and require proper case to be used in the headers. You can find details at the link below.
    http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
    Notice for example "Content-type" should be "Content-Type" (case sensitive).



    ​All topics in [Answers] alphabetically:http://www.lianja.com/community/show...ll=1#post12352
    Last edited by josipradnik; 2016-03-16 at 03:44.

  2. #2
    Lianja MVP
    Join Date
    Dec 2012
    Location
    Croatia, Zagreb
    Posts
    1,135
    Q:
    We are looking to write a simple data import webservice.
    ie 3rd party submits an pre-defined xml stream to our server, webservice puts data in the relevant table fields. No interface required.
    A:
    1. Install Lianja Cloud Server alongside your App. This will access the same data as your desktop RDP App.
    2. Write a small .rsp page that accepts the XML data, parses it and inserts/updates your tables.

    A2:
    There are examples once you have installed the Cloud Server. These demo the contents of these special arrays. Look in the examples directory then type http://localhost:8001/examples/example_xxx.rsp where xxx is the example name from the examples directory.
    The arrays contain the same members as in PHP without the leading $, so the $_server PHP array is called _server in Lianja.
    The _server["body"] contains whatever it was that was posted. You should use POST rather than GET which sends everything in the URL and has smaller size restrictions in the browser.
    Lianja Cloud Server supports ActiveX so you should be able to use oledb to update your VFP tables.
    Depending on the complexity of the XML you are sent you may be able to use xml_decode() or the xquery functions.
    If you do not have the time or inclination to do any of this you can have us do it for you and give you back the .rsp web service.

    A3:
    You need to POST to your web service e.g. mywebservice.rsp?arg1=hello&arg2=world and include the XML/JSON as the data.

    Code:
    <%@ Language=VFP %>
    <html>
    <head>
    </head>
    <body>
    <%
    private p_arg1 = getParameter("arg1", "")
    private p_arg2 = getParameter("arg2", "")
    private p_data = _server["body"]
    
    // p_data now contains your XML or JSON that was POSTed to the web service.
    
    // Now use the xquery() function to extract the information you want and then write back a response if required
    
    //
    // Everything you output using e.g:
    //
    // ?
    // echo
    // text raw...endtext
    //
    // is sent back to the client 
    
    
    %>
    </body>
    </html>
    There are no args in a HTTP POST. Everything is in the body.



    You have a desktop app that is running on user desktops.
    You want to somehow get information from the running app and return that information as JSON, XML or an HTML page.
    There is an simple http server built into your Lianja Apps that run under the App Center. By default this server listens on port 8002 but this is configurable (in the App settings) and handles asynchronous service requests while your App is running.
    So while an App is running, from another App you can query it e.g.:

    Code:
    result = getURL("http://localhost:8002/desktopwebservice/dws_getinfo?customerid=ALFI")
    The web service name follows /desktopwebservice/ in the URL and is a normal program or proc. In this case we have a script named dws_getinfo. It is good practice to name these consistently and place them in the library directory. I would recommend prefixing your desktop web services with dws_.

    Code:
    // In this example, the URL will contain "/desktopwebservice/dws_getinfo" and args will contain "customerid=ALFI"
    // dws_getInfo.prg in the library 
    private p_url
    private p_arg
    private p_args = explode("&", p_arg)
    private p_customerid = getMember("p_args", "customerid", "")
    return "{'url': '&p_url, 'customerid': '&p_customerid'}"
    Your service may return a JSON encoded object (as shown above), an XML string, an HTML string or plain text.
    If the result returned starts with "file:" then the file specified e.g. "file:mytempfile.txt" is read and the result is sent back to the client. This provides the ability to query large amounts of information not limited by internal string length.
    If the result returned starts with "tempfile:" then the file specified e.g. "tempfile:mytempfile.txt" is read and the result is sent back to the client. The file mytempfile.txt is then deleted.
    Notice that in the example above no file extension was given to dws_getinfo so ".prg" (Lianja/VFP script) is assumed. You could also specify:
    Code:
    result = getUrl("http://localhost:8002/desktopwebservice/dws_getinfo.js?customerid=ALFI")
    or
    Code:
    result = getUrl("http://localhost:8002/desktopwebservice/dws_getinfo.php?customerid=ALFI")
    or
    Code:
    result = getUrl("http://localhost:8002/desktopwebservice/dws_getinfo.py?customerid=ALFI")
    or
    Code:
    result = getUrl("http://localhost:8002/desktopwebservice/dws_getinfo.rsp?customerid=ALFI")
    or
    Code:
    result = getUrl("http://localhost:8002/desktopwebservice/dws_getinfo.jssp?customerid=ALFI")
    This is not designed to replace the Cloud Server which handles multiple concurrent requests but rather to provide a means of introspecting running apps and consolidating information from them.
    It is not difficult to see how you could use this to great effect with desktop LAN apps in a Web App that uses a .rsp page that queries information from the various clients running Lianja Apps.
    Tip: remember to use SAVE/RESTORE DATASESSION as these web service requests are handled asynchronously while your App is running.
    Tip: you could specify an apikey=value on the URI and the authenticity of the apikey will be verified when the desktop web service request is received. The API key is an attribute in the App settings. There is a default key generated for you. Look in the App settings for it.



    Q:
    We have been asked for a webservice that does the full .NET thing ie (HTTPS/WSDL/Schema/SOAP etc) but if we can get them to just do a simple POST (credentials are in the xml)
    A:
    The desktop web service API does not currently handle POST operations. It is purely for HTTP GET operations.

    It should not be used for heavy usage as it does interfere with the event dispatching in the main GUI thread and will slow user response down if requests are made continually. In that case you should be using the Lianja Cloud Server which is much more functional and handles HTTPS through the IIS/Apache extension.

    If you have been asked for the whole kitchen sink of ways to call a web service, better to formalize an API that they should use to interact with your application and let them know the format that requests would be made.

    POSTing requests and parsing the XML _server["body"] is all you really need to do. You can authenticate using an API key and/or a session cookie. Any cookie created on the server and sent back to the client (just set _cookie["name"] = value) cannot be altered or deleted on the client. These are known as session cookies and are protected by the browser.



    ​All topics in [Answers] alphabetically:http://www.lianja.com/community/show...ll=1#post12352
    Last edited by josipradnik; 2016-03-16 at 03:45.

  3. #3
    Lianja MVP
    Join Date
    Dec 2012
    Location
    Croatia, Zagreb
    Posts
    1,135
    Q:
    I am returning a result set using print_json(aresult) and I want to include the "Content-type: APPLICATION/JSON"
    A:
    At the top of your .rsp page
    Code:
    Response.contenttype = "Application/json"
    <%
    response.contenttype = "..."
    %>
    it is Lianja/VFP.

    case insensitive.

    Try removing all the HTML tags. You are generating JSON and outputting HTML.

    Code:
    <html>
    <head>
    <meta http-equiv="Content-Type" content="application/json; charset="UTF-8" />
    </head>
    <body>
    ...
    </body>
    </html>
    Remove those.

    The response.contenttype = "application/json" should be being sent then your JSON data.



    Q:
    NetworkRequest. I have had a go at uploading an XML file to my website. I have some confusion about what "args" were required, my solution seems to involve some redundancy. This is what I thought might work (It doesn't!)
    Code:
    // Upload xml file to the web
    oRequest = createObject("networkrequest")
    oRequest.async = .f.
    oRequest.username = "myUserName"
    oRequest.password = "myPassword"
    oRequest.putFile("ftp://www.timelinecontinuum.com/9-11.xml?username='myUserName'&password='myPassword' ",xmlName)
    y = oRequest.ErrorString
    In debug, after oRequest.username, I see:
    Code:
    ? oRequest.username
    ^
    Property/Variable 'USERNAME' not found
    After the putFile request I get:

    Code:
    Logging in to www.timelinecontinuum.com failed: authentication required
    A:
    You can however only use http:// or https:// not ftp:// with "NetworkRequest"
    If you want to upload using sftp i would recommend that you look at using the chilkat components for Lianja from http://www.chilkatsoft.com/lianja.asp



    Q:
    I would like to have the targetFile and source file both coming from variables.
    It works Ok with source file as xmlName where xmlName contains something like "C:\Lianja\Data\timeline\9-11.XML".
    But targetFile resists my attempts to use a variable. I would like to pass through a file name and a subdirectory on my Host.
    So TargetFile would be something like "/DataXML/filename.xml".
    A:
    You can substitute variables into strings using &varname. which would let you use variables. Otherwise you can just create the character variable and use that as an argument to the method call.
    Try omitting the / from the start of the target file. Does that directory already exist and if so does it have the correct permissions.
    it may be that the target can only be a filename.
    One solution would be to have a username that when logged in uses a different directory on the ftp server but that would require some configuration and is Server dependent.



    Q:
    I want to upload an xml file called "MH370.aspx" to a directory on my web site "www.timelinecontinuum.com".
    After your reply I have tried various combinations of the formats shown in the thread "http://www.lianja.com/community/showthread.php?1121-File-upload-and-download-in-Lianja" without success.
    The two attempts below give me the error "Method not allowed":
    Code:
    oRequest.putFile("http://www.timelinecontinuum.com/MH370.aspx","9999.xml")
    oRequest.putFile("http://www.timelinecontinuum.com/MH370.aspx?password='zermattb'&username='TM7o33XU' ","9999.xml")
    You can see I have some misunderstanding of what the params should be; and probably other misunderstandings that I am not aware of.
    A:
    You should be able to do this, replacing username, password, host/targetfile, sourcefile with the relevant details:
    Code:
    oRequest = createObject("networkrequest")
    oRequest.postFile("ftp://username:password@host/targetfile","sourcefile")
    The "Method not allowed" messages will be coming from the server, saying it doesn't accept HTTP uploads.
    As mentioned before, if it's an sftp server, have a look at the Chilkat components.



    ​All topics in [Answers] alphabetically:http://www.lianja.com/community/show...ll=1#post12352
    Last edited by josipradnik; 2016-03-16 at 03:54.

  4. #4
    Lianja MVP
    Join Date
    Dec 2012
    Location
    Croatia, Zagreb
    Posts
    1,135
    I wasn't suggested West-Wind for the web service: nothing I've used is easier than Lianja for creating a web service.
    I was referring to how you are creating the xml. If something else is creating it, you only have to check that it is generating ado xml, as that contains the schema within it and Lianja handles it natively.



    SOAP is considered passe' for web services, fwiw. Passing JSON gives you web mobility. JSON uses the JavaScript var types, which are universal.

    XML is also much longer than JSON: be sure they sent it in ADO format, as that's what Lianja handles for converting directly to cursors.



    Here's the line that works for me when sending JSON to an .rsp web service:

    Code:
    lcRet = posturl(lcUrl,0,array("Content-Type: application/json","charset: UTF-8"),lcJson,"c:\temp\mysite.txt")


    ​All topics in [Answers] alphabetically:http://www.lianja.com/community/showthread.php?2717-Answers


  5. #5
    Lianja MVP
    Join Date
    Dec 2012
    Location
    Croatia, Zagreb
    Posts
    1,135
    Lianja 3.4 provides cross-platform consumer/producer message processing functions which can be used very effectively with web services.
    These functions provide cross-platform messaging enabling you to offload slow processing e.g. send email, to a background service.

    On Windows the messaging functions are implemented using named pipes and on Linux using POSIX message queues.

    Firstly you create your “consumer” and run it as a scheduled task in Windows or a cron job in Linux:
    Code:
    local mqdes, msg, data
    
    // Create the consumer and wait for a connection
    mqdes = mqCreate(“unique_name_of_your_consumer”)
    
    // loop processing messages as they come in from multiple producers
    do while .t.
           msg = mqReceive(mqdes)
            if len(msg)=0
                loop
            endif
            data = json_decode(msg)
            // Now process the message which is now encoded as an object
            // …
    enddo
    Now the producer(s) code looks like this:
    Code:
    // Create the consumer and wait for a connection
    mqdes = mqOpen(“unique_name_of_your_consumer”)
    msg = json_encode(anobject)
    mqSend(mqdes, msg)
    mqClose(mqdes)
    Alternatively you can combine all the above code into a shortened version:
    Code:
    mqSendMessage(“unique_name_of_your_consumer”,  json_encode(anobject))


    Q:
    In a JavaScript application, I am trying to add a blank grid and then populate it later from an array using additems().
    I know this is not yet supported in custom sections, but I thought it may be possible in a standard section.

    A:
    https://www.lianja.com/community/sho...7702#post17702
    Custom grids which can be loaded from an external web service are now implemented in 4.0.1




    All topics in [Answers] alphabetically: https://www.lianja.com/community/sho...ll=1#post13748

    These answers are also systematized on the site "Lianja developer": https://lianjadeveloper.wordpress.co.../web-services/

Bookmarks

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Journey into the Cloud
Join us