7

I'm trying to configure nginx as a reverse proxy server for a web application on a back-end Domino server. We have 99.9% working, but that last 0.1% is really bugging me.

I'll explain. In some cases, the application returns a partial refresh with a special response header called X-XspLocation. If it exists, it contains a url to be redirected to by the client. It's a header generated and used by the XPages environment, my code itself doesn't set or read it. Its value is then:

http://localhost:81/database.nsf/page.xsp/ThankYou

and I want it to be just this: /ThankYou

I tried in a million ways, but it seems impossible to alter its value. As soon as I use proxy_hide_header X-XspLocation; no new headers can be added using add_header! If I leave the hide out, I get double values in the header, so I know my replacement value is correct. Here's my latest attempt that failed:

map $sent_http_x_xsplocation $xsplocation_new {
    "~http://localhost:81/database.nsf/page.xsp/(.*)" "/$1";
}
server {
    ...
    location / {
      proxy_pass   http://localhost:81/database.nsf/page.xsp/;
      # redirect X-XspLocation
      proxy_hide_header X-XspLocation;
      add_header X-XspLocation $xsplocation_new;
      #add_header X-XspLocation2 $xsplocation_new;
    }
}

I even tried with njs to change the header, it probably failed because I don't know how to use js_set or js_content to call a function that doesn't return anything.

Why is it so darned difficult to modify a response header??

The real question is of course: how can I make this work?? Thanks for your assistance!!

More info

In order to prove that the map works, I tested with the following:

    location / {
      proxy_pass   http://localhost:81/database.nsf/page.xsp/;
      # redirect X-XspLocation
      # proxy_hide_header X-XspLocation;
      # add_header X-XspLocation $xsplocation_new;
      add_header X-XspLocation2 $xsplocation_new;
    }

The result is now that the original header plus the new header X-XspLocation2 are present, and the 2nd one is exactly what I need in X-XspLocation.

By the way, nginx version: nginx/1.18.0 on Ubuntu 16.04.6 LTS (My client's provider's system, not mine...)

The full censored config file

map $sent_http_x_xsplocation $xsplocation_new {
    "~http://localhost:81/database.nsf/page.xsp/(.*)" "/$1";
}

server {
    listen       4443 ssl;
    server_name  www.myclient.nl;

    ssl_certificate       /etc/nginx/ssl/www.myclient.nl.pem;
    ssl_certificate_key   /etc/nginx/ssl/www.myclient.nl.pem;

    # do not allow google to index this website
    # TODO: remove when going to production
    add_header  X-Robots-Tag "noindex, nofollow, nosnippet, noarchive";

    # replace redirects in response header fields Location and Refresh
    proxy_redirect http://localhost:81/database.nsf/page.xsp/ https://www.myclient.nl:4443/;
    proxy_redirect http://localhost:81/ https://www.myclient.nl:4443/;

    # tell domino not to encode the response so we can use sub_filter
    proxy_set_header Accept-Encoding "";

    # substitute response content
    sub_filter 'localhost:81'       'www.myclient.nl:4443';
    sub_filter 'www.myclient.nl' 'www.myclient.nl:4443'; #TODO: remove when going production
    sub_filter '/database.nsf/page.xsp/'  '/';
    sub_filter '/database.nsf/'           '/other/';
    sub_filter_once off;

    # Domino
    location = /favicon.ico {
      access_log off; log_not_found off;
      proxy_pass http://localhost:81/database.nsf/Images/favicon.ico/%24file/favicon.ico;
    }

    # root / homepage
    location = / { proxy_pass   http://localhost:81/database.nsf/page.xsp/HomePage; }

    #login
    location /names.nsf { proxy_pass http://localhost:81/names.nsf; }

    # XPages
    location /xsp/ { proxy_pass  http://localhost:81/xsp/; }
    location /domjava/ { proxy_pass  http://localhost:81/domjava/; }

    # training
    location ~* ^/.*-training/(.*) {
      proxy_pass http://localhost:81/database.nsf/page.xsp/training/$1;
    }
    location ~* ^/(.*)-training$ {
      proxy_pass http://localhost:81/database.nsf/page.xsp/$1;
    }

    # IMAGES
    # image resources - any case insensitive match with 'images'
    location ~* '/images/(.*)$' {
      proxy_pass   'http://localhost:81/database.nsf/Images/$1';
    }
    # images referenced from css in file.xsp have this url, redirect to backend correctly
    location ~* '/file.xsp/images/(.*)$' {
      proxy_pass   'http://localhost:81/database.nsf/Images/$1';
    }

    # file resources
    location /file.xsp/ { proxy_pass  http://localhost:81/database.nsf/file.xsp/; }

    # other resources
    location /other/ { proxy_pass   http://localhost:81/database.nsf/; }

    # all other urls
    location / {
      proxy_pass   http://localhost:81/database.nsf/page.xsp/;
      # redirect X-XspLocation
      #add_header X-XspLocation $xsplocation_new always;
      proxy_hide_header X-XspLocation;
      add_header X-XspLocation $xsplocation_new;
    }
}

3 Answers 3

9

"Why is it so darned difficult to modify a response header??"

Some people need to make a living too!

Ah, that wasn't the real question. Damn. Try this

map $upstream_http_x_xsplocation $m_replaceme {
    ""  "";
    "~^.*/page.xsp/(.*)$" "/$1";
    "~.*" "";
}

location / {
      proxy_pass   http://localhost:81/database.nsf/page.xsp/;
      proxy_hide_header X-XspLocation;
      add_header X-XspLocation  $m_replaceme;
}

Tested with nginx/1.14.2

20
  • It's always money, isn't it... :-(
    – D.Bugger
    May 21, 2020 at 11:56
  • Nope, doesn't work. The header X-XspLocation disappears but the new one isn't created. I forgot to mention that most of it works if I add a header, but not for the original header. I'll modify the question.
    – D.Bugger
    May 21, 2020 at 12:04
  • 1
    Did I forget to mention that I tested it? "Its value is then something like:". It might help to show us an exact value. May 21, 2020 at 12:18
  • Nope. The chances of anything coming from Mars... and still it doesn't work here. I even left out the hide, and changed the header name to X-XspLocation2: no dice.
    – D.Bugger
    May 21, 2020 at 12:19
  • 1
    You did replace "$sent_http_x..." by "$upstream_http_x..." ? May 21, 2020 at 12:26
4

Added always works for me

proxy_hide_header X-XspLocation;
add_header X-XspLocation  $m_replaceme always;
1
  • me, tested, this can modify already added header
    – Dee
    May 24 at 9:52
0

Apparently adding header to proxy response from backend is a bit problematic in nginx without recompilation.

add_header will add header to the request from proxy to backend server. It will achieve the goal only if the backend returns the same header without modification in own response. Which may happen, but is not guaranteed of course. Thus, if that doesn't happen - you can try to configure your backend to allow such behavior.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .