Sending extra header in nginx rewrite - nginx

Right now, I am migrating the domain of my app from app.example.com to app.newexample.com using the following nginx config:
server {
server_name app.example.com;
location /app/ {
rewrite ^/app/(.*)$ http://app.newexample.com/$1;
}
}
I need to show-up a popup-banner to notify the user of the domain name migration.
And I want to this based upon the referrer or some-kind-of-other-header at app.newexample.com
But how can I attach an extra header on the above rewrite so that the javascript would detect that header and show the banner only when that header is present coz the user going directly at app.newexample.com should not see that popup-banner?

The thing is that, when you "rewrite" into URI having protocol and hostname (that is http://app.newexample.com/ in your case), Nginx issues fair HTTP redirect (I guess the code will be 301 aka "permanent redirect"). This leaves you only two mechanisms to transfer any information to the handler of new URL:
cookie
URL itself
Since you are redirecting users to the new domain, cookie is no-go. But even in the case of a common domain I would choose URL to transfer this kind of information, like
server_name app.example.com;
location /app/ {
rewrite ^/app/(.*)$ http://app.newexample.com/$1?from_old=yes;
}
This gives you the freedom to process at either Nginx or in a browser (using JavaScript). You may even do what you wanted intially, issuing a special HTTP header for JavaScript in new app server Nginx configuration:
server_name app.newexample.com;
location /app {
if ($arg_from_old) {
add_header X-From-Old-Site yes;
}
}

A similar problem was discussed here. You can try to use a third-party module HttpHeadersMore (I didn't try it myself). But even if it does not work at all, with the help of this module you can do absolutely everything. Example is here.

Your redirect is missing one thing, the redirect type/code, you should add permanent at the end of your rewrite line, I'm not sure what's the default redirect code if not explicitly mentioned.
rewrite ^/app/(.*)$ http://app.newexample.com/$1 permanent;
An even better way is using return
location /app {
return 301 $scheme://app.newexample.com$request_uri;
}
Adding a get parameter as mentioned above would also be a reliable way to do it, you can easily set a session ( flash ) and redirect again to the page it self but after removing the appended get parameter.
EDIT:
Redirecting doesn't send referrer header, if the old domain is still working you could put a simple php file that does the redirect with a header call.
header("Location: http://app.newexample.com")

One possible solution without any headers would be to check the document.referrer property:
if (document.referrer.indexOf("http://app.example.com") === 0) {
alert("We moved!");
}
Using a 301 will set the referrer to the old page. If the referrer doesn't start with the old page url, it was not directed by that page. Maybe a bit quick n dirty, but should work.

Related

Nginx 301 Permanent Redirect For Language Support

I am now enabling language support for my web site. I am including the language as part of the URL. For example: domain.com/en/page I need to setup 301 redirects for existing search engine indexing.
The following works in Nginx to redirect from domain.com/blog to domain.com/en/blog
location = /blog {
return 301 /en/blog;
}
I don't understand the redirect needed to go from domain.com/blog/read/# to domain.com/en/blog/read/# (where # is the sequence field in a postgres database table)
I have spent time looking, searching and reading docs to find this answer myself. I am not understanding.
To prefix the existing requested URI with /en you can use:
return 301 /en$request_uri;
The above will add the three characters before the existing request and also include any arguments that may be present.
To match any URI that begins with /blog, use location /blog { ... }. To match any URI that begins with /blog/read/ use location /blog/read/ { ... }.
Nginx chooses a location to process a request based on a set of rules. So, you will need to consider the other location blocks present within your configuration.

Nginx redirect to url with /#/url

I'm new to using nginx and I'm trying to redirect one url to another.
https://server.com/#/page.html -> https://server.com/page.html
The /#/ comes from using Angular2's router functionality. I decided to change the page to static html because Angular2 loads the entire app at start up and it's unnecessary for this single page of information to be presented as such.
My attempts at solving the problem is as follows. I can redirect from /anotherpage -> /page.html but /#/anotherpage -> /page.html loads the Angular2 app and tries to route to the non existent route.
Using this config and location directives:
server {
listen 8001;
server_name server.com;
...
#SSL Things
...
root /to/root/folder/public;
#Redirects:
location = /anotherpage {
rewrite ^/.* https://$server_name/page.html;
}
#Does not redirect:
location = /#/anotherpage {
rewrite ^/.* https://$server_name/page.html;
}
}
Any suggestions on best practices are welcome as well.
The browser does not send any information after a # is encountered.
Thus when sending https://server.com/#/page.html only https://server.com/ is seen by nginx.
Thus redirecting is not possible and changing the client side application is the only option.

Primary domain rewrite for nginx works fine, but doesn't direct single pages

We just moved our website to a new domain, and the new website uses a totally different URL structure for all of the pages on the website.
For example, the old URL might look like: http://example.com/product/product-name/
The new URL would look like this: http://www.example2.com/product-p/product-name/pro-n.htm
Here's a snippet showing an example of what I'm working with:
server{
location /product/product-name/ {
rewrite ^/product/product-name/
http://www.example2.com/product-p/product-name/pro.htm
permanent;
}
server_name example.com www.example.com;
rewrite ^ $scheme://www.example2.com;
}
As it's working now, http://www.example.com redirects to http://www.example2.com just fine.
However, if you try to visit http://www.example.com/product/product-name/ doesn't redirect to http://www.example2.com/product-p/product-name/pro.htm, it simply redirects to the root domain http://www.example2.com
Does anyone know how we redirect the primary domain AND redirect single pages to their new page?
Thanks,
You need to place your global rewrite directive into a location container:
location / {
rewrite ^ $scheme://www.example2.com;
}
#Richard's answer is fine.
I would only notice that permanent in the end of rewrite directive means 301 redirection, and such redirections are cached by all browsers, which can make it difficult to test. So while you are testing, I would recommend using redirect instead of permanent.
When you're done, put permanent back. Good luck!

Redirecting old URLs to new URLs based on tags

We had a database corruption on our website, now we are building a new one.
However, we have thought off a different approach, we are migrating our old articles to a sub domain and building a new website with a better UI and architecture.
What I would like to do is redirect url from old website to the sub domain, with out in the format as this:
http://olddomain.com/foo/something
to
http://sub.olddomain.com/foo/something
and we want to keep the the olddomain to serve new content
http://oldomain.com/foo2/something
is this possible with Nginx
UPDATE
We have a set word based on which we want to redirect
we just want
http://olddomain/foo/extrainfo
to redirect
http://sub.olddomain/foo/extra
when using the rewrite rule
/abc/ redirect permanent
we are having an issues that is a URL has word foo it's getting redirected to the new domain.
we just want http://olddomain/foo/ to redirect to http://sub.olddomain./foo/extra
not http://olddomain/abc/foo to http://sub.olddomain
You'll need something within your URL to identify if it's an old URL or a new URL. If you have something, than it's easy and we can answer the question. Your given example could easily be solved with:
location ~ ^/[a-z]+/[a-z]+$ {
return 302 $scheme://sub.$server_name$request_uri;
}
location ~ ^/[a-z0-9]+/[a-z]$ {
// serve new stuff
}
But don't forget about search engines and other robots! If you plan to use the original URLs for the new content in the future don't redirect anything and simply deliver the pages at the same places.
Yes, this is simple with nginx. You just need to put a rewrite rule in the correct location/server blocks:
server {
listen 80;
server_name olddomain.com;
location ~/foo/ {
rewrite ^ http://sub.olddomain.com$request_uri? permanent;
}
location / {
#serve new content
}
}
server{
listen 80;
server_name sub.olddomain.com;
location / {
#serve old content
}
}
I would second the previous comment that you should make sure you take into account SEO.

nginx multi-stage 404 handling

We just moved to a new site, and want to redirect old links where necessary - however, some still work. For instance,
/holidays/sku.html
still works, while
/holidays/christmas/
no longer works. I'd like to be able to allow the site to attempt to serve a page, and when a 404 is reached, THEN try to pass it through a series of regex redirects, that may look like:
location ~* /holidays/(.*)+$ { set $args ""; rewrite ^ /holidays.html?r=1 redirect; }
I'm using a ~* location directive instead of doing a direct rewrite because we're moving from a Windows-based ASPX site to Magento with php-fpm behind nginx, so we suddenly have to worry about case sensitivity.
Without using nested location directives (which are actively discouraged by nginx documentation) with an #handler of some sort, what's the best way to allow nginx to attempt to serve the page first, THEN pass it across redirects if it fails?
Thanks!
http://wiki.nginx.org/NginxHttpCoreModule#try_files

Resources