URL rewriting QUERY_STRING NGINX? - nginx

I want to download any file from the host whose last address had the x-oss-process parameter.
i.php?path=$1&x-oss-process=%1
Refer that $1 is the address of the referenced file and %1 is the value of the x-oss-process parameter
Like the link below
https://dl.example.com/img/all/235868.jpg?x-oss-process=image/resize,m_lfit,h_200,w_200/quality,q_60
After referring this address to the following address
i.php?path=img/all/235868.jpg&x-oss-process=image/resize,m_lfit,h_200,w_200/quality,q_60
Now how do I write the nginx code to do this? Thank you for your help.

If the query argument name didn't contain any dash characters, like x_oss_process instead of x-oss-process, the solution would be much more simple. In that case we could check $arg_x_oss_process variable (see $arg_name variable description):
if ($arg_x_oss_process) {
rewrite ^ /i.php?path=$uri;
}
The first parameter ^ is a regex that matches any string, $uri is a normalized request URI (without query arguments). All the query arguments would be added to the rewrited URI (see the rewrite directive description):
If a replacement string includes the new request arguments, the previous request arguments are appended after them. If this is undesired, putting a question mark at the end of a replacement string avoids having them appended, for example:
rewrite ^/users/(.*)$ /show?user=$1? last;
However since your query argument name contain dashes, the solution will be more complex (see this SO question for additional details). We would need to get the x-oss-process query argument value from $args variable using the map directive which shoud be placed outside the server block:
map $args $x_oss_process {
~(?:^|&)x-oss-process=([^&]*) $1;
}
server {
...
if ($x_oss_process) {
rewrite ^ /i.php?path=$uri;
}
...
}
This rewrite rule will rewrite
/img/all/235868.jpg?x-oss-process=image/resize,m_lfit,h_200,w_200/quality,q_60
request to the
/i.php?path=/img/all/235868.jpg&x-oss-process=image/resize,m_lfit,h_200,w_200/quality,q_60
This is slighly different from what you've been asked for (note the slash before img/all/235868.jpg URI part). I'd rather change i.php script to correctly process this, but if you want to strip this slash with nginx itself, you can use second map block:
map $args $x_oss_process {
~(?:^|&)x-oss-process=([^&]*) $1;
}
map $uri $truncated_uri {
~/(.*) $1;
}
server {
...
if ($x_oss_process) {
rewrite ^ /i.php?path=$truncated_uri;
}
...
}

Related

Nginx rewrite any arg name

I am trying to build a rewrite for CDN system which uses arguments to point to the data. All data is stored in the same location so any rewrite needs to wildcard rewrite the $arg_name and then pass the value for the data along. Turning this:
http://cdn.example.com/data/?main_loc=datastring
into this:
http://example.com/datastore/datastring
Using a location directive I can fetch the request to /data/, but from there I don't know what the rewrite would need to look like to do a "match any arg name" like main_loc, backup_loc etc. to pass its value as rewrite.
Can I apply regex to match any $arg_name and use the value from that?
location ^~ /data/ {
rewrite ^$arg_(\w*\_\w*)$ http://example.com/datastore/$1;
}
Or what would that look like?
You could capture the arg value with the following map:
map $args $arg_value {
~=(.*) $1;
}
Then redirect to it:
location = /data/ {
return 301 http://example.com/datastore/$arg_value;
}

Nginx redirect a specific file path to file path with an extra query param if it's not there

