FoswikiRedirectCache

Design and Operation of Foswiki Redirect Cache

There is some confusion on how the Foswiki Redirect Cache is supposed to work. This topic currently describes how the cache might work.

From the Foswiki::Request::Cache module documentation:

Class that implements a disk cache of Foswiki::Request objects.

There are a couple of cases where we need to cache request objects; over a 403 redirect (which is a GET and therefore has limited parameter capacity) and over a confirmation, such as a strikeone validation. In these cases we need to cache not just the request parameters, but also any uploads associated with the request. We also need the means to keep the cache tidy.

Note that the cache records the method() and path_info() of the original request and restores them on reload.

Two flows described below: A simple redirect from a GET of a protected page requiring authentication, and a redirect from a POST that requires authentication to proceed.:

Simple redirect for page requiring authentication

This is apparently the current flow for simple get redirect to login:
 
CLIENT Action
Message
SERVER Action
edit
1
GET bin/view/Protected/Topic
 
 
edit
2
 
 
Authentication Required
edit
3
 
<-- 302 Redirect to bin/login?origurl=
 
edit
4
GET bin/login?origurl=bin/view/Protected/Topic
 
 
edit
5
 
 
Return Login Page
edit
6
POST bin/login
 
 
edit
7
 
 
Authenticate User
edit
8
 
 
Create redirect_cache for POST / login / ?origurl=
edit
9
 
<-- 302 Redirect to bin/view?redirect_cache=<hex>
 
edit
10
GET bin/view/Protected/Topic?redirect_cache=
 
 
edit
11
 
<-- 302 Redirect to bin/view/Protected/Topic (content of origurl)
 
edit
12
GET bin/view/Protected/Topic
 
 
edit

gac: What we could do to restore the original URL (easy for a GET, might be harder for a POST): In this example, I don't see that the cache created in step 8 serves any purpose. If the redirect to login in step 3 doesn't include a cache, then the exit / returning redirect probably should not either.

Redirect from POST

This is the flow for the case when the initial event triggering authentication was a POST, such as a save using an expired session, or a submission from a comment form or other form while unauthenticated.

CLIENT Action Message SERVER Action
POST bin/save/Protected/Topic
 
 
edit
 
 
Authentication Required
edit
 
 
Create redirect_cache for POST bin/save/Protected/Topic
edit
 
<-- 302 redirect bin/login
 
edit
GET bin/login?origurl=bin/save/Protected/Topic
 
 
edit
 
 
Return Login Page
edit
POST bin/login
 
 
edit
 
 
Authenticate User
edit
 
<-- 302 Redirect to bin/save?redirect_cache=<hex>
 
edit
GET bin/save/Protected/Topic?redirect_cache=
 
 
edit
 
 
Process save
edit
 
<-- 302 Redirect to bin/view/Protected/Topic
 
edit
GET bin/view/Protected/Topic
 
 
edit


