Using Caché Server Pages (CSP)
HTTP Requests in CSP
[Home] [Back] [Next]
InterSystems: The power behind what matters   
Class Reference   
Search:    

The primary task of CSP is to provide dynamic content in response to incoming HTTP (Hypertext Transport Protocol) requests. This section covers the basics of how HTTP requests are handled by CSP.

HTTP is a simple protocol in which a client makes a request to a server. HTTP is a stateless protocol; the connection between a client and a server lasts only as long as it takes to service the request. Every HTTP request contains a request header which specifies the request type (such as GET or POST), a URL, and a version number. A request may also contain additional information. CSP automatically determines which HTTP requests it should handle, dispatches them to the appropriate class running on a Caché server, and packages up the request information into easy-to-use objects (such as the %CSP.Request object).
CSP Runtime Environment
The following diagrams show the architecture of CSP and HTTP requests:
CSP Architecture
The runtime environment of a CSP application consists of the following:
HTTP Request Processing
The following diagram illustrates the flow of events when CSP processes an HTTP request:
HTTP Event Flow
  1. The browser (or similar web client) makes an HTTP request.
  2. The web server determines that this is a CSP request and dispatches it to the CSP Gateway (installed on the web server). 2a The web server might serve static content, depending on your application configuration.
  3. The CSP Gateway repackages the request and sends it to the correct Caché Server.
  4. The Caché Server decodes the message and determines whether the request is for a static page or a CSP class.
    If the request is for a static file (such as an .html or .jpg file), the Caché server finds the file within the local file system and sends its contents back to the client. (Note that if you are serving files containing Unicode text, CSP uses the BOM to determine the correct encoding to use. The BOM must be present in Unicode text files.)
    If it is for a class, it determines which event handling class (part of your application) will process the event and invokes the class Page method.
  5. The output of the Page method or the static page is sent back to the CSP Gateway as an HTTP response.
  6. The CSP Gateway hands the HTTP response to the web server (specifically, the response is streamed back to the web server via the CSP Gateway).
  7. The web server returns the response to the web browser which then processes the response — in the case of HTML, it displays it.
Web Server and the CSP Gateway
An HTTP request starts when an HTTP client, such as a web browser, sends a message to a web server. The CSP Gateway is a DLL or shared library used by the web server (such as IIS or Apache) to process certain types of events. The CSP Gateway processes an HTTP request if the following conditions is true:
The CSP Gateway provides the following functionality:
  1. It provides minimal processing and off-loads most of its work to the Caché server providing more resources for the web server.
  2. It maintains a pool of connections to named CSP servers.
  3. It provides failover options to allow use of multiple, interconnected CSP servers.
CSP Server
The CSP server is a process running on a Caché server that is dedicated to serving requests from a CSP Gateway. Each Caché server may run as many CSP server processes as desired (subject to limits imposed by machine type; CSP servers are not counted in license calculations).
When handling stateless requests, each CSP server process can support requests from many different clients. In state preserving mode, a process is dedicated to process requests from one client, until state preserving mode is turned off.
Note:
One of the key strengths of Caché is that there is no real difference between an application server and a data server; you can configure your application to use as many, or as few, machines as necessary based on your requirements. This is done independently of application logic and database schema. Whether a particular system is an application server or a data server (or both) is simply a matter of configuration.
CSP Server Event Flow
When the CSP server receives a request from the CSP Gateway, it determines whether the request is for a static page or for a CSP class. If it is for a static page, it sends the page back immediately. If it is for a CSP class, it does the following:
  1. Determines what session this request belongs to. If none, it starts a new session.
  2. Makes sure that the request is processed in the correct Caché Namespace.
  3. Makes sure that the correct %CSP.Session object is available and creates an instance of the %CSP.Request object based on the information contained in the HTTP request. If any decryption is required, it does that as well.
  4. Constructs %CSP.Response object to allow application to modify response headers.
  5. Determines which class should handle the request and invokes its Page method (which, in turn, invokes the OnPage callback method).
