I've actually done something similar to this. Give this a try:
proc send_to_sideband { data server } {
set sbserver [connect -protocol TCP -timeout 100 -idle 5 -status conn_status $server]
send -status send_status -timeout 100 $sbserver $data
return [recv -status recv_status -timeout 300 $sbserver]
}
when RULE_INIT {
set static::SBSERVER "10.80.0.65:8888"
}
when HTTP_REQUEST {
HTTP::header remove Accept-Encoding
if { [HTTP::payload] eq "" } {
set sb [call send_to_sideband [HTTP::request] $static::SBSERVER]
} else {
HTTP::collect [HTTP::header Content-Length]
}
}
when HTTP_REQUEST_DATA {
set sb [call send_to_sideband "[HTTP::request]\r\n\r\n[HTTP::payload]" $static::SBSERVER]
}
when HTTP_RESPONSE {
if { [HTTP::header exists Content-Length] } {
HTTP::collect [HTTP::header Content-Length]
}
}
when HTTP_RESPONSE_DATA {
set version [HTTP::version]
switch [HTTP::status] {
"200" { set status "[HTTP::status] OK" }
"204" { set status "[HTTP::status] No Content" }
"301" { set status "[HTTP::status] Moved Permanently" }
"302" { set status "[HTTP::status] Found" }
"304" { set status "[HTTP::status] Not Modified" }
"307" { set status "[HTTP::status] Temporary Redirect" }
"400" { set status "[HTTP::status] Bad Request" }
"401" { set status "[HTTP::status] Unauthorized" }
"402" { set status "[HTTP::status] Payment Required" }
"403" { set status "[HTTP::status] Forbidden" }
"404" { set status "[HTTP::status] Not Found" }
"405" { set status "[HTTP::status] Method Not Allowed" }
"500" { set status "[HTTP::status] Internal Server Error" }
"501" { set status "[HTTP::status] Not Implemented" }
"502" { set status "[HTTP::status] Bad Gateway" }
"503" { set status "[HTTP::status] Service Unavailable" }
}
foreach x [HTTP::header names] {
append hdr "$x: [HTTP::header $x]\r\n"
}
set sb [call send_to_sideband "HTTP/$version $status\r\n$hdr\r\n[HTTP::payload]" $static::SBSERVER]
}
So here's the thing. In the HTTP_REQUEST event, I'm either sending the sideband request if the payload is empty (like with a typical GET request) using just [HTTP::request] - the full HTTP message up to the end of the headers, or collecting on the Content-Length and then doing the sideband request with both [HTTP::request] and [HTTP::payload]. The sideband VIP will get this, and because it's a properly formatted HTTP request, will trigger its own HTTP_REQUEST event. When the real server responds, we don't have the benefit of an [HTTP::response] command that contains all of the HTTP response message up to the end of the headers, so you have to build it from scratch from the available variables. So then we take the rebuilt headers and payload and make another sideband request. This time however, the sideband iRule shouldn't trigger its HTTP_REQUEST event because the incoming data isn't a valid HTTP request. If you've formatted the data correctly it may trigger the HTTP_RESPONSE event (because it's actually a response), but then the more reliable method may simply be (potentially in both directions) to just look at the data at the TCP layer.
when CLIENT_ACCEPTED {
TCP::collect
}
when CLIENT_DATA {
log local0. [TCP::payload]
TCP::release
TCP::collect
}