My redirection requirements are:
http://localhost/module/client/core/client_loader.js should redirect to http://localhost/module/client/core/client_loader.js?v=1.0
http://localhost/module/client/core/client_loader.js?s1=t1&s2=t2 should redirect to http://localhost/module/client/core/client_loader.js?s1=t1&s2=t2&v=1.0
http://localhost/module/client/core/client_loader.js?v=1.0 should not redirect
http://localhost/module/client/core/client_loader.js?s1=t1&v=1.0 should not redirect
If the filepath does not have a query paramerter "v" then it should append query parameter and redirect otherwise just leave it. Here conditions A{} and AB{} working but redirection is not working. nginx version is nginx/1.21.3. Any help please.
location = /module/client/core/client_loader.js {
set $cond "";
if ($arg_v = "") {
set $cond A;
}
if ($is_args) {
set $cond "${cond}B";
}
if ($cond = AB) {
# if the path has query parameters but does not have "v" query param
rewrite ^ /client_loader.js?$args&v={{ .Values.version }} break;
}
if ($cond = A) {
# if the path doesn't have query parameters also does not have "v" query param
rewrite ^(.*)$ $1?v={{ .Values.version }} break;
}
}
I'm assuming you need a redirect rather than internal URI rewrite. To get a redirect you need to use either permanent (for HTTP 301 redirection) or redirect (for HTTP 302 redirection) flag. nginx rewrite directive (as well as location one) works with so-called normalized URI which does not include a query part (check the location directive documentation for additional details about URI normalization). And as it stated by the rewrite directive documentation:
If a replacement string includes the new request arguments, the previous request arguments are appended after them. If this is undesired, putting a question mark at the end of a replacement string avoids having them appended, for example:
rewrite ^/users/(.*)$ /show?user=$1? last;
So you can add the following if block to your configuration:
if ($arg_v = '') {
# add 'v' query argument if an URI is '/module/client/core/client_loader.js' and don't touch any other URI
rewrite ^/module/client/core/client_loader\.js$ /module/client/core/client_loader.js?v={{ .Values.version }} permanent;
# any other query arguments will be preserved
}

Prevent user from overwriting query string parameter with Nginx rewrite

I have the following Nginx rewrite rule:
rewrite ^/([a-z0-9-]+)$ /post.php?slug=$1 last;
Nginx will now apply rewrites like the following:
/a -> /post.php?slug=a
/a?slug=b -> /post.php?slug=a&slug=b
The second example is problematic. How can I prevent visitors from adding query string parameters that are already added by rewrite rules? Other query string parameters may still be supplied. Examples of desired behavior:
/a -> /post.php?slug=a
/a?slug=b -> /post.php?slug=a
/a?foo=b -> /post.php?slug=a&foo=b
You can remove slug query argument:
location ~ ^/(?<slug>[a-z0-9-]+)$ {
if ($args ~ (.*)(^|&)slug=[^&]*(\2|$)&?(.*)) {
set $args $1$3$4;
}
rewrite ^ /post.php?slug=$slug last;
}
This complex regex would remove slug query argument from query arguments string regardless of whether it is at the beginning, in the middle or at the end of that string.

Nginx rewtire question mark

I use Windows 7 for developing web sites. Now I have a problem on rewrite an url. Try to change a question mark to an underscore, but nothings seems to work.
location /site/ {
rewrite "^skript.php([?]{1})(.*)$" skript.php_$2;
}
Url should be "skript.php_$args.
Solution needed.
The ? is the delimiter for the query string. The rewrite and location directives use a normalised URI which already has the query string removed and placed into $args.
There are a number of ways to append _$args to the URI, depending on what you are trying to achieve. For example:
location = /foo.php {
rewrite ^ $uri_$args?;
}
Or:
location = /foo.php {
return 301 $uri_$args;
}
Or:
rewrite ^/foo.php$ $uri_$args?;
See this and this for details.

Nginx rewrite: how to change URL from dynamic to static

I'm configuring nginx as reverse proxy.
I need to change (rewrite?) the URLs, example: when the request (to nginx Reverse Proxy) is "http://example.com/test/?username=test1;password=passwdtest1" it will must "modified" to the main server as "http://example.com/test/?username=production;password=passwdproduction1".
Consider that in the original request the fields "username=test1;password=passwdtest1" are not always the same (they changes), instead the "modified" to the main server are always the same.
Others example to be more clear:
"/test/?username=test1;password=passwdtest1" -> "/test/?username=production;password=passwdproduction1"
"/test/?username=test1876;password=somepasswd" -> "/test/?username=production;password=passwdproduction1"
"/test/?username=somevalues;password=somepasswdvalue" -> "/test/?username=production;password=passwdproduction1"
So, independently to what are the values of "?username=somevalues;password=somepasswdvalue" it should always become "?username=production;password=passwdproduction1".
Thanks for your help!
A little late on the answer but this should work for you:
location ~* /test/? {
if ($arg_username ~ "^$|\s+") { return 404; }
if ($arg_password ~ "^$|\s+") { return 404; }
rewrite ^ /test?username=production&password=passwdproduction1? permanent;
}
The code above checks if it is within the example.com/test path. If it is it will check if the user name or the password variable are present and not empty in the query string. In case if any isn't present or is empty it will return a 404 else it will redirect you to the preferred url.
By the way, instead of the semicolon in your example urls I would use an ampersand (&).

Resources