CSP Server URL and Class Name Resolution
The CSP server determines which class to dispatch an HTTP request to by interpreting its URL. CSP disassembles a URL into the following components:
URL: http://localhost:[<port_no>]/csp/samples/object.csp?OBJID=2
URL Components
Component Purpose
http:// protocol
localhost web server address
[<port_no>] optionally, the port number that the web server is running on; defaults to port 80
/csp/samples/ directory
object.csp file name and extension
?OBJID=2 query
The protocol and server address are handled by the web server and are not relevant to the CSP server. The directory is used to determine which CSP application the URL refers to. Every Caché configuration can define a number of CSP applications, which are identified by the directory portion of a URL. Each CSP application, which can be created and modified on the Web Applications page in the Management Portal ([Home] > [Security] > [Web Applications]), specifies a number of settings used by all requests with a given URL directory. The most important of these are the Caché Namespace in which the request is to be executed and the authentication mechanism, which specifies what kind of connections to the application can be established.
The name of the class to handle the request is determined from the file name using the following algorithm, based on the CSP application:
For example, the CSP server dispatches this URL:
http://localhost:57772/csp/samples/menu.csp
to a class called menu contained within the package csp running in the Caché namespace associated with the directory /csp/samples (in this case the SAMPLES namespace).
If the URL directory /csp/accounting is associated with the Caché namespace ACCOUNTING, then the CSP server dispatches this URL:
http://localhost:57772/csp/accounting/Ledger.csp
to a class called ledger contained within the package csp running in the Caché namespace ACCOUNTING.
Note that URL file names used with CSP have a number of restrictions:
Note:
If a .csp file is placed within a subdirectory of a defined directory, then the subdirectory name becomes part of the package name for the %CSP.Page class used for the page. For example, if the URL directory /csp/samples is defined as a CSP application, then /csp/samples/myapp/page.csp refers to a class named csp.myapp.page.
%CSP.Page Class
On the CSP server, all HTTP requests are handled by invoking methods defined by the %CSP.Page class. The %CSP.Page class never directly handles requests itself; it simply defines the interface required to process HTTP requests. The actual event handling is done by a subclass of %CSP.Page (created either manually or as a result of processing a CSP source file).
Subclasses of %CSP.Page are never instantiated; that is, no %CSP.Page objects are ever created. The methods defined by %CSP.Page are all class methods and do not require an object in order to be invoked. As we shall see, any state information required by these methods is provided by other objects (such as the %CSP.Request and %CSP.Session objects) which are managed by the CSP server.
Page Method
After the CSP server determines which %CSP.Page class should process a request, it sets up the appropriate processing context and then invokes that class' Page method. Setting up the processing context includes redirecting the standard output device ($IO) so that all output (using the Write command) is sent back to the HTTP client and creating instances of any required objects (such as the %request, %response, and %session objects) or local variables.
The Page method handles the complete response to the HTTP request. It does this by invoking the callback methods, OnPreHTTP, OnPage, and OnPostHTTP in that order. These are referred to as callback methods because a subclass can override them in order to provide custom behavior.
The OnPreHTTP method is responsible for writing out the header for the HTTP response. This includes information such as content type and cookies. The default behavior is to set content type to text/html. You typically only need to override the OnPreHTTP method in cases where you need more direct control over the response header.
The OnPage method performs the bulk of the effort in responding to an HTTP request. It is responsible for writing out the body of the request, such as an HTML or XML document.
For example, here is a sample CSP class containing an OnPage method:
Class MyApp.Page Extends %CSP.Page
{
ClassMethod OnPage() As %Status
{
    Write "<html>",!
    Write "<body>",!
    Write "My page",!
    Write "</body>",!
    Write "</html>",!
    Quit $$$OK
}
}
The OnPostHTTP method is provided as a place to perform any operations you wish to perform after processing of the HTTP request is complete.
%CSP.Page Class Parameters
The %CSP.Page class contains a number of class parameters that you can override to provide custom behavior without having to write code.
For a list of all available class parameters, refer to the documentation for %CSP.Page.
If you are developing applications programmatically you can override these class parameters within the subclasses of %CSP.Page you create (using the Class Editor within the Studio for example).
If you are creating pages using .csp files, you can provide values for these parameters using the csp:class tag:
<csp:class PRIVATE="1">
Limiting Page Access by Resources
Use the SECURITYRESOURCE parameter to limit access to CSP pages. SECURITYRESOURCE takes a comma-delimited list of system resources and associated permissions. You can specify an OR condition using the vertical bar (|) and an AND condition using a comma (,). A user must hold the specified permissions on all of the specified resources in order to view this page or invoke any of the page's server-side methods from the client.
An item in the list has the following format:
Resource[:Permission]
Resource is any of the resources set on this system. (See [Home] > [Security Management] > [Resouces] for a list of resources.)
Permission is one of USE, READ, or WRITE. Optional; default is USE.
Example
R1,R2|R3,R3|R4
This example means the user must have resource R1 AND one of (R2 OR R3) AND one of (R3 OR R4). If the user has R1,R3 they can run the page. If the user has R1,R4, they cannot run the page, as they do not meet the R2 OR R3 condition. The vertical bar (|) OR condition takes precedence over the comma (,) AND condition.
Handling CSP Errors
%CSP.Error is the default CSP error page. Use this as the superclass of any error pages that you create. You can pull information out of the error using the functions provided in %CSP.Error.
Handling CSP Errors Before a License Has Been Granted
If you already have an existing session and the user tries to go to a page that is not found, CSP displays the standard error page because the session already has a license.
If a CSP application does not yet have a license, and any of the following errors occur, then CSP displays the standard web HTTP/1.1 404 Page Not Found error message by default. You can change what page is displayed when errors are encountered before a license has been granted by setting the following parameters on the error page (usually a subclass of %CSP.Error) for your application.
LICENSEERRORPAGE
If the following error is generated, CSP looks at the value of the LICENSEERRORPAGE parameter:
Cannot grant license.
LICENSEERRORPAGE can have the following two values:
"" — Returns the HTTP/1.1 404 Page Not Found error (default)
Path to a static HTML page — Displays the named static page, such as /csp/samples/static.html.
PAGENOTFOUNDERRORPAGE
If any of the following errors are generated, CSP looks at the value of the PAGENOTFOUNDERRORPAGE parameter:
Class does not exist
Method does not exist
CSP application does not exist (set parameter on default error page)
CSP page does not exist
File does not exist
CSP namespace does not exist
CSP illegal request
File cannot open
CSP session timeout 
PAGENOTFOUNDERRORPAGE can have the following three values:
"" — Return the HTTP/1.1 404 Page not found error (default)
1 — Obtains a license and displays the standard error page.
Path to a static HTML page — Displays the named static page, such as /csp/samples/static.html.
OTHERSTATICERRORPAGE
If any other errors are generated, CSP looks at the value of the OTHERSTATICERRORPAGE parameter.
OTHERSTATICERRORPAGE can have the following three values:
"" — Obtains a license and displays the standard error page (the default)
1 — Outputs the 404 Page not found error, no license required.
Path to a static HTML page — Displays the named static page, such as /csp/samples/static.html.
%CSP.Request Object
When the CSP server responds to an HTTP request, it packages information about the incoming request into an instance of the %CSP.Request object. You can refer to this object using the variable %request. Refer to the documentation for the %CSP.Request class for a complete list of its properties and methods.
URL Property
To find the URL (not including the query string) of an incoming HTTP request, use the URL property of the %CSP.Request object:
 Write "URL: ", %request.URL
