Forum Discussion
HTTP_RESPONSE - STREAM::expression to replace one string with another in HTTP data payload
I am trying to replace any instance of a certain URI whenever it occurs in the HTTP response data. It occurs within JavaScript <script> tags of the HTML document. I have the default system stream profile on the virtual server, and I'm using an iRule.
When I inspect the web page after in my browser, I still see the URI that I am trying to replace, even the first instance of it. Although, as I understand it from reading the content at the links below here, I am using STREAM::expression in my iRule, so I think it should replace all occurrences, not just the first. Seems to not be replacing any though.
https://support.f5.com/csp/article/K39394712
https://clouddocs.f5.com/api/irules/STREAM__expression.html
I have also checked these out:
https://devcentral.f5.com/s/articles/ltm-stream-profile-multiple-replacements--regular-expressions
https://clouddocs.f5.com/api/irules/STREAM__replace.html
Here is what I have.
# FQDN app.example.com resolves to ltm virtual server SNAT IP
# if URI starts with /fooportal
# then reverse proxy to https://example.com/fooportal
# if the URI started with anything other than /fooportal
# then 307 redirect to host example.com
# but with the originally requested path
#
#
when HTTP_REQUEST {
# Disable the stream filter for client requests
STREAM::disable
# only requests to app.example.com will come to this virual server
# app.example.com has a DNS Address record to this virtual server's SNAT IP Address
# whereas the DNS Address record for example.com is the back-end real server address
if { ([string tolower [HTTP::uri]] starts_with "/fooportal") } {
HTTP::header replace Host "example.com"
pool example.com_HTTPS_Pool
} elseif { ([string tolower [HTTP::header host]] eq "app.example.com") } {
HTTP::header replace Host "example.com"
HTTP::respond 307 Location https://[HTTP::host][HTTP::uri]
}
}
when HTTP_RESPONSE {
# Disable the stream filter for server responses
STREAM::disable
# Enable the stream filter for text responses only
if {([HTTP::status] == 200) && ([HTTP::header value Content-Type] starts_with "text")} {
# Replace 'example.com' with 'app.example.com'
STREAM::expression {@example.com/fooportal/@app.example.com/fooportal/@}
# Enable the stream filter
STREAM::enable
}
}
- spivAltocumulus
Everything is working after adding a custom httpcompression profile to the LTM virtual server and specifying content-types for compression. I also had to tell the server to remove Accept-Encoding in the HTTP request block of the iRule, because if the server's HTTP response comes back to f5 compressed then stream cannot parse for the string we want to replace. The httpcompression profile is to compress the HTTP response before f5 sends it back to the original client.
Final iRule looks like this:
# If URI starts with /fooportal
# then reverse proxy to foo.example.com
# If the URL started with anything other than /fooportal
# then 307 redirect to foo.example.com
# but with the originally requested path
#
# https://clouddocs.f5.com/api/irules/STREAM.html
# https://support.f5.com/csp/article/K39394712
# https://clouddocs.f5.com/api/irules/STREAM__expression.html
# https://devcentral.f5.com/s/question/0D51T00006i7fhv/understanding-stream-expression-and-compression
# https://clouddocs.f5.com/cli/tmsh-reference/latest/modules/ltm/ltm_profile_stream.html
# https://support.f5.com/csp/article/K15434
# https://techdocs.f5.com/en-us/bigip-14-0-0/big-ip-local-traffic-manager-implementations-14-0-0/compressing-http-responses.html
#
when HTTP_REQUEST {
# Disable the stream filter for client requests
STREAM::disable
if { ([string tolower [HTTP::uri]] starts_with "/fooportal") } {
HTTP::header replace Host "foo.example.com"
# Tell server not to compress response
# LTM does not uncompress response content, so if the webserver has compression enabled
# we must prevent the server from sending us a compressed response by changing the request
# header that indicates client support for compression (on our LTM client-side we can re-
# apply compression before the response goes across the Internet)
HTTP::header remove Accept-Encoding
pool foo.example.com_HTTPS_Pool
} elseif { ([string tolower [HTTP::header host]] eq "app.foo.example.com") } {
HTTP::header replace Host "foo.example.com"
HTTP::respond 307 Location https://[HTTP::host][HTTP::uri]
}
}
when HTTP_RESPONSE {
# Disable the stream filter for server responses
STREAM::disable
# Enable the stream filter for text responses only
if {([HTTP::status] == 200) && ([HTTP::header value Content-Type] starts_with "text")} {
# Replace 'foo' with 'app.foo'
STREAM::expression {@foo.example.com/fooportal@app.foo.example.com/fooportal@}
# Enable the stream filter
STREAM::enable
# enable compression
COMPRESS::enable
}
}
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com