Forum Discussion
Dealing with iRule $variables for HTTP2 workload while HTTP MRF Router is enabled
- Feb 12, 2023
Hi Pete,
Somehow found the cause of the variable glitch an a final workaround for my problem.
If you set any local variables during the CLIENT_ACCEPTED event then the outlined strange variable beharior happens.
If you dont set any variable during the CLIENT_ACCEPTED event, then the HTTP_REQUEST event is able to pass variables to the SERVER_CONNECTED and SERVERSSL_* events and you can also pass variable out of those events to the HTTP_REQUEST_RELEASE event.
Looks like a very annoying bug. I would love to open a new case, but my MVP support contract just has become outdated.... 🤐
Cheers, Kai
Just for completeness: I opened a case for this issue. I am curios to see what the outcome is.
I am also experimented with MR::store and MR::restore. The MR_EGRESS event triggers after the SERVER_CONNECTED and SERVERSSL_CLIENTHELLO_SEND events and are therefor unusable.
My test iRule is below. As soon I set a variable in CLIENT_ACCEPT, CLIENTSSL_CLIENTHELLO or CLIENTSSL_HANDSHAKE the "var2" set in HTTP_REQUEST is not available in the SERVER_CONNECTED, SERVERSSL_CLIENTHELLO_SEND or HTTP_REQUEST_SEND, but in the HTTP_REQUEST_RELEASE event.
Another finding in my tests is that the HTTP_REQUEST_SEND event is not triggered as soon there is a HTTP/2 Profile (Server) attached, but this is another topic.
when CLIENT_ACCEPTED {
#log local0. "Set var1 to client_accept"
#set var1 "client_accept"
}
when CLIENTSSL_CLIENTHELLO {
#log local0. "Set var1 to clientssl_hello"
#set var1 "clientssl_hello"
}
when CLIENTSSL_HANDSHAKE {
#log local0. "Set var1 to clientssl_handshake"
#set var1 "clientssl_handshake"
}
when HTTP_REQUEST {
if { [info exists var1] } {
log local0. "var1: $var1"
} else {
log local0. "var1: not set"
}
log local0. "Set var1 to http_request"
set var1 "http_request"
log local0. "Set var2 to http_request"
set var2 "http_request"
}
when MR_INGRESS {
if { [info exists var1] } {
log local0. "var1: $var1"
} else {
log local0. "var1: not set"
}
if { [info exists var2] } {
log local0. "var2: $var2"
} else {
log local0. "var2: not set"
}
MR::store var1
MR::store var2
}
when MR_EGRESS {
if { [info exists var1] } {
log local0. "var1: $var1"
} else {
log local0. "var1: not set"
}
if { [info exists var2] } {
log local0. "var2: $var2"
} else {
log local0. "var2: not set"
}
MR::restore var1
MR::restore var2
}
when SERVER_CONNECTED {
if { [info exists var1] } {
log local0. "var1: $var1"
} else {
log local0. "var1: not set"
}
if { [info exists var2] } {
log local0. "var2: $var2"
} else {
log local0. "var2: not set"
}
}
when SERVERSSL_CLIENTHELLO_SEND {
if { [info exists var1] } {
log local0. "var1: $var1"
} else {
log local0. "var1: not set"
}
if { [info exists var2] } {
log local0. "var2: $var2"
} else {
log local0. "var2: not set"
}
}
when HTTP_REQUEST_SEND {
if { [info exists var1] } {
log local0. "var1: $var1"
} else {
log local0. "var1: not set"
}
if { [info exists var2] } {
log local0. "var2: $var2"
} else {
log local0. "var2: not set"
}
}
when HTTP_REQUEST_RELEASE {
if { [info exists var1] } {
log local0. "var1: $var1"
} else {
log local0. "var1: not set"
}
if { [info exists var2] } {
log local0. "var2: $var2"
} else {
log local0. "var2: not set"
}
}
MR::store, MR::restore as well as most other MR::* command are broken for HTTP2 workloads. MRF-HTTP2 is a very purpose driven, optimized and stripped down MRF-Mode.
Regarding HTTP_REQUEST_SEND: You may check the HTTP2-MRF event flow observations i gathered during my DEBUG_PAGE explorations. Between the lines your will find the solution for this...
# Information: Dealing with Keep-Alive Sessions for HTTP2 is sometimes annoying. Restart your browser or kill connections
# via TMSH if you feel that LTM does not do what you want...
# CLIENT_ACCEPTED
# CLIENTSSL_CLIENTHELLO
# CLIENTSSL_CLIENTCERT
# CLIENTSSL_HANDSHAKE
# CLIENTSSL_DATA_CS_INGRESS
# Note: HTTP2::disconnect is badly needed to trigger CLIENTSSL_* events on every single request.
# Unfortunately Chromium will stall after 6 GOAWAY responses (used by HTTP2::disconnect) for up to 5 minutes, because of
# a well known bug (see Chromium bug tracker ID=1030255).
# You may use Fiddler Everywhere as MitM to get full HTTP2::disconnect support to dig into the CLIENTSSL_* events. But even
# then you will end up with limited DEBUG PAGE support because of lacking SSL Renegotiation to inject cookies backwards
# into the session.
#
# My best advise is to debug clientside SSL handshakes using HTTP/1 to get full a interactive experience.
# HTTP_REQUEST
# MR_INGRESS_CS (the event is called MR_INGRESS, but filtering is based on [IP::remote_addr] eq [IP::client_addr])
# PERSIST_DOWN (async event)
# LB_SELECTED (async event)
# LB_FAILED (async event if error happens during SS connection establishment)
# MR_FAILED (async event if error happens during SS connection establishment)
# Note: LB_FAILED and MR_FAILED trigger at the same time. Both event allow HTTP2 based responses.
# SERVER_CONNECTED
# SERVERSSL_CLIENTHELLO_SEND
# SERVERSSL_SERVERHELLO
# SERVERSSL_SERVERCERT
# SERVERSSL_HANDSHAKE
# SERVERSSL_DATA_SS_EGRESS
# Note: SERVERSSL_DATA_SS_EGRESS (the event is called SERVERSSL_DATA) get triggered when SSL::collect was called in SERVERSSL_HANDSHAKE
# It seems to be egress HTTP2.0 communication to the backend server to negotiate the HTTP2 session.
# MR_EGRESS_SS (the event is called MR_EGRESS, but filtering is based on [IP::remote_addr] eq [IP::server_addr])
# HTTP_REQUEST_RELEASE
# Note: The HTTP_REQUEST_SEND event does not trigger for HTTP2 in GW mode (could be a bug). Only HTTP_REQUEST_SEND triggers.
# SERVERSSL_DATA_SS_INGRESS
# Note: SERVERSSL_DATA_SS_INGRESS (the event is called SERVERSSL_DATA) get triggered when SSL::collect was called in HTTP_REQUEST_RELEASE
# It seems to be ingress HTTP2.0 communication from the backend server.
# The event is able to receive a cookie header via variable, but you can not pass information to other events via table nor variables (at least not stable!).
# Using static:: namespace allows a stable cross communication to the HTTP RESPONSE event to become able to deliver the page.
# HTTP_RESPONSE
# MR_INGRESS_SS
# MR_EGRESS_CS
# HTTP_RESPONSE_RELEASE
# Note: Using the DEBUG PAGE for event trigger after HTTP_RESPONSE_RELEASE is not possible, because we wont get a chance
# to send a HTTP response after this event has been triggered.
# You may still trigger the page on those event an store the HTLM to [table] and review the content later,
# but this is not very useful.
# CLIENTSSL_DATA_CS_EGRESS
# Note: CLIENTSSL_DATA_CS_EGRESS (the event is called CLIENTSSL_DATA) get triggered when SSL::collect was called in HTTP_RESPONSE_RELEASE
# It seems to be egress HTTP2.0 communication to the client.
Note: Whenever you see *_CS and *_SS or even *_CS_INGRESS and *_CS_EGGRESS event names. It means that a given even triggers more tan once during a single HTTP Request/Response.
Drop me an E-Mail and I will give you a personal DEBUG_PAGE session for HTTP2 with MRF-Router
Cheers, Kai
- Juergen_MangSep 17, 2025
MVP
I already gave up using MR:: commands and I also do not use MR_* events. I want iRules that work independently from the HTTP version.
F5 support already confirmed that the HTTP_REQUEST_SEND event is not triggered with HTTP2 MRF-Router, but this is only internally documented. The MR_EGRESS event should be used instead, unfortunately this event does not support all the iRule commands HTTP_REQUEST_SEND supports.
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