Asynchronous HTTP Requests
There is no end in sight to the growth of online content and web services. Sooner or later your application will need to communicate with an online service for new functionality. You may need to interface your OpenInsight based application with a web API or simply need to download a file. This blog article walks through extending the built-in functionality to provide a more feature rich user experience.
Out of the box OpenInsight 9 includes the function OLE_GetWebPage for accessing online content. It’s easy to get this function working and it does a good job at providing basic access. The help file indicates it is a wrapper around the Microsoft XMLHTTP COM object and abstracts a lot of the advanced features provided by the object.
This blog article provides a working example to directly interface with the XMLHTTP COM object for asynchronous communication and downloading binary files. (Disclaimer: Our tests have shown that downloading files larger than 100MB can become problematic. We believe this is due to the requirement that OpenInsight handle the entire request as a single process and thus constraining resources. Another approach might be necessary if a more robust solution is required.)
Asynchronous communication provides a richer user experience because it enables the application to respond to user activity which is especially useful over slow connections or during large downloads if the users wants to end the download early. OLE_GetWebPage operates synchronously which halts program execution until the request has completed or timed out.
With OLE_GetWebPage it’s not possible to download binary content such as images or compressed files unless we directly interface with the XMLHTTP COM object (along with additional assistance as documented below.)
This article is comprised of three parts. The first part explains the VBScript wrapper which is needed to help OpenInsight with binary downloading. The second part reviews our OpenInsight example program, SRP_HTTP_ASYNC_EXAMPLE, and how the XMLHTTP COM object and VBScript wrapper are used together. Finally, the third part explores another example program, SRP_HTTP_ASYNC_EXAMPLE2, shows how to replace both native OpenInsight COM technology and the VBScript wrapper in favor of just the SRP COM utility.
The VBScript wrapper VBS_ASYNC_DOWNLOAD is an insert record with a VBScript program that exposes the XMLHTTP COM object to OpenInsight. Follow along with this example and download VBS_ASYNC_DOWNLOAD.txt and save it as an insert record in your application.
It is possible to directly communicate with the XMLHTTP COM object but without the wrapper it becomes difficult to do when dealing with binary data. This is because the responseBody property of the XMLHTTP COM object returns the data in a SAFEARRAY, a data type not supported in OpenInsight. Thus, we’ll need an additional helper object to process the binary data. We won’t discuss the wrapper line by line but will call attention to the three important functions:
The example OpenInsight routine uses the wrapper by calling DownloadAsync() function to begin a download. This function returns immediately and can be checked periodically by calling getDownloadState() to monitor when the download finishes. The final function getDownloadContent() returns the downloaded content or the path to a file containing the content (if binary).
OpenInsight Example Code
The example OpenInsight BASIC+ routine SRP_HTTP_ASYNC_EXAMPLE demonstrates how to call the VBScript wrapper and asynchronously download text or binary content. Let’s walk through the key points to the program starting from the top.
// Create a VBScript control
// Call the wrapper and start the download
RetVal = objDLScript@->Run(‘DownloadAsync’, URL , isBinary)
Here our example program calls a self-contained GoSub to load the VBScript wrapper from the compiled insert record into the COM handle objDLScript@. If it was already loaded in memory the object is re-used.
Once loaded our program then calls another self-contained GoSub to interface with the VBScript wrapper by using the Run method to call the DownloadAsync function. The URL of the resource to download is passed in along with a boolean value indicating if the return type should be treated as binary data.
The program then sets up a loop that runs until our user specified timeout value is reached or the download completes. Each iteration of the loop calls another self-contained GoSub to continue application processing. Additionally, another self-contained GoSub is called to check for a completed download as follows:
// Call the wrapper to check if the download is finished.
Response = objDLScript@->Run(‘getDownloadState’)
When Response equals HTTP_COMPLETED$ the download is finished and the processing loop ends.
Finally we get the downloaded data by calling:
// Return the downloaded content as a string or path to a file
// containing the binary download data.
ResponseText = objDLScript@->run(‘getDownloadContent’)
The variable ResponseText will contain either the download content if isBinary = False$ when DownloadAsync is called or a path to a temporary file containing the content if isBinary = True$.
OpenInsight Example2 Code
For those wanting to maintain a more BASIC+ focused solution we offer SRP_HTTP_ASYNC_EXAMPLE2. Technically this solution still relies upon an external library (SRP COM), but the BASIC+ coding is much closer to what a pure solution based on native OpenInsight COM would look like. In fact, the SRP COM library was designed to work very similarly to the OpenInsight COM library but updated to be a little more robust.
Therefore, where SRP_HTTP_ASYNC_EXAMPLE passes control into the VBScript wrapper, SRP_HTTP_ASYNC_EXAMPLE2 brings the equivalent VBScript logic directly into BASIC+. We will leave it to the reader to study these routines in greater detail. Suffice to say that SRP_HTTP_ASYNC_EXAMPLE2 was written using the same structure as SRP_HTTP_ASYNC_EXAMPLE so side-by-side comparisons are easy to do.
Whether using the VBScript wrapper or just SRP COM, you have a simple example of how to utilize the XMLHTTP COM object to provide a more feature rich experience for the user. Both solutions serve as a base for you to customize and further extend the use of the XMLHTTP COM object to not only download content but also send data to the remote server…a topic which may be covered in a future blog article. For a complete list of XMLHTTP COM options see the MSDN documentation on XMLHTTP request members.