1

I have a URL:

https://www.example.com/test.html

This URL can have query parameters like:

https://www.example.com/test.html?cat=11&rating=5

I want to redirect ONLY:

https://www.example.com/test.html

To:

https://www.example.com/test2

When I do so via:

location = /test.html {
    return 301 https://example.com/test2;
}

The URL with parameters also redirects: https://www.example.com/test.html?cat=11&rating=5

redirects to: https://example.com/test2

Is it possible to redirect URL strictly without the affecting parameters?

UPDATE: I still want https://www.example.com/test.html?cat=11&rating=5 to work as normal, but the https://www.example.com/test.html should do the redirect to /test2

UPDATE: my local docker machine server section of NGINX

server {
    listen      80;
    listen      [::]:80;
    server_name magento.test;

    set $MAGE_ROOT /var/www/php;

    set $maintenance off;

    if (-f $MAGE_ROOT/maintenance.enable){
        set $maintenance on;
    }

    include /var/www/php/nginx.conf;
}

UPDATE:

root $MAGE_ROOT;
index index.php index.html index.htm;
    
autoindex off;
charset UTF-8;
error_page 404 403 = /errors/404.php;
#add_header "X-UA-Compatible" "IE=Edge";
add_header 'X-Content-Type-Options' 'nosniff';    

# Deny access to sensitive files
location /.user.ini {
    deny all;
}


# PHP entry point for setup application
location ~* ^/setup($|/) {
    root $MAGE_ROOT;
    location ~ ^/setup/index.php {
        fastcgi_pass   php:9000;

        fastcgi_param  PHP_FLAG  "session.auto_start=off \n suhosin.session.cryptua=off";
        fastcgi_param  PHP_VALUE "memory_limit=4000M \n max_execution_time=600";
        fastcgi_read_timeout 600s;
        fastcgi_connect_timeout 600s;

        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }

    location ~ ^/setup/(?!pub/). {
        deny all;
    }

    location ~ ^/setup/pub/ {
        add_header X-Frame-Options "SAMEORIGIN";
    }
}

# PHP entry point for update application
location ~* ^/update($|/) {
    root $MAGE_ROOT;

    location ~ ^/update/index.php {
        fastcgi_split_path_info ^(/update/index.php)(/.+)$;
        fastcgi_pass   php:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        fastcgi_param  PATH_INFO        $fastcgi_path_info;
        include        fastcgi_params;
    }

    # Deny everything but index.php
    location ~ ^/update/(?!pub/). {
        deny all;
    }

    location ~ ^/update/pub/ {
        add_header X-Frame-Options "SAMEORIGIN";
    }
}

location / {
    try_files $uri $uri/ /index.php$is_args$args;
}

location /pub/ {
    location ~ ^/pub/media/(downloadable|customer|import|custom_options|theme_customization/.*\.xml) {
        deny all;
    }
    alias $MAGE_ROOT/pub/;
    add_header X-Frame-Options "SAMEORIGIN";
}

location /static/ {
    # Uncomment the following line in production mode
    # expires max;

    # Remove signature of the static files that is used to overcome the browser cache
    location ~ ^/static/version {
        rewrite ^/static/(version\d*/)?(.*)$ /static/$2 last;
    }

    location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2|html|json)$ {
        add_header Cache-Control "public";
        add_header X-Frame-Options "SAMEORIGIN";
        expires +1y;

        if (!-f $request_filename) {
            rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
        }
    }
    location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
        add_header Cache-Control "no-store";
        add_header X-Frame-Options "SAMEORIGIN";
        expires    off;

        if (!-f $request_filename) {
        rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
        }
    }
    if (!-f $request_filename) {
        rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
    }    

    add_header X-Frame-Options "SAMEORIGIN";
}

location /media/ {
    try_files $uri $uri/ /get.php$is_args$args;

    location ~ ^/media/theme_customization/.*\.xml {
        deny all;
    }

    location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ {
        add_header Cache-Control "public";
        add_header X-Frame-Options "SAMEORIGIN";
        expires +1y;
        try_files $uri $uri/ /get.php$is_args$args;
    }
    location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
        add_header Cache-Control "no-store";
        add_header X-Frame-Options "SAMEORIGIN";
        expires    off;
        try_files $uri $uri/ /get.php$is_args$args;
    }
    add_header X-Frame-Options "SAMEORIGIN";
}

