Score:0

Mobile redirect in nginx with query string

lc flag

I'm trying to redirect mobile visitors to AMP pages with nginx. I've basically using the script @ https://gist.github.com/dangayle/2919206 with recommended modifications, plus elements from the answer @ add a URL suffix path (for mobile AMP) without causing a redirect loop in nginx_

The main difference here is that I'm not trying to redirect mobile users to a mobile sub-domain, and instead just add a query string ("?amp=1"):

That's the code in the HTTP block for nginx.conf:

    default 0;

    "~* (android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino" 1;

    "~* ^(1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-)" 1;
}

and the remaining code in location /:

set $mobile_rewrite do_not_perform;

if ($mobile_agent = 1){
    set $mobile_rewrite perform;
}

if ($mobile_agent = 1){
    set $mobile_rewrite perform;
}

#check if query arg = yes (example.com?mobile=yes), set variable
if ($arg_mobile = 'yes') { 
    add_header Set-Cookie mobile=yes;
    set $mobile_rewrite perform;
}

#check if cookie mobile=yes, set variable
if ($cookie_mobile = 'yes') { 
    set $mobile_rewrite perform;
}

#check if cookie mobile=no, break
if ($cookie_mobile = 'no') { 
    set $mobile_rewrite do_not_perform;
}

#check if query arg = no (example.com?mobile=no), break
if ($arg_mobile = 'no') { 
    add_header Set-Cookie mobile=no;
}

#if $mobile_rewrite = perform, do the redirect
if ($mobile_rewrite = perform) {
    rewrite ^.*(?<!/?amp=1)$ $scheme://www.cnx-software.es$request_uri?amp=1 break;
}

I still get troubles with redirects stuck in a loop. For example: https://www.cnx-software.es/2021/08/31/arm-china-ahora-es-totalmente-independiente-de-arm/?amp=1?amp=1&amp=1?amp=1&amp=1?amp=1&amp=1?amp=1&amp=1?amp=1&amp=1...

The problem is probably the rewrite line, but I have been able to pinpoint the exact issue.

Score:1
us flag

You are trying to do a negative match in regex to prevent rewrites when amp query argument is 1 in the request URL.

It is better to do this check with one more if block:

if ($arg_amp = 1) {
    set $mobile_rewrite do_not_perform;
}

Then your rewrite can be:

if ($mobile_rewrite = perform) {
    rewrite ^ $scheme://www.cnx-software.es$request_uri?amp=1 break;
}
lc flag
Thank you. It works, it's much simpler than what I attempted to do. I have read we should avoid using "if" in location blocks. But anyway, somehow for some reason, the redirection caused a 404 error on mobile only, and after moving the code up right below the server_name line, it's OK now. Another note. nginx says return should be used instead of rewrite when possible in https://www.nginx.com/blog/creating-nginx-rewrite-rules/ So would it be better to use something like ```return 301 $scheme://www.cnx-software.es$request_uri?amp=1;``` Or it does not really matter?
us flag
I was thinking about using `return`, but since you used `break` with the `rewrite`, it only performs an internal rewrie. Also, I think a permanent redirect isn't good in this case.
lc flag
I've just noticed this creates a problem with links shared on Facebook, or other sources that add one or more query strings. So I created a map `map $is_args $separator { default "?"; "?" "&"; }` and changed the rewrite as follows: `rewrite ^ $scheme://www.cnx-software.es$request_uri${separator}amp=1 break;` It almost work, but for some reasons after a first redirect that does: https://www.cnx-software.es/2021/09/23/un-primer-vistazo-a-la-placa-de-desarrollo-microchip-polarfire-soc-fpga-icicle/?fbclid=xxx&amp=1, it goes in a loop with $arg_amp=1 not detected.
lc flag
Interesting... If I click on the link with ?fbclid=xxx&amp=1, then it works, but not when going to a link with just ?fbclid=xxx. It looks like my redirection creates a link with "?fbclid=xxx&amp=1?fbclid=xxx" instead... So the amp arg value is "1?fblcid=xxx" instead... How is that possible?
us flag
This might happen because of the default behavior of nginx to append query strings on rewrites. I will refine my answer to address this.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.