Data Property and URL Parameters
A URL may contain a list of parameters (also known as the URL query). The %CSP.Request object makes these available via its Data property.
For example, suppose the incoming URL contains:
/csp/user/MyPage.csp?A=10&a=20&B=30&B=40
You can retrieve these parameters on the server using:
 Write %request.Data("A",1)    // this is 10
 Write %request.Data("a",1)    // this is 20
 Write %request.Data("B",1)    // this is 30
 Write %request.Data("B",2)    // this is 40
Data is a multidimensional property and each value stored within it has 2 subscripts: the name of the parameter and the index number of the parameter (parameters can occur multiple times within a URL as with B above). Note that parameter names are case-sensitive.
Also note that it does not matter if an incoming HTTP request is a GET or a POST request: the Data property represents the parameter values in exactly the same way.
You can use the ObjectScript $Data ($D) function to test if a given parameter value is defined:
 If ($Data(%request.Data("parm",1))) {
 }
If you wish to refer to a parameter but are not sure if it is defined, you can use the ObjectScript $Get function:
 Write $Get(%request.Data("parm",1))
You can find out how many values are defined for a particular parameter name using the Count method of the %CSP.Request object:
 For i = 1:1:%request.Count("parm") {
    Write %request.Data("parm",i)
 }
CgiEnvs Property and CGI Environment Variables
The web server provides a set of values, referred to as CGI (Common Gateway Interface) environment variables, which contain information about the HTTP client and web server. You can get access to these CGI environment values using the multidimensional property CgiEnvs. You can use this in the same manner as the Data property.
For example, to determine what type of browser is making the HTTP request, look at the value of the CGI environment variable HTTP_USER_AGENT:
 Write %request.CgiEnvs("HTTP_USER_AGENT")