location /media/customer/ {
    deny all;
}

location /media/downloadable/ {
    deny all;
}

location /media/import/ {
    deny all;
}

location /media/custom_options/ {
    deny all;
}

location /errors/ {
    location ~* \.xml$ {
        deny all;
    }
}

# PHP entry point for main application
location ~ ^/(index|get|static|errors/report|errors/404|errors/503|health_check)\.php$ {
    try_files $uri =404;
    fastcgi_pass   php:9000;
    fastcgi_buffers 1024 4k;

    fastcgi_param  PHP_FLAG  "session.auto_start=off \n suhosin.session.cryptua=off";
    fastcgi_param  PHP_VALUE "memory_limit=4000M \n max_execution_time=18000";
    fastcgi_read_timeout 600s;
    fastcgi_connect_timeout 600s;

    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

gzip on;
gzip_disable "msie6";

gzip_comp_level 6;
gzip_min_length 1100;
gzip_buffers 16 8k;
gzip_proxied any;
gzip_types
    text/plain
    text/css
    text/js
    text/xml
    text/javascript
    application/javascript
    application/x-javascript
    application/json
    application/xml
    application/xml+rss
    image/svg+xml;
gzip_vary on;

# Banned locations (only reached if the earlier PHP entry point regexes don't match)
location ~* (\.php$|\.phtml$|\.htaccess$|\.git) {
    deny all;
}

1 Answer 1

2

Query arguments are not subject to test in location or rewrite directives, they works only with the normalized URI of HTTP request. The only way to do what you want is to check $args (or $is_args) variable:

location = /test.html {
    if ($is_args = '') {
        return 301 /test2;
    }
    ... # default request processing
}

If you show your full server block, maybe I could suggest more optimized solution. For example, if you have only one location block, something like this should work:

location / {
    if ($is_args = '') {
        rewrite ^/test\.html$ /test2 permanent;
    }
    ... # default request processing
}

However there can be a caveat with this configuration. I don't know if the various browsers takes into account query string while caching redirects, and it could lead to unconditional redirect with any request to /test.html no matter of query string presence. To avoid it I suggest to use 302 temporary redirect:

return 302 /test2;

or

rewrite ^/test\.html$ /test2 redirect;

Update

You can either add this check to server context in the main configuration file:

server {
    listen      80;
    listen      [::]:80;
    server_name magento.test;

    set $MAGE_ROOT /var/www/php;

    set $maintenance off;

    if (-f $MAGE_ROOT/maintenance.enable){
        set $maintenance on;
    }

    if ($is_args = '') {
        rewrite ^/test\.html$ /test2 permanent;
    }

    include /var/www/php/nginx.conf;
}

or to location / { ... } block of magento configuration file:

location / {
    if ($is_args = '') {
        rewrite ^/test\.html$ /test2 permanent;
    }
    try_files $uri $uri/ /index.php$is_args$args;
}
Sign up to request clarification or add additional context in comments.

12 Comments

@KalvinKlien 1. $args variable value doesn't include a question sign, right directive is return 301 /hardware.html?$args;. 2. Are you sure this isn't a cached result? Can you check an actual server response with something like curl from command line? Anyway I'm going to check this on my sandbox, I will tell you what I got after testing this.
@KalvinKlien Oh, of course you got an infinite loop with this config since you are redirecting /hardware.html?some_query_string to itself. And I mean caching inside browser (they caches 301 redirects like any other static content), not nginx caching. You need to process this /hardware.html request like any other requests, but I need to see your whole server block to suggest how to do it.
@KalvinKlien Once again - both location and rewrite directives works with the normalized URI of HTTP request, not the whole request string. You can't check query string with location or rewrite directives, normalized URI does not contain that string, it contains only /hardware.html in your case no matter if query string is present or not. You don't need to shield / symbol in nginx regexes (though you can do it if you want to), but if you don't shield a dot symbol, it would match any character.
@KalvinKlien I need to see your location blocks, this one gave me nothing. Probably they are inside the /var/www/php/nginx.conf? Look at my second example, I'm using location / { ... }, not the /location = test.html { ... }. That's because I want to process any other request default way including /hardware.html with query arguments.
@KalvinKlien You can try if ($is_args = '') { rewrite ^/hardware\.html$ /test-page permanent; } directly in server context outside of any location blocks, add this before the include /var/www/php/nginx.conf; line.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.