Forum Discussion

John_Lennon_457's avatar
John_Lennon_457
Icon for Nimbostratus rankNimbostratus
Mar 22, 2010

Redirection to HTML error page if no pool selected

I'm new at using a LTM. I'm using ProxyPass V10 - http://devcentral.f5.com/wiki/default.aspx/iRules/ProxyPassV10.html - I wrote a script to convert the almost 1,000 rules from our Reverse Proxy to this format (with some cleanup too) and it's working fine. The issue I'm having is with the handling of mistakes (mistyped URLs or similar) for which I don't have a solution.

I tried to add a 2nd iRule where I do some redirections but the 404 isn't always a good test as the error the user gets is a connection reset (as no data is sent by the web servers if the URL is invalid).

 
 when HTTP_REQUEST { 
 switch -glob [HTTP::uri] { 
 "/" { HTTP::uri {/home} } 
 "/mashups*" { HTTP::uri {/home/html/product.jsp?p=mashups} } 
 "/images*" { HTTP::uri {/images} } 
 "/error.html" { HTTP::uri {/error_gh.html} } 
 "/down.html" { HTTP::uri {/down.html} } 
 "/catalog*" { HTTP::uri {/plugins/plugincatalog} } 
 "/MastHead/*" { HTTP::uri {/images} } 
 }  
 } 
  
 when HTTP_RESPONSE {  
    if { [HTTP::status] contains "404"} {  
      HTTP::redirect "https://www.mysite.com/error.html" 
    }  
  }  
 

I about 20 or so Pools selected with the ProxyPass iRule, what I'd like to accomplish is:

- be redirected to an error.html page when no pool is dynamically selected (I don't have a default pool) regardless of the URL typed

- be redirected to an error.html page when the user types a wrong URL and the web server doesn't return any response

Ideally I'd like to handle these cases in the iRule above, not in the ProxyPass one.

Thanks for your help and hints.

  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    Hi John,

     

     

    - be redirected to an error.html page when no pool is dynamically selected (I don't have a default pool) regardless of the URL typed

     

     

     

    If you set even a dummy default pool, ProxyPass will select it if there isn't a match in the HTTP_REQUEST event for the requested host and/or URI against the ProxyPass datagroup. So you could put your second iRule at a later priority (when HTTP_REQUEST priority 501) and then check if '[LB::server pool] eq $default_pool'. If so, then no match was found in the ProxyPass iRule and you could then send a redirect to an error URL.

     

     

    - be redirected to an error.html page when the user types a wrong URL and the web server doesn't return any response

     

     

     

    I can't think of a way to handle this if the server sends no HTTP response for an invalid request. Conceptually, you could try to increment a counter on each HTTP request, decrement the counter on each response and then look for an incremented count when the server closes the connection. However, you cannot send an HTTP response from the SERVER_CLOSED event. So I'm not sure this is possible.

     

     

    Can you change the server behavior to send a 404 or any other specific status?

     

     

    Aaron
  • Hi Aaron,

     

    we're close however there is an issue - most likely the way I've coded it.

     

     
     when HTTP_REQUEST priority 501 { 
     if { [LB::server pool] eq $default_pool } { 
     set myURI "[HTTP::uri]" 
     HTTP::redirect "https://www.mysite.com/error.html" 
     HTTP::uri {/error_gh.html}  
     log local0.error "Redirecting user IP: [IP::client_addr] to /error.html, URI requested: $myURI $default_pool" 
     } 
     } 
     

     

     

    What I see is that this code is triggered after the previous HTTP_REQUEST changed the URI, for example because of this rule:

     

    /catalog*" { HTTP::uri {/plugins/plugincatalog

     

     

    What I see in the log is:

     

    Rule Redirections : Redirecting user IP: 96.237.xxx.xxx to /error.html, URI requested: /plugins/plugincatalog Dummy_pool

     

     

    What is the proper way of resolving this?

     

    Thanks
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    If you're rewriting the request using HTTP::uri, the URI would be updated and then sent to the default pool. If the default pool doesn't include valid IP:ports, then the request would fail. I thought you wanted to send an HTTP redirect. In that case, the client should get the redirect.

     

     

    Or have I misunderstood what the problem is?

     

     

    Aaron
  • I had to change from redirection to change the URI as with redirection I get this:

     

     

    Mar 23 13:07:42 local/tmm1 info tmm1[4822]: Rule ProxyPass : VS=GH, Host=www.mysite.com, URI=/home: Found Rule, Client Host=www.mysite.com, Client Path=/home, Server Host=www.mysite.com, Server Path=/home

     

    Mar 23 13:07:42 local/tmm1 info tmm1[4822]: Rule ProxyPass : VS=GH, Host=www.mysite.com, URI=/home: Redirecting to https://www.mysite.com/home/

     

    Mar 23 13:07:42 local/tmm1 err tmm1[4822]: 01220001:3: TCL error: Redirections - Operation not supported. Multiple redirect/respond invocations not allowed (line 3) invoked from within "HTTP::redirect "https://www.mysite.com/error.html""

     

     

  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    Ah, I forgot that the ProxyPass iRule would be redirecting some requests. You could set a variable at the beginning of HTTP_REQUEST (set redirected 0) and then set it to 1 for the two HTTP::redirects. You could then check if $redirect==0 before trying to redirect in the second iRule.

     

     

    Does that sound like it would work for you?

     

     

    Aaron
  • I'm sorry but it doesn't seem to work quite yet:

     

    Mar 24 15:29:30 local/tmm1 err tmm1[4822]: 01220001:3: TCL error: Redirections - Operation not supported. Multiple redirect/respond invocations not allowed (line 4)
  • hoolio's avatar
    hoolio
    Icon for Cirrostratus rankCirrostratus
    I don't think I was very clear in the last post... I was trying to suggest that you modify the ProxyPass iRule to add a "redirected" variable to track whether the ProxyPass iRule had attempted a redirect. So you could add 'set redirected 0' at the beginning of the ProxyPass HTTP_REQUEST event, add 'set redirected 1' before each HTTP::redirect command in the ProxyPass iRule and then only use HTTP::redirect in the second iRule if '$redirected==0'.

     

     

    Aaron
  • Your posting was very clear but it introduced the issue I showed. I've rewritten my rules since and I'll try a different approach, I'm sure you'll see a post soon :-)