For information on the CGI environment variables you can use, see the section CGI Environment Variables in the CSP Gateway Configuration Guide.
Cookies Property
If the HTTP request contains any cookies, you can retrieve their values using the multidimensional property, Cookies. You can use this in the same manner as the Data property.
In this book, see section %CSP.Response Object and the OnPreHTTP Method for examples of setting cookies.
Data can also be saved in the %session object. See User Session Data – Data Property. See an example of using cookies in cookie.csp in the CSP Samples database.
MIME Data Property
An incoming request may contain MIME (Multipurpose Internet Mail Extensions) data. This is typically used for larger pieces of information, such as files. You can retrieve MIME data using the %CSP.Request object. This creates and returns an instance of a Caché stream object that you can then use to read the MIME data.
For an example using MIME data, refer to the upload.csp page in the CSP samples.
%CSP.Response Object and the OnPreHTTP Method
You can control what response headers are sent back to the HTTP client using the %CSP.Response object. The CSP server automatically creates an instance of this class and places a reference to it in the variable %response.
As the %response object controls HTTP headers, you typically set its properties in the OnPreHTTP method of the %CSP.Page class. For example, to redirect an incoming HTTP request, define the following OnPreHTTP method:
Class MyApp.Page Extends %CSP.Page
{
// ...

ClassMethod OnPreHTTP() As %Boolean
{
    Set %response.ServerSideRedirect = "C:\CacheSys\csp\samples\redirect.csp"
    Quit 1
}
}
If you use CSP classes to create a CSP page, use the following code to set header values:
Class MyPage Extends %CSP.Page
{
ClassMethod OnPreHTTP() As %Boolean
{
    Do %response.SetCookie("name","value")
    Quit 1
}
If you use HTML to create a CSP page, use the following code to set header values:
<head></head>
<script language="Cache" method="OnPreHTTP" arguments="" returntype="%Boolean"> 
    Do %response.SetCookie("name","value") 
    Quit 1
</script>
<body></body>
Serving Cookies with the SetCookie Method
You can send cookies to the HTTP client using the %response object's SetCookie method. Refer to the section Storing Data in Cookies.
Accessing Cookies
Once a cookie has been saved. you can access its value with this code:
[in Page Classes]
ClassMethod OnPage() As %Status 
{ 
Write "<body>"
Write "<p>COOKIES:</p>" 
Write "<ul>"
Set cookie=%request.NextCookie("")
While cookie'="" { 
      For count=1:1:%request.CountCookie(cookie) { 
   Write "<li>",cookie," - ",..EscapeHTML(%request.GetCookie(cookie,count)),"</li>",! 
   }
Set cookie=%request.NextCookie(cookie)
} 
Write "</ul>"
Write !,"</body>"
Quit $$$OK 
} 
[on CSP pages]
<body>
<p>COOKIES:</p>
<ul>
<script language="Cache" runat="server">
Set cookie=%request.NextCookie("")
While cookie'="" {
    For count=1:1:%request.CountCookie(cookie) {
    Write "<li>",cookie," - ",..EscapeHTML(%request.GetCookie(cookie,count)),"</li>",!
    }
Set cookie=%request.NextCookie(cookie)
}
</script>
</ul>
</body>
A cookie definition can include an expiration date and a path in this format:
Do %response.SetCookie("NAME","VALUE",expireData,path)
A blank expireData field defines an in-memory cookie. If, however, you specify a value for the expireData field this becomes a permanent cookie that is removed at the time specified. The format for the expireData field is Wdy, DD-Mon-YYYY HH:MM:SS GMT, for example: Wednesday, 24-Mar-2004 18:12:00 GMT.
Serving Different Content Types
Typically a CSP page serves text/html content. You can specify a different content type in several ways: