When working with Apache reverse proxy configurations, a common requirement is to set headers only when they're not already present. This becomes particularly important when:
- Multiple layers of proxies might be injecting headers
- Upstream services might provide their own headers
- You want to avoid header duplication or overwrites
The solution lies in using RequestHeader setifempty
instead of the regular set
directive. Here's the improved configuration:
<Location /api>
RequestHeader setifempty MY_HEADER "value"
ProxyPass http://127.0.0.1:8000/api
ProxyPassReverse http://127.0.0.1:8000/api
</Location>
For more complex conditional logic, you can combine multiple directives:
<If "%{HTTP:MY_HEADER} == ''">
RequestHeader set MY_HEADER "default_value"
</If>
Or when dealing with response headers:
Header setifempty X-Custom-Header "backup_value"
Always verify your header behavior with curl:
curl -I http://your.server/api/some-endpoint
While conditional header logic is useful, remember:
- Each conditional check adds minimal overhead
- Complex expressions should be avoided in high-traffic scenarios
- Consider using environment variables for dynamic values
When working with Apache reverse proxies, we often need to set custom headers before forwarding requests. However, blindly setting headers with RequestHeader set
can overwrite existing headers, which might be problematic when:
- Downstream services already set specific headers
- Multiple proxy layers exist in your infrastructure
- You want to respect original headers from clients
Apache provides the setifempty
directive for this exact scenario. Here's how to modify your configuration:
<Location /api>
# Only sets if header doesn't exist
RequestHeader setifempty MY_HEADER "default_value"
# Standard proxy configuration
ProxyPass http://127.0.0.1:8000/api
ProxyPassReverse http://127.0.0.1:8000/api
</Location>
For more complex conditions, you can use Apache's expr syntax:
<Location /api>
# Only set header if not present
RequestHeader set MY_HEADER "value" "expr=%{req:MY_HEADER} == ''"
ProxyPass http://127.0.0.1:8000/api
ProxyPassReverse http://127.0.0.1:8000/api
</Location>
To verify your conditional headers are working:
curl -v http://your-server/api
(without headers)curl -v -H "MY_HEADER: existing_value" http://your-server/api
The second request should preserve the original header value.
- Security Headers: Only set X-Forwarded-For if not present
- Debugging Headers: Add debug headers only when missing
- Canary Deployments: Set routing headers conditionally
The setifempty
directive has minimal overhead compared to regular header setting. The expr-based solution is slightly more resource-intensive but provides greater flexibility for complex conditions.