When working with Domino server applications behind an Nginx reverse proxy, the X-XspLocation
header presents a unique challenge. This header contains internal server URLs that need to be transformed before reaching the client.
The typical Nginx header manipulation pattern of proxy_hide_header
followed by add_header
doesn't work as expected because:
- Nginx processes these directives in a specific order
- The header modification occurs at a different phase of request processing
- Multiple headers can end up being sent to the client
Here's the effective configuration that resolves this issue:
map $sent_http_x_xsplocation $xsplocation_new {
default "";
"~http://localhost:81/database.nsf/page.xsp/(.*)" "/$1";
}
server {
# ... other server configuration ...
location / {
proxy_pass http://localhost:81/database.nsf/page.xsp/;
# Remove original header
proxy_hide_header X-XspLocation;
# Add modified header only when the original exists
if ($xsplocation_new) {
add_header X-XspLocation $xsplocation_new;
}
}
}
Several important details make this solution work:
- The
map
directive should have a default value to avoid errors - Conditional header addition prevents empty headers from being sent
- The regex pattern must exactly match your specific URL format
For more complex transformations, consider using Nginx JavaScript:
js_import /etc/nginx/conf.d/header_handler.js;
server {
# ... other configuration ...
location / {
proxy_pass http://localhost:81/database.nsf/page.xsp/;
js_header_filter header_handler.processHeaders;
}
}
With header_handler.js
containing:
function processHeaders(r) {
const location = r.headersOut['X-XspLocation'];
if (location) {
const newLocation = location.replace(
/http:\/\/localhost:81\/database.nsf\/page.xsp\/(.*)/,
'/$1'
);
r.headersOut['X-XspLocation'] = newLocation;
}
}
export default { processHeaders };
Always verify your header modifications using:
curl -I https://yourdomain.com/test-url
Or with more detailed inspection:
curl -vsk https://yourdomain.com/test-url 2>&1 | grep -i X-XspLocation
When implementing header transformations:
- Map operations are generally faster than regex replacements
- JavaScript processing adds overhead but offers more flexibility
- Consider caching transformed values for frequently accessed URLs
If you encounter problems:
- Check Nginx error logs:
tail -f /var/log/nginx/error.log
- Verify variable values using
add_header Debug $variable_name
- Ensure there are no conflicting header modifications elsewhere in your config
When working with Domino servers behind Nginx reverse proxies, one particular pain point is handling the X-XspLocation header. This special header generated by XPages often contains full internal URLs that need to be rewritten before reaching the client.
The main issues we face:
Original header: http://localhost:81/database.nsf/page.xsp/ThankYou
Desired output: /ThankYou
Standard Nginx header manipulation techniques don't work well here because:
- proxy_hide_header completely removes the header
- add_header creates duplicate headers if the original isn't hidden
- The map directive works but needs proper header replacement
The most reliable solution is to use Nginx's Headers More module. Here's the complete implementation:
load_module modules/ngx_http_headers_more_filter_module.so;
map $sent_http_x_xsplocation $xsplocation_new {
"~http://localhost:81/database.nsf/page.xsp/(.*)" "/$1";
default "";
}
server {
# ... other server config
location / {
proxy_pass http://localhost:81/database.nsf/page.xsp/;
# Header manipulation
more_set_headers -s 200 'X-XspLocation: $xsplocation_new';
more_clear_headers 'X-XspLocation';
}
}
If you can't use additional modules, this approach works with standard Nginx:
map $sent_http_x_xsplocation $xsplocation_new {
"~http://localhost:81/database.nsf/page.xsp/(.*)" "/$1";
default "";
}
server {
# ... other server config
location / {
proxy_pass http://localhost:81/database.nsf/page.xsp/;
# Hide original and add new only when map returns value
proxy_hide_header X-XspLocation;
if ($xsplocation_new) {
add_header X-XspLocation $xsplocation_new;
}
}
}
When implementing this solution:
- Ensure your map directive appears outside server blocks
- The regex pattern must match your specific Domino configuration
- Test with curl -I to verify header changes
- Clear browser cache when testing as 301/302 redirects get cached
To troubleshoot header issues, add these directives temporarily:
add_header X-Debug-Original-XspLocation $sent_http_x_xsplocation;
add_header X-Debug-New-XspLocation $xsplocation_new;
This will show you exactly what's happening with the header transformation.