$Web_Form_Done

From m204wiki
Jump to navigation Jump to search

Send Web Response for a Form


$Web_Form_Done sends the current output data to the browser, or it redirects the browser to do a GET on the current URL, and sends the current output data to the browser when the GET request is received. $Web_Form_Done might then also wait for the POST of the form sent to the browser.

$Web_Form_Done is callable, takes five arguments, and returns a number. A return of 0 indicates success; all other errors cause request cancellation.

Syntax

%rc = $Web_Form_Done([ redir_timeout], [post_timeout], [options], check_field, check_val)

Syntax terms

redir_timeout The amount of time to wait for the GET resulting from the redirect that $Web_Form_Done might send to the browser. This parameter is optional; it may have the following values:
  • A positive number, to indicate the number of seconds to wait.
  • -1, to indicate that no redirect is to be done.
  • 0, the default, to indicate that the FORMREDIRWAIT default (typically 60), the value set in the port definition, or the value set in the ON rule associated with the current request is to be used.
For additional comments, see "Setting timeout values".
post_timeout The amount of time to wait for the POST of one of the forms or of the only form on the page sent by $Web_Form_Done. This parameter is optional; it may have the following values:
  • A positive number, to indicate the number of seconds to wait.
  • -1, the default, to indicate that no wait for the POST is to be done.
  • 0, to indicate that the FORMPOSTWAIT default (typically 900), the value set in the port definition, or the value set in the ON rule associated with the current request is to be used.
For additional comments, see "Setting timeout values".
options A blank-delimited set of options for specifying the port's response processing when a POST to the web server URL is expected. This parameter has two defaults: one for how to respond if a POST is received, and one for how to respond if a GET is received. The valid options are:
FLUSH When a POST is received, flush the page that was sent. This eliminates the need to do a $Web_Flush before starting a new response page.
NOFLUSH When a POST is received, do not flush the page that was sent. This makes it possible to re-send the current page by simply doing a $Web_Done or $Web_Form_Done. This is likely to be appropriate only if the application determines that a POST was from a stale copy of the page, though this is probably more easily handled by using a check form field. This is the default.
GET When a GET is received (most likely as the result of a Refresh or Reload), resend the current page. This is the default.
NOGET When a GET is received (most likely as the result of a Refresh or Reload), terminate the wait for the POST, and process the request as if a GET had been done for the URL for the first time.
check_field The name of the form field in a POST whose value will be compared against the value specified in the fifth parameter. If the value does not match, the current page is resent, because the POST is probably from a stale copy of the form, probably reached via a Backpage.

This parameter should almost certainly contain the name of a hidden form field on the form for which the POST is being waited.

For additional comments, see "Using check fields".

check_val The value to be compared against the value of the field specified by the fourth parameter in a POST. If the value does not match, the current page is resent, because the POST is probably from a stale copy of the form, probably reached via a Backpage.

This parameter should almost certainly contain the value of a hidden form field on the form for which the POST is being waited. It should be a value such as a timestamp that will be different on every form.

For additional comments, see "Using check fields".

Usage notes

$Web_Form_Done serves two basic purposes:

  • To eliminate pages that are returned as the result of a POST. This is accomplished by redirecting back to the current URL when a page is to be returned for a POST. Since a browser always converts a redirect to a GET, the result page ends up being a GET result. This is important because:
    • It eliminates browser warning messages about re-posts on Backpage operations.
    • It eliminates a separate URL in the browser cache for each POST of a form that results in the form being redisplayed with an error message. It is highly recommended that, whenever such a form redisplay is to be done, $Web_Form_Done be used with a 0 or positive first argument parameter rather than $Web_Done.
  • To make possible persistent or conversational web applications. When 0 or a positive value is used for the second parameter on a $Web_Form_Done, the $Web_Form_Done waits for the user to fill in the form and POST it. When $Web_Form_Done returns, the result of the POST can be examined with all context (%variables, images, found sets, lists, $lists and so on) preserved. While such a persistent or conversational web application is not a "true" web application because true web applications are completely stateless, they can still be quite useable. For example, it might be much easier to convert an existing conversational 3270 application into a conversational web application rather than into a stateless one.

The subsections that follow discuss further aspects of persistent sessions and how to set and work with $Web_Form_Done.

Managing URLs in persistent sessions

The first execution of a persistent $Web_Form_Done, that is, a $Web_Form_Done that waits for a POST, establishes the URL of the request that contains the function as the "base" URL for the persistent session.

It is the programmer's responsibility to ensure that the action URL on the <form> tag matches the base URL for a persistent $Web_Form_Done (as discussed later below, Version 6.4 of Sirius Mods allows extensions to the base URL to also be considered a match). Similarly, it is the programmer's responsibility to ensure that method="POST" is used in the <form> tag. If either of these is neglected, $Web_Form_Done will never notice the POST of the form and will eventually time out.

$Web_Form_Action is provided to facilitate correct setting of the action attribute of the <form> tag for persistent applications. Outside of truncation issues, $Web_Form_Action is guaranteed to return the exact URL for which a $Web_Form_Done with a non-negative POST wait time will be waiting.

The following example illustrates the use of $Web_Form_Action with $Web_Form_Done. For additional details, see $Web_Form_Action and $Web_Form_Action_Len.

HTML <form method="POST" - action="{$Web_Form_Action."> . . . rest of form </form> </body> </html> END HTML * Send the form and wait for the POST %rc = $Web_Form_Done(0, 0)