Flow based upon wireshark traces below. I'll try to work up an actual flow diagram from a wireshark trace combined with some TRACE_CACHE information later today -- GeorgeClark - 30 Apr 2010)

  1. GET bin/view/Protected/Topic?param=val This is the request that we have to save and return to from the redirects
    • Foswiki::AccessControlException
    • Response is a 302 (redirect from TemplateLogin.pm:69). Redirect is to bin/login?origurl=bin/view/Protected... and does not use a redirect cache (unless hte original request was a POST, which in this case it isn't)
  2. GET for bin/login?origUrl=bin/view/Protected/Topic;param=val
    • The server generates a page that contains a login form with <input type="hidden" name="param" value="val"> and <input type="hidden" name="origUrl" value="bin/view/Protected/Topic">
  3. POST bin/login?param=val;user=edward;pass=lear (User fills in login details and hits submit)
    • User is authenticated
    • 302 redirect to origurl. Because the request was a POST, the params are stuffed into the redirect cache '41babe'
    • On disk, 41babe contains (you can trace this by enabling TRACE_CACHE in Foswiki::Request::Cache):
      • param=val
    • For this example, redirecting from GET, this use of the cache is superfluous. The event we need to cache is step 1 - highlighted in red. The alternative case would be when Step 1 is a POST (for example using comment button, or an expired session) When Step 1 is a POST, then It creates the cache, and login would pass it through and restore it once the user is authenticated. I have a local patch which suppresses the cache when login is entered without a pre-existing cache. (If login is "entered" with origurl, then it redirects with origurl. If login is entered with a cache (signifying a cached POST) it redirects with the cache.)
  4. GET bin/view/Protected/Topic?redirect_cache=41babe
    • CGI request restored from redirect cache before view request is processed. The request should be reconfigured such that the <base in the output is the origUrl (this isn't happening for some reason)
    • The changes to the request are supposed to tell the browser about the changed URL
-- CrawfordCurrie - 30 Apr 2010

Wireshark Trace on Trunk - without modification deleting the action from cache

(Irrelevant HTTP headers edited out)

GET /System/PerlDoc?module=Foswiki::Func HTTP/1.1
Cookie: FOSWIKIPREF=%7CTwistyPlugin_topicattachmentslist%3D1%7CJQueryTwistyPlugin_edithelp%3D0%7CJQueryTwistyPlugin_topicattachmentslist%3D1%7CTwistyPlugin_attachhelp%3D0%7CTwistyPlugin_edithelp%3D0%7CTwistyPlugin_twistyIdSystemWebChangesAlert1%3D0%7CTwistyPlugin_additionalSettings%3D1%7CWebChangesForAllWebs_dateLastCheck%3D2010-02-15%2012%3A25%3A27%7CTwistyPlugin_loginhelp%3D1%7CTwistyPlugin_twistyIdSystemTwistyPlugin4%3D0%7CTwistyPlugin_topicattachmentslist2%3D1%7CTwistyPlugin_topicattachmentslist1%3D1%7CTwistyPlugin_infoOnNestedWebs%3D1%7CTwistyPlugin_twistyIdSystemTwistyPlugin5%3D%7CTwistyPlugin_topicform%3D; log_pos=65233; FOSWIKISID=4e32226e1db071c15da140ed86ae71c1; FOSWIKISTRIKEONE=4875b1d3c0071ae89b3907f96c121408

HTTP/1.1 302 Found
Set-Cookie: FOSWIKISID=4e32226e1db071c15da140ed86ae71c1; path=/; HttpOnly
Location: /bin/login/System/PerlDoc?module=Foswiki::Func;origurl=/System/PerlDoc%3fmodule%3dFoswiki::Func

Initial GET is redirected to bin/login with the origurl parameter

GET /bin/login/System/PerlDoc?module=Foswiki::Func;origurl=/System/PerlDoc%3fmodule%3dFoswiki::Func HTTP/1.1
Host: foswiki.xxxxxxxx.com
Cookie: FOSWIKIPREF=%7CTwistyPlugin_topicattachmentslist%3D1%7CJQueryTwistyPlugin_edithelp%3D0%7CJQueryTwistyPlugin_topicattachmentslist%3D1%7CTwistyPlugin_attachhelp%3D0%7CTwistyPlugin_edithelp%3D0%7CTwistyPlugin_twistyIdSystemWebChangesAlert1%3D0%7CTwistyPlugin_additionalSettings%3D1%7CWebChangesForAllWebs_dateLastCheck%3D2010-02-15%2012%3A25%3A27%7CTwistyPlugin_loginhelp%3D1%7CTwistyPlugin_twistyIdSystemTwistyPlugin4%3D0%7CTwistyPlugin_topicattachmentslist2%3D1%7CTwistyPlugin_topicattachmentslist1%3D1%7CTwistyPlugin_infoOnNestedWebs%3D1%7CTwistyPlugin_twistyIdSystemTwistyPlugin5%3D%7CTwistyPlugin_topicform%3D; log_pos=65233; FOSWIKISID=4e32226e1db071c15da140ed86ae71c1; FOSWIKISTRIKEONE=4875b1d3c0071ae89b3907f96c121408

HTTP/1.1 200 OK
Server: Apache
X-Foswikiuri: /bin/login/System/PerlDoc?module=Foswiki::Func;origurl=/System/PerlDoc%3fmodule%3dFoswiki::Func
X-Foswikiaction: login
Set-Cookie: FOSWIKISTRIKEONE=4875b1d3c0071ae89b3907f96c121408; path=/

Browser issued the redirected GET and receives login page (Many other get's for javascript, etc. all responded with 304 - unchanged. Omitted from trace)

POST /bin/login/System/PerlDoc HTTP/1.1
Host: foswiki.xxxxxxxx.com
Referer: http://foswiki.xxxxxxxxx.com/bin/login/System/PerlDoc?module=Foswiki::Func;origurl=/System/PerlDoc%3fmodule%3dFoswiki::Func
Cookie: FOSWIKIPREF=%7CTwistyPlugin_topicattachmentslist%3D1%7CJQueryTwistyPlugin_edithelp%3D0%7CJQueryTwistyPlugin_topicattachmentslist%3D1%7CTwistyPlugin_attachhelp%3D0%7CTwistyPlugin_edithelp%3D0%7CTwistyPlugin_twistyIdSystemWebChangesAlert1%3D0%7CTwistyPlugin_additionalSettings%3D1%7CWebChangesForAllWebs_dateLastCheck%3D2010-02-15%2012%3A25%3A27%7CTwistyPlugin_loginhelp%3D1%7CTwistyPlugin_twistyIdSystemTwistyPlugin4%3D0%7CTwistyPlugin_topicattachmentslist2%3D1%7CTwistyPlugin_topicattachmentslist1%3D1%7CTwistyPlugin_infoOnNestedWebs%3D1%7CTwistyPlugin_twistyIdSystemTwistyPlugin5%3D%7CTwistyPlugin_topicform%3D; log_pos=65233; FOSWIKISID=4e32226e1db071c15da140ed86ae71c1; FOSWIKISTRIKEONE=4875b1d3c0071ae89b3907f96c121408
validation_key=4e7c8cd55b789bff983f85f7eacb523b&module=Foswiki%3A%3AFunc&origurl=%2FSystem%2FPerlDoc%3Fmodule%3DFoswiki%3A%3AFunc&username=admin&password=xxxxxxxx

[FROM SERVER LOG / TRACE_CACHE OUTPUT]

Saving method =POST
Saving path_info =/System/PerlDoc
Saving action =login

HTTP/1.1 302 Found
Set-Cookie: FOSWIKISID=4e32226e1db071c15da140ed86ae71c1; path=/; HttpOnly
Location: /System/PerlDoc?foswiki_redirect_cache=5da693ff3b00f7726b27d3aa4aa5b204

Client redirected again - back to the original URL, but with a redirect cache

GET /System/PerlDoc?foswiki_redirect_cache=5da693ff3b00f7726b27d3aa4aa5b204 HTTP/1.1
Host: foswiki.xxxxxxxx.com
Referer: http://foswiki.xxxxxxxx.com/bin/login/System/PerlDoc?module=Foswiki::Func;origurl=/System/PerlDoc%3fmodule%3dFoswiki::Func
Cookie: FOSWIKIPREF=%7CTwistyPlugin_topicattachmentslist%3D1%7CJQueryTwistyPlugin_edithelp%3D0%7CJQueryTwistyPlugin_topicattachmentslist%3D1%7CTwistyPlugin_attachhelp%3D0%7CTwistyPlugin_edithelp%3D0%7CTwistyPlugin_twistyIdSystemWebChangesAlert1%3D0%7CTwistyPlugin_additionalSettings%3D1%7CWebChangesForAllWebs_dateLastCheck%3D2010-02-15%2012%3A25%3A27%7CTwistyPlugin_loginhelp%3D1%7CTwistyPlugin_twistyIdSystemTwistyPlugin4%3D0%7CTwistyPlugin_topicattachmentslist2%3D1%7CTwistyPlugin_topicattachmentslist1%3D1%7CTwistyPlugin_infoOnNestedWebs%3D1%7CTwistyPlugin_twistyIdSystemTwistyPlugin5%3D%7CTwistyPlugin_topicform%3D; log_pos=65233; FOSWIKISID=4e32226e1db071c15da140ed86ae71c1; FOSWIKISTRIKEONE=4875b1d3c0071ae89b3907f96c121408

[FROM SERVER LOG  - TRACE_CACHE]
CACHE LOAD set method ( POST )
CACHE LOAD set path_info ( /System/PerlDoc )
CACHE LOAD set action ( login )
ReqCache: Loaded /var/www/SVN/foswiki/core/working/tmp/passthru_5da693ff3b00f7726b27d3aa4aa5b204, URL now http://foswiki.xxxxxxxx.com/bin/login

HTTP/1.1 200 OK
X-Foswikiuri: /System/PerlDoc?foswiki_redirect_cache=5da693ff3b00f7726b27d3aa4aa5b204
X-Foswikiaction: login
Set-Cookie: FOSWIKISID=4e32226e1db071c15da140ed86ae71c1; path=/; HttpOnly

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html class="natHtml" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en_US" lang="en_US">
<head>
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<title>PerlDoc - System - Foswiki</title>
<base href="http://foswiki.xxxxxxxx.com/bin/login/System/PerlDoc" />

Note the INCORRECT <base tag in the response. Remains set to login.

-- GeorgeClark - 30 Apr 2010


Redirect from POST is very broken. PaulHarvey reported a redirect loop with MetaCommentPlugin, initially suspected to be an ajax / javascript issue, however the same issue occurs using regular CommentPlugin.
  • Create a sandbox topic with simple %COMMENT{}% macro
  • Log out
  • Post a comment - which posts to bin/save
    • save redirects to GET bin/login to get credentials
    • which redirects to GET bin/login to get credentials
    • Infinite loop redirecting until browser gives up. Problem appears to be UI.pm processes the redirect cache for the login, and attempts to save which again redirects to login.
    • The same problem does not occur on the release branch. Trunk only.
At this point I don't have any idea how to fix. Note that my change removing the "action" from the cache prevents the loop but causes other failures. I've locally reverted that change.

-- GeorgeClark - 01 May 2010

That doesn't make sense; why would bin/login redirect to bin/login, unless an access control exception was raised; in which case, why is that exception being raised during a login process which, by it's very nature, cannot be access controlled?

Later: a preliminary analysis shows that the decision whether to require authentication is based on the action in the request (sound familiar?). The save request is a POST, so when the login script is redirected to from save, the action is set to save in the redirect cache. When responding to the redirect, the request is restored from the cache before the authentication is checked. So the action is restored to save, and so it once again throws the exception to redirect to login. Thus you end up with an infinite loop.

Later still: as I suspected, the problem is the way FSA works. This fixes the infinite loop, and may point the way to fixing some of the other issues:
Index: Request/Cache.pm
===================================================================
--- Request/Cache.pm   (revision 7304)
+++ Request/Cache.pm   (working copy)
@@ -78,10 +78,10 @@
       . $!;
 
     # Serialize some key info from the request
-    #  Note: action is not saved - it will be set properly by the target script.
     foreach my $field qw(method path_info action) {
         print $F $field,'=', ($req->$field() || ''), "\n";
-        print STDERR "Saving $field =" . $req->$field() || '' . "\n" if (TRACE_CACHE); 
+        print STDERR "Saving $field =" . ($req->$field() || '') . "\n"
+          if (TRACE_CACHE); 
     }
     print $F "=\n";
 
Index: Request.pm
===================================================================
--- Request.pm   (revision 7304)
+++ Request.pm   (working copy)
@@ -36,12 +36,6 @@
 use IO::File ();
 use CGI::Util qw(rearrange);
 
-sub TRACE_CACHE {
-
-    # Change to a 1 to trace cache usage
-    0;
-}
-
 =begin TML
 
 ---++ ClassMethod new([$initializer])
@@ -96,20 +90,45 @@
 
 =begin TML
 
----++ ObjectMethod action() -> $action
+---++ ObjectMethod action([$action]) -> $action
 
 Gets/Sets action requested (view, edit, save, ...)
 
 =cut
 
 sub action {
-    return @_ == 1
-      ? $_[0]->{action}
-      : ( $ENV{FOSWIKI_ACTION} = $_[0]->{action} = $_[1] );
+    my ($this, $action) = @_;
+    if (defined $action) {
+        # Record the very first action set in this request. It will be required
+        # later if a redirect cache overlays this request.
+        $this->{base_action} = $action unless defined $this->{base_action};
+        $ENV{FOSWIKI_ACTION} = $this->{action} = $action;
+        return $action;
+    } else {
+        return $this->{action};
+    }
 }
 
 =begin TML
 
+---++ ObjectMethod base_action() -> $action
+
+Get the first action ever set in this request object. This remains
+unchanged even if a request cache is unwrapped on to of this request.
+The idea is that callers can always find out the action that initiated
+the HTTP request. This is required for (for example) checking access
+controls.
+
+=cut
+
+sub base_action {
+    my $this = shift;
+    return defined $this->{base_action} ? $this->{base_action}
+      : $this->action();
+}
+
+=begin TML
+
 ---++ ObjectMethod method( [ $method ] ) -> $method
 
 Sets/Gets request method (GET, HEAD, POST).
Index: LoginManager.pm
===================================================================
--- LoginManager.pm   (revision 7304)
+++ LoginManager.pm   (working copy)
@@ -486,14 +486,18 @@
     unless ( $session->inContext('authenticated')
         || $Foswiki::cfg{LoginManager} eq 'none' )
     {
-        my $script = $session->{request}->action;
+        # This checks the *base_action* which is the action in the
+        # request *before* any request cache was restored. Otherwise
+        # you can end up with an infinite loop - see
+        # Foswiki:Development.FoswikiRedirectCache
+        my $action = $session->{request}->base_action();
 
-        if ( defined $script && $this->{_authScripts}{$script} ) {
+        if ( defined $action && $this->{_authScripts}{$action} ) {
             my $topic = $session->{topicName};
             my $web   = $session->{webName};
             require Foswiki::AccessControlException;
-            throw Foswiki::AccessControlException( $script, $session->{user},
-                $web, $topic, 'authentication required' );
+            throw Foswiki::AccessControlException( $action, $session->{user},
+                $web, $topic, $action . ' requires authentication' );
         }
     }
 }

-- CrawfordCurrie - 01 May 2010

SUCCESS

I can confirm that the above changes fix the infinite redirect loop and %COMMENT is able to redirect and save.

The REST handler used by the MetaCommentPlugin is broken - but core foswiki appears healthy. I'll check in these fixes and attribute them to you.

MetaCommentPlugin fails with:
ERROR: (404) Invalid REST invocation - /Sandbox/MetaCommentTest does not  refer to a known handler

I'm guessing that the cache restored the url to rest/MetaCommentPlugin/Comment but internally left the path set to Sandbox/MetaCommentTest instead of the rest path. The redirect is properly sent to
http://foswiki.xxxxxxxx.com/bin/rest/MetaCommentPlugin/comment?foswiki_redirect_cache=0f5455df21b819908f92e02f7163760b

But the rest error identifies the original target topic where the POST to add the comment was issued.

Digging a bit into TemplateLogin.pm, it appears that for some reason in the rest case, the post to login is restoring the old cache and creating a new cache again, losing the original request. If I force the redirect to not create a new cache (similar to the origulr case), the old cache is preserved and the rest code appears to work.

The field that seems to be incorrectly restored is the path_info. It starts out MetaCommentPlugin/Comment, and changes to Sandbox/MetaCommentTest following the login.

Trace information from %COMMENT test
                 'path_info' => '/Sandbox/CommentTest',
                 'uri' => '/bin/save/Sandbox/CommentTest',
  Saving method =POST
  Saving path_info =/Sandbox/CommentTest
  Request action() 2 returning save
CACHE LOAD set path_info ( /Sandbox/CommentTest )
                 'path_info' => '/Sandbox/CommentTest',
                 'uri' => '/bin/login/Sandbox/CommentTest?foswiki_redirect_cache=5d56ce880352fc773748e04f33cf68b7',
ENTERING login
                 'path_info' => '/Sandbox/CommentTest',
                 'uri' => '/bin/login/Sandbox/CommentTest',
ENTERING login
Issuing REDIRECT from login
  Saving method =POST
  Saving path_info =/Sandbox/CommentTest
  Request action() 2 returning login
CACHE LOAD set path_info ( /Sandbox/CommentTest )
                 'path_info' => '/Sandbox/CommentTest',
                 'uri' => '/bin/save/Sandbox/CommentTest?foswiki_redirect_cache=4b3e0914390d02bae4a08e949850d33a',
                 'path_info' => '/Sandbox/CommentTest',
                 'uri' => '/Sandbox/CommentTest',

Test from MetaComment (rest)
                 'path_info' => '/MetaCommentPlugin/comment',
                 'uri' => '/bin/rest/MetaCommentPlugin/comment',
  Saving method =POST
  Saving path_info =/MetaCommentPlugin/comment
  Request action() 2 returning rest
CACHE LOAD set path_info ( /MetaCommentPlugin/comment )
                 'path_info' => '/MetaCommentPlugin/comment',
                 'uri' => '/bin/login/Sandbox/MetaCommentTest?foswiki_redirect_cache=ec12a73ad3efb49ce5f34a51d25c02e3',
ENTERING login
                 'path_info' => '/Sandbox/MetaCommentTest',
                 'uri' => '/bin/login/Sandbox/MetaCommentTest',
ENTERING login
Issuing REDIRECT from login
  Saving method =POST
  Saving path_info =/Sandbox/MetaCommentTest
  Request action() 2 returning login
CACHE LOAD set path_info ( /Sandbox/MetaCommentTest )
                 'path_info' => '/Sandbox/MetaCommentTest',
                 'uri' => '/bin/rest/MetaCommentPlugin/comment?foswiki_redirect_cache=5542f38237597f6a069ba4ef70689187',

-- GeorgeClark - 01 May 2010

the post to login is restoring the old cache and creating a new cache again - yes, of course. A redirect cache only exists for the duration of a redirect. Back to basics:
  1. A 302 redirect is limited in length because it is a GET request. Therefore if you 302 to another page, you have to use a redirect cache to pass the parameters.
  2. A redirect cache only exists for the 'duration' of the 302 i.e. between the time the server returns the 302 to the client until receives it back
So, if I POST a request that requires a 302 for some reason, and that results in a page that is then POSTed (such as login), then I'd expect to see this:
  1. Client sends POST to origUrl?param=x
    • Server responds with 302 to a login page with a foswiki_redirect_cache=A
  2. Client gets 302 login?foswiki_redirect_cache=A, and requests that page from server
    • Server unpacks foswiki_redirect_cache 'A', which sets param=x in the CGI query.
    • Login script encodes param=x into the login page form, sends login page to client
  3. Client POSTs response to the form on that login page
    • Server processes POST, which results in a redirect to origUrl. Because method=POST, it stores the query in a redirect_cache and emits a 302
  4. Client gets 302?origUrl?foswiki_redirect_cache=B, and requests that page from the server
    • Server unpacks foswiki_redirect_cache 'B', which sets param=x in the CGI query

-- CrawfordCurrie - 02 May 2010

I've committed a fix. in the 5th step above, if the script in the origurl field is the "rest" script, the redirect is done without using a redirect_cache. This seems to allow the MetaCommentPlugin to function posting across a redirect for authentication, and the CommentPlugin also continues to function.

Trac url: http://trac.foswiki.org/changeset/7312

I don't know that this is the correct or best fix. But it seems to work.

-- GeorgeClark - 03 May 2010

I'm afraid that's fixing the symptom, not the cause, and there are a couple of reasons that can't work.
  1. qr./rest/. is ony present if no $Foswiki::cfg::{ScriptSuffix} has been set
  2. Other scripts besides rest may require the same treatment.

The problem is not isolated to rest, it comes about because the redirect to origUrl is cached based on the method used to get to the login script, and not the method used to get to the origUrl. Looking at our example again, given an initial GET
  1. Client sends GET to origUrl?param=x
    • Server responds with 302 to a login page with no foswiki_redirect_cache (method!=POST)
  2. Client gets 302 login?param=x, and requests that page from server
    • Login script encodes param=x into the login page form, sends login page to client
  3. Client POSTs response to the form on that login page
    • Server processes POST, which results in a redirect to origUrl. Because method=POST, it stores the query in a redirect_cache and emits a 302
  4. Client gets 302?origUrl?foswiki_redirect_cache=B, and requests that page from the server
    • Server unpacks foswiki_redirect_cache 'B', which sets param=x in the CGI query
In the example, the method used to invoke origUrl was a GET, not a POST. The method should be recorded and restored with the origUrl. This would change steps 3 and 4 to:
  • Client POSTs response to the form on that login page
    • Server processes the POST, which contains values for origUrl, param and method.
    • Server sends 302. Because method says the origUrl was a GET, there is no need for a cache.
  • Client gets 302?origUrl?param=x and requests that page from the server

-- CrawfordCurrie - 03 May 2010
Topic revision: r18 - 03 Jan 2016, JozefMojzis
The copyright of the content on this website is held by the contributing authors, except where stated elsewhere. See Copyright Statement. Creative Commons License    Legal Imprint    Privacy Policy