|
||||||||||||||||||||||||||||
When programming for the web using OECGI3, whether using O4W or just directly, occasions arise when the developer needs to query HTTP headers sent by the client that aren't included in the default information passed forward by OECGI3. Additionally, it can become necessary to set HTTP headers for return to the client. The following article discusses how to achieve such functionality.
Querying HTTP HeadersBy default OECGI3 passes through a subset of the available HTTP headers. However there may be times when access to additional headers is required. For example, recently when writing a multi-lingual O4W application we wanted to determine which language the user who was attempting to use the system had set their browser to. Knowing this would allow us to deliver back content in their native tongue.To achieve this we'd have to examine the HTTP_ACCEPT_LANGUAGE header value. Examination of the HTTP_REQUEST passed through showed that this was not available to us.Fortunately a little known registry entry saved the day for us. The registry key value "AdditionalValues" allows the specification of a comma delimited list of additional HTTP header values that should be passed into the HTTP Request. The first value will be inserted in field 27, the second in field 28 etc. Please note that this behaviour is likely to change with OpenInsight X when the list of additional values will likely be made multi-valued in field 30. So for our application we modified the registry entry (Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\RevSoft\OECGI3) as follows :- Which resulted in a modified request with our desired values :-
It was then a simple programmatic exercise to extract the language and return the correct pages to the client.
Setting HTTP Headers
When interacting with external APIs, it can sometimes be necessary to set specific HTTP header values - to communicate, for example, the results of an operation via the Status HTTP Header element. There are two ways of approaching this from within OpenInsight - using the INET API routines or playing directly with the labelled common used for setting HTML Headers.
INET API Routines
OpenInsight ships with a number of routines designed to make interacting with the return results of an INET procedure easier. There are currently five of these. They are actually documented in the help file "OpenInsight and Internet", but if, like me, you expect to find system subroutines documented in the Programmer's Reference Manual, I redocument them here with a little more detail.
INETAPI_SETCONTENTTYPEThis takes one parameter - the content type to set. For a definitive list of possible content types see the IANA site. Content type is used by the rendering browser to know how to treat the information that follows. If the content type is found to be incorrect, browsers will examine the beginning of the information looking for a "magic number" that identifies the file type. If that fails browsers will resort to checking the extension of the file.INETAPI_SETNOCACHEThis takes one parameter, a boolean. If set to 0 then the header is updated to contain an EXPIRES value of 0 and a PRAGMA value of "No-cache". That is to say, somewhat counterintuitively if you want to set no caching you pass FALSE$ not TRUE$. Regretfully this is likely to be ignored by browsers as the Pragma directive is an HTTP 1.0 standard designed for requests only - not responses.If you as a developer wish to control caching correctly you should use the CACHE-CONTROL header value which is discussed here and defined in the RFC here. With CACHE-CONTROL you can set whether caching is allowed only at the browser or also at proxy/web servers and you can specify how long the information can be cached for. CACHE-CONTROL can be used in conjunction with the section below on setting custom headers. OpenInsight X will modify this behaviour to use the CACHE-CONTROL directives. INETAPI_SETSTATUS
This takes one parameter - the status code to set. A list of all valid codes may be found in the RFC here.
INETAPI_SETREDIRECTThis routine takes four parameters :-
This is perhaps most easily understood with a simple example. Imagining that we have invoked a program using OECGI3.EXE such as INET_LOOKUP as follows
inet_Lookup?First=John&Second=Smith&Third=Male
and within our program we decided that we wished to redirect to a program called INET_RESULT but only passing in the gender, we would
call inetApi_SetRedirect("inet_Result", request, 1,"First,Second")
This would result in the STATUS header being set to 302 for a redirect and the LOCATION header being set to the fully qualified location of inet_Result?Third=Male.
INETAPI_SETCOOKIE
This takes eight parameters and these may be field mark delimited to permit the setting of multiple cookies at once. The parameters are as follows :-
If inetApi_SetCookie were invoked as follows
call inetapi_setCookie("Mario","Brothers", 17000, 8000, |
"", ".sprezzatura.com", 1, 1) the SET-COOKIE header would be set to "Mario=Brothers; expires=Thu, 17-07-2014 02:13:20 GMT; path=/; domain=.sprezzatura.com; httponly; secure" Setting Custom HeadersIf you wish to set any headers other than the ones catered for above, it is actually very straightforward. Just include the insert INET_HEADERS. This includes a labelled common area with two variables - the headers and their values as field mark delimited arrays. Then depending upon the header type being set, you would either replace an existing value with the new value, or append to the list. For example if you were setting STATUS you would only want one STATUS value in the header, but if you were wishing to set cookies you might have more than one.
locate headerName in inet_Header_Names% using @FM setting loc else null
inet_Header_Names%< loc > = headerName inet_Header_Values%< loc > = headerValue
For those of you who've expressed an interest, the internal Sprezzatura OpenInsight Coding Standards document is now available for download from our Whitepapers Section.
Regular users will know that calls to SET_PROPERTY and GET_PROPERTY can be made more efficient by passing @rm delimited arrays to the routines rather than making multiple individual calls.
Although using the @rm concatenation method can lead to improved performance you need to be aware of how it is actually implemented, otherwise it can lead to some subtle bugs that may be hard to track down. This is because internally there are two types of properties; PS (Presentation Server) properties, and Synthetic properties, and the order in which they are processed when combined together could cause your code to behave in a manner that you are not expecting. The PS properties are implemented at a low-level inside the Presentation Server (OINSIGHT.EXE) and generally deal with “real” visual properties such as TEXT, SIZE, LIST and so on: basically they wrap the low-level UI attributes of forms and controls. Access to these properties is via two functions called ps_Get_Property and ps_Set_Property. They are not documented but are used internally by the normal Get_Property and Set_Property functions as needed. The Synthetic properties are implemented in Basic+ and deal with Form IO logic, data conversion and suchlike; i.e. the things that are specific to OI rather than Windows. When you don’t use the @rm concatenation method then Get_Property and Set_Property first try to process the request as a Synthetic property, and, if not found, it is then passed on to the PS. This obviously doesn’t cause any issues as no concatenation is involved. When you do use the @rm concatenation method both Get_Property and Set_Property first pass the arrays onto the PS, which deals with the properties it is responsible for. After that the arrays are scanned for any Synthetic properties and processed accordingly. In many cases this would have no effect unless the order in which the properties are called is critical. Consider the following example:
* // Set the TEXT _without_ firing a CHANGED event
* // (This will NOT work!) objxArray = "SYSTEM" propArray = "BLOCK_EVENTS" dataArray = TRUE$ objxArray := @rm : @window : ".EDL_NAME" propArray := @rm : "DEFPROP" dataArray := @rm : strName objxArray := @rm : "SYSTEM" propArray := @rm : "BLOCK_EVENTS" dataArray := @rm : FALSE$ Call Set_Property( objxArray, propArray, dataArray ) In this case both BLOCK_EVENTS property calls (PS properties) will be processed before the DEFPROP call (a synthetic property), meaning they will have no effect and the CHANGED event will fire. Consider yourself warned! This is taken from the document "OI Coding Standards" published by Sprezzatura. |
||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||