As mentioned above, $Web_Form_Done has additional flexibility: Once the first $Web_Form_Done establishes the base URL, any browser request with a URL whose beginning matches this base URL (assuming user ID and other basic criteria also match) will be considered a response to the $Web_Form_Done. This allows parameters to be added to a base URL in a persistent session, and it allows hypertext links to continue a persistent session on one of its pages.

For example, if a persistent session is created by URL /cust/update?crn=54321, a page generated for this session can have a link like:

<a href="/cust/update?crn=54321&view=history">History</a>

When the user clicks on this link, the $Web_Form_Done for the session returns. The request can then examine the URL sent from the browser using $Web_IsIndex_Parm or $Web_Parm, can determine that the URL parameter view is set to history, and can take appropriate action.

Many releases of Netscape Navigator and Netscape Communicator have the following problem: when a POST is redirected to a GET for a URL that exactly matches the POST action URL, the browser decides it is in a redirect loop and refuses to do the GET. If you want to use the redirect aspect of $Web_Form_Done with such versions of Netscape Navigator or Netscape Communicator, they can be "tricked" into working by adding an octothorpe (#) character at the end of the action URL, as in:

HTML <form method="POST" - action="{$Web_Form_Action.#"> . . . rest of form </form> </body> </html> END HTML * Send the form %rc = $Web_Form_Done

This doesn't seem to cause any problems with other browsers, so it is a safe tactic if you are unsure about whether any end users will be using a version of Netscape with this bug.

Setting timeout values

The redirect timeout and POST timeout are very different. Since browsers automatically respond to a redirect, a long delay between sending a redirect and receiving the associated GET suggests either a network problem or a problem with the browser. Therefore, a fairly aggressive redirect timeout (approximately 60 seconds or less) is in order.

Since the POST timeout is the maximum amount of time the end-user will be given to fill in a form and POST it, this timeout is, in effect, a session inactivity timeout: if the user takes more than the indicated time to fill in the form, the persistent session is terminated and the user's POST will simply restart the request.

Unfortunately, persistent web applications have no way of knowing if or when a user has navigated away from the application by clicking on a hypertext link on one of the application pages, by backpaging through her browser cache, by selecting a browser bookmark, or by explicitly typing in a URL. There is also no way to determine when a user exits the browser or simply shuts down the workstation. For these reasons, it is probably a good idea to make the wait timeout of the POST somewhat conservative. It is also probably a good idea to keep the default setting of 1 for the port definition parameter MAXIPSES. This limits the number for persistent legacy sessions per user to one.

In addition, while it is possible to specify a separate POST timeout on each $Web_Form_Done, it is probably better to specify a value of 0 and to use the FORMPOSTWAIT default of 900 or the value specified on the port definition or ON rule. This ensures a consistent session timeout value within an application or web server, and it makes it easy to change the session timeout as needed.

Identifying the request user

$Web_Form_Done depends not only on URLs being consistent between GET and POST requests, they depend on requests by different users being distinguishable. $Web_Form_Done will use every bit of data at its disposal to distinguish requests and so prevent one user from seeing another user's data. Among these bits of data are:

  • The URL
  • The userid of the user POST'ing the form. Obviously, this is not of much use for public requests running under the WEBUSER userid.
  • The IP address of the browser. This cannot be used if the VARIPADDR parameter is set on the port definition. It is also of very limited utility if most users access the port through a single proxy server.
  • The identifying cookie set because of the WEBCOOKID port definition parameter.

Persistent sessions work best in a situation where every user logs in under a different userid. In situations where this would not be the case, such as public applications, it is recommended that the WEBCOOKID parameter be set. While it might be possible to prevent users from seeing each other's persistent session pages by generating unique URLs (perhaps by including time stamps in them), unless the actual end-users can be identified through userids or WEBCOOKID cookies, there is a great risk of an individual user accidentally or maliciously producing a large number of orphaned sessions.

Using check fields

When using $Web_Form_Done with a non-negative POST wait time, that is when using a persistent session, the URL for the persistent session might produce several different forms, all of which get posted to the same URL. This is not a problem when things are working well and users are cooperative. However, if a user were to backpage to a previous form in the persistent session and then POST it, $Web_Form_Done would have no way of knowing this has happened. It would return to the application with one form posted while the application expected another. This could cause serious application problems if the application is not written to deal with the situation, and in any case, an application coder would prefer not to have to worry about this.

To solve this forms problem, Janus Web Server provides the check field and check value parameters on the $Web_Form_Done call, which can be used as follows:

  1. Each form sent to the browser as part of a persistent session must have a hidden field that contains a value unique to that incarnation of the form, typically a time stamp.
  2. The name of the hidden field and its value are passed to $Web_Form_Done, which checks the value of the field when it receives a POST.
  3. If the value of the field is not the same as that specified on the $Web_Form_Done call, Janus Web Server resends the current form on the URL. It assumes that the user has backpaged and POST'ed, so displaying the most recent page in the persistent session is the most logical action.

The following code demonstrates the use of such a hidden check field:

%TIMESTAMP = $Web_Date HTML <form method="POST" - action="{$Web_Form_Action."> <input type="hidden" name="validate" - value="{%TIMESTAMP}"> . . . more form stuff END HTML %rc = $Web_Form_Done(0, 0, , - 'validate', %TIMESTAMP)