RXS Router
From Wiki
|
| User Guide |
| v2.10+ |
Contents |
Overview
The RXS Router (RXSRTR) is a program included with RPG-XML Suite (RXS) v2.10+ which runs on the IBM i (AS/400, iSeries, System i) within the HTTP server, acting as a 'router' for CGI requests which use the HTTP protocol.
RXSRTR enables you to both simplify your HTTP processing and add functionality which is not directly available through the HTTP server configuration. Once installed, RXSRTR sits seamlessly between your HTTP server and your CGI programs; no changes are required to existing CGI program functionality and no changes are required to any existing URL's you use to access your CGI programs (such as user favorites or links from webpages).
RXSRTR enables you to perform the following additional functionality:
- Route all CGI requests through a single URL format
- Specify a library list to use when calling programs
- Swap to a different user profile when calling programs
- Log all information about the request to an audit log file
- Call non-CGI programs, passing parameters and receiving responses
All this functionality is data-driven – that is, it is controlled via data held in a single control file used by RXSRTR. If you need to add or change the programs you need to call, you simply update the RXSRTR control file.
Simplified HTTP Configuration
Below is an example HTTP server instance configuration fragment, showing how three different URL formats match different CGI program calls in different libraries:
ScriptAliasMatch ^/cgi-bin/(.*) /qsys.lib/public.lib/$1.pgm ScriptAliasMatch ^/cust/(.*) /qsys.lib/customers.lib/initial.pgm ScriptAliasMatch ^/db2wse/(.*) /qsys.lib/db2wse.lib/db2wse.pgm <Directory /qsys.lib/public.lib/> Options +ExecCGI Allow From all </Directory> <Directory /qsys.lib/customers.lib/> Options +ExecCGI Allow From all </Directory> <Directory /qsys.lib/db2wse.lib/> Options +ExecCGI Allow From all </Directory>
In this case, multiple ScriptAliasMatch directives route different URLs to different CGI programs in different libraries. For instance, assuming this HTTP server is on a IBM i with an IP address of 192.168.0.1, below is a list of example URLs and the resulting program which will be called:
| URL used | CGI Program called |
|---|---|
| http://192.168.0.1/cgi-bin/mypgm | PUBLIC/MYPGM |
| http://192.168.0.1/cgi-bin/yourpgm | PUBLIC/YOURPGM |
| http://192.168.0.1/cust/john | CUSTOMERS/INITIAL |
| http://192.168.0.1/cust/ | CUSTOMERS/INITIAL |
| http://192.168.0.1/db2wse/string | DB2WSE/DB2WSE |
This can be confusing, since it's not always clear which program will eventually be called when a given URL is used and the configuration can grow very large and complex, since each library specified has to have its own <Directory> section in the configuration, specifying authorities etc. Additionally, if any changes are required, the HTTP server must be restarted. Finally, the above configuration is also insecure, since it allows any user to call any program in the PUBLIC library.
By contrast, RXSRTR allows you to replace all the above configuration with a single ScriptAliasMatch and <Directory> section in your HTTP server instance configuration file which can be used for all CGI program calls:
ScriptAliasMatch ^/(.*) /qsys.lib/rxsrtr.lib/rxsrtr.pgm <Directory /qsys.lib/rxsrtr.lib/> Options +ExecCGI Allow From all </Directory>
Using the above directive, every URL will call RXSRTR and by configuring RXSRTR, you can ensure that all existing URL's (which may exist as links in web pages, user's bookmarks etc.) will result in the same programs being called as before.
Within the RXSRTR configuration itself, you define which programs should be called and how. You can dynamically change these configuration settings without needing to change the HTTP server configuration or restart the HTTP server.
This means that you can have a much simpler HTTP configuration. Because RXSRTR works at the program level, you can easily configure RXSRTR to specify exactly which programs can be called, immediately making your system more secure.
Enhanced HTTP Routing Functionality
When a request is matched by the HTTP server which results in RXSRTR being called, RXSRTR analyzes the URL to determine a 'request routing identifier' (RRID), which will be used to determine the routing call processing for the request. This processing is described in detail in the RXS Router Configuration section.
Once the RRID has been determined for a request, RXSRTR retrieves the control data for that RRID. The control data specifies not only the actual program to call, but also the following characteristics of the call:
- Which additional libraries to add to the library list prior to calling the program
- Which user profile to swap to for the call
RXSRTR control data is held in the RXSRTRCTL file. Each record has a key of the RRID and contains a 'routing data' field. Within the routing data field, various flag/value pairs can be specified to control what program will be called for the given RRID.
The format of the DATA field is as follows:
{-flag value -flag value –flag value...}
where flag can be one of a number of special values as follows:
| Flag | Description of associated value |
|---|---|
| pgm | Name of application program to be called (required) |
| lib | Name of application library |
| usrprf | User profile to run as |
| passwd | Password for user profile |
| liblst | Comma-separated library list (10 libraries max) or qualified job description name |
| cvtopt | Comma-separated conversion options |
| response | Response type for non-CGI programs |
Note the following specifications related to control data flags and the way they must be specified in the DATA field in the RXSRTRCTL file:
- Each flag must be prefixed with a minus-sign, e.g. -pgm
- Values are automatically converted to upper-case for processing
- Flag/value pairs can be specified in any order
- Except for the pgm flag, all flag/value pairs are optional
- Comma-separated lists (for the liblst and cvtopt flags) must contain no embedded blanks
Note that there is a special *CONFIG record shipped in the RXS router control file which contains different valid flag values. See the RXS Router Configuration section for more details.
Control Flag Details
- pgm
- The pgm flag defines the program to be called. It can either be a valid i5/OS name or a special value. Valid special values are *0-*9. If a special value is used, the corresponding SCRIPT_NAME path segment is used as the program name, where 0 is the RRID itself, 1 is the next segment and so on. For instance, if RXSRTR is called with the following URL:
http://192.168.0.1/test/john/mike/fred
- then TEST will be used as the RRID. If the TEST record in RXSRTRCTL has -pgm *1 specified, then JOHN will be used as the program name, if –pgm *2 is specified, MIKE will be used as the program name and so on.
- lib
- The lib flag defines the library of the program to be called. If the library is not in the library list, it will be added to the top of the library list. If the lib flag is not specified, *LIBL will be used.
- usrprf/passwd
- The usrprf and passwd flags define the user profile which the job should use whilst calling the program. If usrprf is specified, passwd must also be specified and vice-versa. If either the specified user profile or password are invalid or if the user profile is disabled, RXSRTR will return an error to the browser and will not call the program.
- liblst
- The liblst flag defines the library list which should be used for the request. The liblst flag can be specified in one of two ways:
- liblst library1,library2,library3
- liblst library/jobd
- If a comma-separated list of libraries is specified, they are each added in order to the bottom of the library list. If a qualified job description (*JOBD) is specified, the initial library list (INLLIBL) of the *JOBD is retrieved and the libraries are each added in order to the bottom of the library list. All libraries added as a result of the liblst flag are removed when control is returned from the called program.
- cvtopt
- See the Conversion Options section for details of how the cvtopt flag should be specified.
- response
- See the Calling non-CGI programs section for details of how the response flag should be specified.
Example RXSRTRCTL Record
| ID | DATA |
|---|---|
| ZAP | -pgm zappgm –liblst qgpl/zapjobd –lib qgpl -passwd donald -usrprf goofy |
In this case, if the 'ZAP' RRID is used for the request, RXSRTR will change its library list to be the library list held in the QGPL/ZAPJOBD job description. It will then change to run using the GOOFY user profile. Finally, it will call program ZAPPGM in library QGPL.
Control Data Conversion Options
Depending on the value of the cvtopt control flag, RXSRTR may perform certain steps prior to calling the specified program. Some of the conversion options are designed to allow existing CGI programs which expect a particular value for the SCRIPT_NAME or QUERY_STRING environment variables to continue to be called as before, even though you may have changed the calling URL to implement RXSRTR control. Multiple conversion options can be combined in a comma-separated list. Each conversion option will be processed in the order it is found. The following sections describe the conversion options.
rm_sn (Remove RRID from SCRIPT_NAME)
The rm_sn conversion option indicates that if the RRID is included in the URL, it will be removed from the SCRIPT_NAME environment variable prior to the CGI program being called.
If the rm_sn conversion option is specified and the URL used to call RXSRTR is
http://192.168.0.1/rxsrtr/db2wse/mylib/myfile
then if the CGI program retrieves the SCRIPT_NAME environment variable, it will retrieve a value of
/db2wse/mylib/myfile
rather than the expected value of
/rxsrtr/db2wse/mylib/myfile
rm_qs (Remove RRID from QUERY_STRING)
The rm_qs conversion option indicates that if the RRID is included in the URL, it will be removed from the QUERY_STRING environment variable prior to the CGI program being called.
If the rm_qs conversion option is specified and the URL used to call RXSRTR is
http://192.168.0.1/cust/?fname=john&rxsrtr=mickey&lname=smith
then if the CGI program retrieves the QUERY_STRING environment variable, it will retrieve a value of
fname=john&lname=smith
rather than the expected value of
fname=john&rxsrtr=mickey&lname=smith
sn_pr (Parse parameters from SCRIPT_NAME)
The sn_pr conversion option indicates that the program being called will be passed a number of parameters, as specified in the SCRIPT_NAME environment variable, where every path segment after the RRID will be treated as a separate character parameter.
If the URL used to call RXSRTR is:
http://192.168.0.1/zap/mickey/mouse
and the ZAP control record has the following value:
-pgm zappgm –lib qgpl -cvtopt sn_pr
then RXSRTR will call program QGPL/ZAPPGM as follows:
CALL PGM(QGPL/ZAPPGM) PARM('MICKEY' 'MOUSE')
All parameters passed to the specified program will be passed as string pointers. In RPG, this means that they should be defined as follows:
D ZAPPGM PR Extpgm('ZAPPGM')
D fname * Const Options(*String)
D lname * Const Options(*String)
Calling non-CGI programs using RXS Router
CGI programs work by writing their output (typically the HTML for a web page) to 'standard output'. When the CGI program ends and control is returned to the HTTP server, the standard output is sent to the browser, displaying as a web page. However, if you use the HTTP server to call a non-CGI 'application' program, because it doesn't write to standard output, an HTTP 500 error page will appear.
However, RXSRTR allows you to call a non-CGI application program, with the following limitations:
- The program must be a batch (non-interactive) program
- A maximum of 10 parameters can be passed to the program
- All parameters must be defined in the program as character strings with a maximum length of 256 bytes
If you wish to pass parameters to the program, you must specify the sn_pr conversion option, which will pass each of the SCRIPT_NAME path segments following the RRID as a character parameter. See the Conversion Options section for details on how to specify this conversion option and the calling URL. When calling a non-CGI program, you must configure RXSRTR to send a response to the browser as an ad-hoc web-page, by specifying the response flag. It can be specified in one of the following two ways:
-response *confirm
or
-response *msg
After RXSRTR has called the program, it checks the value of the response flag. If -response *confirm is specified in the control record, RXSRTR will send a generic "Program called successfully" message to the browser. If -response *msg is specified, RXSRTR will retrieve the last message sent to it from the application program and will write it out to the browser.
For instance, if an application program is typically called from a command-line or from a green-screen menu and sends a completion message (e.g. "Audit record created") to the screen, calling this program from RXSRTR and specifying –response *msg in the RXSRTRCTL record will cause this same message to be sent to the browser.
Initializing RXS Router
For performance reasons, when the RXS Router is first called within a job, it reads the records from the RXS Router control file RXSRTRCTL and caches the data into a user space called RXSRTRCTLU, in the same library where the RXS Router itself exists. On subsequent calls within the same job, it uses the cached values, thus eliminating costly file I/O. However, if records in the RXSRTRCTL file are added, deleted or updated, the RXS Router cache must be updated.
A command called INZRXSRTR (Initialize RXS Router) is supplied with the RXS Router. When this command is run from a command line, the RXS Router cache is updated to contain the current values from the RXSRTRCTL file.
This command can also be used to refresh the cached call pointers in Apache CGI jobs. This is useful because normally OS/400 will cache programs for reuse, but when you are doing web service development you will want Apache to pick up the latest version of the program after compiling it. Normally one would have to either recompile the entry level program to clear all cached call pointers or restart Apache. Neither of those options are optimal, so that is why we introduced the INZRXSRTR command to effectively refresh all cached call pointers.
