Forum Discussion

Brad_Otlin's avatar
Brad_Otlin
Icon for Employee rankEmployee
May 08, 2013
Solved

Reference an iRule variable in an HTML iFile response

I have a sorry page iRule that serves an html sorry page if no servers are left in the pool and serves another page if a 404 or 5xx is encountered. The 404/5xx portion of the irule tries each server in the pool before actually serving the sorry page.

 

The site down sorry page displays the url attempted pulled from variables $http_host and $http_uri which are set during the HTTP_REQUEST event

 

The 404/5xx sorry page displays the url attempted pulled from variables $http_host and $http_uri which are set during the HTTP_REQUEST event. It also displays the http status code from variable $http_status which is set from HTTP::status during the HTTP_RESPONSE event.

 

The html is all defined in the iRule and served via "HTTP::respond 200 content ".

 

This all works great.

 

But I would like to move all the html code into 2 iFiles so we can easily modify the sorry page content without touching the iRule. I have uploaded the 2 html files as iFiles.

 

The new iRule now has the following 2 HTTP::respond commands:

 

  • HTTP::respond 200 content [ifile get down_html]
  • HTTP::respond 200 content [ifile get error_html]

Almost everything works as expected. EXCEPT - when the html code in the iFiles try to use the variables set in the iRule. They each display as plain text.

 

  • $http_host
  • $http_uri
  • $http_status

Is there a way to get the html code in the iFile to reference the variables set in the iRule?

 

 

attached files:

 

  • iRule -sorry.txt
  • down.html iFile - down.txt
  • error.html iFile - error.txt
  • I think the subst Tcl command is closest to what you want:

    
    HTTP::respond 200 content  [subst -nocommands -nobackslashes [ifile get error_html]]
    

    Very clean, and much safer than using eval.

8 Replies

  • Hey Brad, I'm pretty sure there isn't a way to do this. Could you not directly serve some HTML that includes (and will expand) the variables and then pull the iFiles in using include statements or something similar?
  • Steve:

     

    Do you have an example of what you mean and how this would be accomplished?

     

    If I am putting (some) html code IN the iRule, that almost defeats the purpose of my reason for using the iFiles.

     

  • It is possible, albeit a little tricky.

     

    
    when HTTP_REQUEST {
        set http_host [HTTP::host]
        set http_uri [HTTP::uri]
        eval "set temp \"[string map {"\"" "\\\""} [ifile get down.html]]\""
        HTTP::respond 200 content $temp
    }
    

     

    You can also just do:

    HTTP::respond 200 content [eval "set temp \"[string map {"\"" "\\\""} [ifile get down.html]]\""]

    You can use local variables and commands (ie. [HTTP::host]) inside the HTML files as well. Essentially what you're doing is assigning the contents of the HTML file to a local variable, encapsulating the whole thing in quotation marks to make it one long string, replacing all of the internal quotation marks with escaped quotation marks, and then evaluating the new string to replace all of the inline variables and commands. You have to be careful of course that you don't have any TCL errors in your HTML, as that'll be a little less forgiving in the troubleshooting department. Also, if you have any other special characters in your HTML, like the square brackets, you'll need to escape them too.

  • spark_86682's avatar
    spark_86682
    Historic F5 Account
    I think the subst Tcl command is closest to what you want:

    
    HTTP::respond 200 content  [subst -nocommands -nobackslashes [ifile get error_html]]
    

    Very clean, and much safer than using eval.
  • I definitely like that one better. If you remove the "-nocommands" option you can also evaluate some iRule/TCL commands in the HTML file, like [HTTP::host] and [string toupper ]. A *little* dangerous still, but very cool.
  • Seconded with Spark. I always use [subst -nobackslashes [ifile get ifile_name]] for this purpose. It works just fine for dynamically replacing the variables and commands into the page text that you've stored in the iFile.
  • John_Alam_45640's avatar
    John_Alam_45640
    Historic F5 Account

    Split page into two parts:

    set ifile1 [ifile get down_html_part1]  
    set dynamic_part "today is wedenesday"  
    set ifile2 [ifile get down_html_part2]  
    
    set content "$ifile1$dynamic_part$ifile2"  
    HTTP::respond 200 content $content