Forum Discussion
Strict header Insertion
- Nov 19, 2025
You’re running into a very common issue: when you use `HTTP::respond` in an iRule, you completely generate the full response, meaning F5 won’t automatically add additional headers afterward.
So if you want HSTS (or any other header) applied, you must include it directly inside the HTTP::respond command that sends the content.
Also, you can’t use `HTTP_RESPONSE` or `HTTP_RESPONSE_RELEASE` here because there is no server response coming back—you are short-circuiting the request and generating the response directly on the F5.
That means `HTTP_RESPONSE` will never fire.
To solve this situation
Add the HSTS header directly in your `HTTP::respond` commands, like this:
```
when HTTP_REQUEST {
set hsts_header {Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"}switch [HTTP::uri] {
"/" {
HTTP::respond 200 \
content [ifile get webpage_ifile] \
"Content-Type" "text/html" \
$hsts_header
}"/mainpage.png" {
HTTP::respond 200 \
content [ifile get mainpage_ifile] \
"Content-Type" "image/png" \
$hsts_header
}"/favicon.ico" {
HTTP::respond 200 \
content [ifile get favicon_ifile] \
"Content-Type" "image/x-icon" \
$hsts_header
}
}
}
```This will work as the HSTS header is inserted at the moment the response is generated.
Since the F5 is creating the response internally, this is the only chance to add the header.
Make sure this is HTTPS-onlyHSTS must only be applied to HTTPS responses.
If this iRule applies on an HTTP virtual server, you should either redirect HTTP to HTTPS first or add a protocol check.
You can do this once with a small TCL variable
As shown, using a `set` for the header at the top avoids repeating long strings.
If you want to enforce TLS-only redirect
Add this at the top:
```
if { [TCP::local_port] == 80 } {
HTTP::respond 301 Location "https://[HTTP::host][HTTP::uri]"
return
}
```I usually prefer using an HTTP Profile instead of iRule
If your VIP is HTTPS and you want HSTS globally, you can simply:
1. Go to:
```
Local Traffic → Profiles → HTTP → <your HTTP Profile>
```2. Set:
```
HSTS = Enabled
Max Age = 31536000
Include Subdomains = Checked
```This is cleaner and doesn't need iRules.
However, since you're generating the response via `HTTP::respond`, the rule still overrides everything—so adding the header directly in the rule is required unless you switch to standard server responses.
So here is the summary`HTTP::respond` bypasses the normal response pipeline.
Therefore, you must add `Strict-Transport-Security` in the same command that generates the response.
Your updated iRule as above will satisfy the security scan.
let me now for any further assistance.
F5 Design Engineer
You’re running into a very common issue: when you use `HTTP::respond` in an iRule, you completely generate the full response, meaning F5 won’t automatically add additional headers afterward.
So if you want HSTS (or any other header) applied, you must include it directly inside the HTTP::respond command that sends the content.
Also, you can’t use `HTTP_RESPONSE` or `HTTP_RESPONSE_RELEASE` here because there is no server response coming back—you are short-circuiting the request and generating the response directly on the F5.
That means `HTTP_RESPONSE` will never fire.
To solve this situation
Add the HSTS header directly in your `HTTP::respond` commands, like this:
```
when HTTP_REQUEST {
set hsts_header {Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"}
switch [HTTP::uri] {
"/" {
HTTP::respond 200 \
content [ifile get webpage_ifile] \
"Content-Type" "text/html" \
$hsts_header
}
"/mainpage.png" {
HTTP::respond 200 \
content [ifile get mainpage_ifile] \
"Content-Type" "image/png" \
$hsts_header
}
"/favicon.ico" {
HTTP::respond 200 \
content [ifile get favicon_ifile] \
"Content-Type" "image/x-icon" \
$hsts_header
}
}
}
```
This will work as the HSTS header is inserted at the moment the response is generated.
Since the F5 is creating the response internally, this is the only chance to add the header.
Make sure this is HTTPS-only
HSTS must only be applied to HTTPS responses.
If this iRule applies on an HTTP virtual server, you should either redirect HTTP to HTTPS first or add a protocol check.
You can do this once with a small TCL variable
As shown, using a `set` for the header at the top avoids repeating long strings.
If you want to enforce TLS-only redirect
Add this at the top:
```
if { [TCP::local_port] == 80 } {
HTTP::respond 301 Location "https://[HTTP::host][HTTP::uri]"
return
}
```
I usually prefer using an HTTP Profile instead of iRule
If your VIP is HTTPS and you want HSTS globally, you can simply:
1. Go to:
```
Local Traffic → Profiles → HTTP → <your HTTP Profile>
```
2. Set:
```
HSTS = Enabled
Max Age = 31536000
Include Subdomains = Checked
```
This is cleaner and doesn't need iRules.
However, since you're generating the response via `HTTP::respond`, the rule still overrides everything—so adding the header directly in the rule is required unless you switch to standard server responses.
So here is the summary
`HTTP::respond` bypasses the normal response pipeline.
Therefore, you must add `Strict-Transport-Security` in the same command that generates the response.
Your updated iRule as above will satisfy the security scan.
let me now for any further assistance.
F5 Design Engineer
- nmaynardDec 01, 2025
Altocumulus
Apologies on the extremely slow response!
I really appreciate your lengthy response to my post! This was the solution that ended up working in my specific situation. For some reason, blowing away the iRule altogether and adding the headers as a set variable seemed to do the trick. I have had the auditors scan the static page again, and it is now showing the strict header insertion.
Thank you again!
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
