WEBSVC

Top  Previous  Next

 

The WEBSVC command listens for incoming simple web services connections.

 

 

Format

 

WEBSVC subr {options}

 

where

 

subrSpecifies the name of the subroutine to be called to process the incoming requests.

 

optionsAny combination of the following:
CLOSEAlways close the connection, ignoring any KEEP-ALIVE in the response header.
DEBUGGINGCauses the child process to write the request header and response header to the phantom log file.
FILE nSets the threshold size in kb above which the request body will be passed to the subroutine via a file instead of in memory. If not set, a file is never used.
MAX nSets the maximum number of simultaneous child processes. Defaults to 10 if omitted.
POOL nameSpecifies the connection pool name to be used for the child processes.
PORT portnoIs the port number on which to listen for incoming connections. Defaults to 80 if omitted. Linux systems only allow processes running as root to listen on port numbers less than 1024.

 

 

The WEBSVC command, typically used in a phantom process, listens for incoming web services connections on the specified port number. When a connection arrives, a phantom process is started to service this request. If the limit on simultaneous connections has been reached, the listener process pauses briefly until some other connection terminates.

 

The phantom process parses the incoming web request, separating the header from the request body, and calls the catalogued processing subroutine specified in the command line. This subroutine should be declared as

SUBROUTINE name(IP.ADDR,           ;* Origin

               ACTION,            ;* Request type (GET, POST, etc)

               URI,               ;* URI
               RQST.HEADER,       ;* Request header as a data collection...

               RQST.BODY,         ;* ...and associated request body

               RESPONSE.HEADER,   ;* Response header...
               RESPONSE.BODY,     ;* ...and associated response body

               CLOSE.CONNECTION,  ;* Close connection after sending response?

               INFO)              ;* Additional information

 

The final argument, INFO, was introduced at release 3.4-16 as a data collection containing miscellaneous information that the user supplied subroutine may find useful. This argument is optional and may be omitted. If present, the data collection may contain:

poolPool name if connection pooling is being used.
portServer port number
request.body.pathTemporary file pathname when passing the request body via a file. This collection element is absent for requests that are passed in memory. The user supplied subroutine should delete the file when it is no longer needed.
response.body.pathOn return from the user supplied subroutine, if this collection element is present, it contains the pathname of a file that holds the response body.
delete.response.fileOn return from the user supplied subroutine, if this collection element is True and the response was returned via a file, the file will be deleted.

 

 

As an example of how the incoming request is processed, consider a simple request submitted via a browser:

http://mysite.com/a/b?x&y&z

 

ACTIONis the HTTP request type (GET, POST, etc).

 

URIis the URI string "/a/b?x&y&z"

 

RQST.HEADERis a data collection with an element for each of the name/value pairs in the HTTP request such as

ACCEPT text/html, application/xhtml+xml, */*

ACCEPT-ENCODING gzip, deflate

ACCEPT-LANGUAGE en-GB

CONNECTION Keep-Alive

HOST mysite.com

USER-AGENT Mozilla/5.0

 

RQST.BODY would be a null string in this example.

 

The subroutine processes this data and constructs the response body as a field mark delimited dynamic array. For example,

 

RESPONSE.BODY = '<!DOCTYPE html>'

RESPONSE.BODY<-1> ='<html>'

RESPONSE.BODY<-1> = '<p>Hello ' : IP.ADDR : '</p>'

RESPONSE.BODY<-1> ='</html>'

RESPONSE.BODY = CHANGE(RESPONSE.BODY, @FM, CRLF)

 

The final line in the above example is needed from QM release 3.4-15 onwards as the data returned via the subroutine's RESPONSE.BODY argument is treated as binary data and not altered in any way before transmission.

 

The default values for RESPONSE.HEADER and CLOSE.CONNECTION if not updated by the user supplied subroutine are equivalent to:

 

RESPONSE.HEADER = 'HTTP/1.1 200 OK'

RESPONSE.HEADER<-1> = 'Content-Type: text/html'

RESPONSE.HEADER<-1> = 'Server: QM/':change(system(SYS$VERSION), '-', '.')

RESPONSE.HEADER<-1> = 'Date: ' : OCONV(EPOCH(), 'E4WADMYTSZL[A3,", ",A3]')

RESPONSE.HEADER<-1> = 'Connection: close'

 

CLOSE.CONNECTION = @TRUE

 

If the response header includes a CONNECTION element, the CLOSE.CONNECTION argument is updated to the corresponding state.

 

If the POOL command line parameter has been used, the phantom process will go into an idle wait state until either a new connection arrives or the pool timeout is reached. Use of connection pools can improve performance as the process can potentially omit initialisation tasks such as opening files.