How to get nginx to do a redirect to url-encoded query parameter
Actually, proxy_pass
does normalisation by default, but it only affects $uri
part. Thus you only need to decode the beginning of the passed string to get it working:
location / { if ( $arg_redirect = '') { return 400 "Missing redirect directive in request"; } if ( $arg_redirect ~ (.+)%3A%2F%2F(.+) ){ # fix :// between scheme and destination set $arg_redirect $1://$2; } if ( $arg_redirect ~ (.+?)%3A(.*) ){ # fix : between destination and port set $arg_redirect $1:$2; } if ( $arg_redirect ~ (.+?)%2F(.*) ){ # fix / after port, the rest will be decoded by proxy_pass set $arg_redirect $1/$2; } proxy_pass $arg_redirect; }
With the above I managed to access http://localhost/?redirect=http%3A%2F%2F127.0.0.1%3A81%2Fsfoo%20something%2Fs
The solution seems dirty and the only alternative using default modules is map
(even less cleaner in my opinion). I'd rather split redirect
argument into pieces: scheme (http or https), destination, port, and uri. With that you would be able to construct full address without rewriting:
proxy_pass $arg_scheme://$arg_dest:$arg_port/$arg_uri
Ok, there is very weird and curious solution
server { listen 80; resolver x.x.x.x; location /basepath { if ($arg_redirect = '') { return 400 "Missing redirect directive in request"; } proxy_pass http://127.0.0.1:80/basepath/$arg_redirect; } location ~ ^/basepath/(?<proto>\w+):/(?<redir>.+)$ { proxy_pass $proto://$redir; }}
Nginx does not encode path with variables in proxy_pass and send it as is. So, I make $arg_* part of proxy_pass uri, send request to self and nginx will receive new request which will be decoded.
But because Nginx will clean path and replace //
to /
I split protocol part in regexp.
And ... I would never recommend using this solution, but it works :)
try like this and let me know if it works
location /basepath { if ( $arg_redirect = '') { return 400 "Missing redirect directive in request"; } set_unescape_uri $decodedredirect $arg_redirect; proxy_pass $decodedredirect; proxy_intercept_errors on; error_page 301 302 307 = @handle_redirects; }