Omnis Technical Note TNWE0018 Dec 2007

Using Omnis HTTP Commands

For Omnis Studio 4.x or above (non-Unicode)
By Omnis Tech Support

Problem

How do I get a JPG picture into a binary or a picture variable, in order to display it in a remote form? More specifically, the picture file is not available as a file in the local file system, but located somewhere in the Internet (for example, it could be the following picture: http://www.omnis.net/images/omnis_logo1.png located on the Omnis web site).

At first sight, it seems easy to display such a picture, since there are the JPEG and Omnis Picture controls available for remote forms. But again, the problem is how do you get the picture from a remote server location into the JPG or Picture control in the remote form? The answer is to use the Omnis HTTP commands to return the picture into Omnis.

HTTP Request and HTTP Response

Before we dive into the details regarding the Omnis HTTP commands, let us look at what happens when a picture, or any other data, is requested from a remote location via HTTP. If you enter the URL for a file, such as a picture as above, into the address line of a browser (Firefox, Internet Explorer, ...) the file or picture in this case is displayed in the browser. What is happening in the background? The browser (as a client) sends an "HTTP Request" to the web server www.omnis.net and requests the file with the URI /images/omnis_logo1.png. The server sends an "HTTP Response" back to the browser which contains, among other things, the required file which is displayed by the browser. The format of the data packets for the request and the response are in a standard format, as specified in RFC 2616, see: www.faqs.org/rfcs/rfc2616.html

The request mainly consists of a header in which the client identifies itself and specifies the required information and the format. The server answers with a response package which again consists of a header and the body with the required information.

The HTTP header in both cases is transferred as standard ASCII text and therefore can be caught by appropriate Packet Sniffer programs (e. g. Wireshark, formerly: Ethereal) and read without any recoding. See for example: www.wireshark.org

They consist of single lines which are completed by a carriage return (CR = ASCII Code 13) and a linefeed (LF = ASCII Code 10) each. In each line, a value is assigned to a field, the format is <fieldname> ":" <value>. Between header and body there is a blank line. So in front of the body the string CR+LF+CR+LF is displayed.

Omnis as a browser?

Omnis has some 4GL commands to execute an HTTP request/response cycle. To come back to the original problem, we can use these commands to return a picture from a remote location. Firstly, Omnis has to send an HTTP request to the server to retrieve or "get" the image file. This works with the following code ("host" and "uri" are local variables of the type Character, "socket" of the type Long Integer):

Calculate host as 'www.omnis.net'
Calculate uri as '/images/omnis_logo1.png'
HTTPGet (host,uri) Returns socket

If the request is accepted, the variable "socket" contains a positive value. For this request, Omnis sends the following standard header:

GET /images/omnis_logo1.png HTTP/1.1
Host: www.omnis.net
Accept: */*
User-Agent: Omnis Software - OMNIS

If you want to define additional header parameters in the request or to enhance the URI using cgi parameters, you can enhance HTTPGet using optional parameters; the Omnis code would then look like this:

Do cgiList.$define()
Do cgiList.$cols.$add('attribute',kCharacter,kSimplechar,2000)
Do cgiList.$cols.$add('value',kCharacter,kSimplechar,2000)
Do cgiList.$add( ... )
Do headerList.$define()
Do headerList.$cols.$add('name',kCharacter,kSimplechar,2000)
Do headerList.$cols.$add('value',kCharacter,kSimplechar,2000)
Do headerList.$add( ... )
HTTPGet (host,uri,cgiList,headerList) Returns socket

With a valid socket you can now fetch the data from the server with an additional command and store them at first in a variable "buffer" (of the type Character):

HTTPRead (socket,buffer) Returns charCount

The data may not be completely fetched with the first HTTPRead, therefore as a precaution, you can read in a loop (the variable "bufferPart" is also of the type Character). So the complete code to read the HTTP Response is:

If socket>0
Calculate buffer as ''
Repeat
Calculate bufferPart as ''
HTTPRead (socket,bufferPart) Returns charCount
Calculate buffer as con(buffer,bufferPart)
Until (len(bufferPart)=0)|(charCount=0)
HTTPClose (socket)
... (see below) ..
End If

After all data have been fetched, it's important to use the HTTPClose (socket) command. It's interesting at this stage to look at the content of the variable "buffer"; it starts with:

HTTP/1.1 200 OK
Server: Zeus/3.3
Date: Tue, 08 Dec 2007 12:34:57 GMT
Content-Length: 4351
Content-Type: image/jpeg
Last-Modified: Thu, 01 Dec 2007 10:04:25 GMT

A blank line and then the binary data follows after the header.

If an invalid URI was sent in the request, for example, the file "studio4_box.jpg" is not available in the sub-directory "/products/studio/" of the web server, the number 2xx will not be returned, and typically 404 would be returned. So a fool-proof implementation should check this number in the first line and see whether or not the first digit is equal to 2. For example:

If not(mid(buffer,pos(' ',buffer)+1,1)='2')
OK message Error {[uri] not found}
Quit method
End If

Now you have to separate the body from the header. Remember that everything after the blank line is reference data. Therefore you can declare the following local variables:

posEmptyLine (Long integer)
bufferStripped (Binary)
picFormat (Character)

and the instance variable:

iPicture (Binary)

and add the following Omnis code in front of the End If command:

Calculate posEmptyLine as pos(chr(kCr,kLf,kCr,kLf),buffer)
Calculate bufferStripped as mid(buffer,posEmptyLine+4,len(buffer))
Calculate picFormat as pictformat(bufferStripped)
Calculate iPicture as pictconvfrom(picFormat,bufferStripped)

You can assign the variable iPicture to the $dataname property of the JPEG control and the image will be displayed.