1

I am trying to rewrite/redirect to specific subdomains if the url request path matches some pattern.

I would like to do something like this if i get a request like "https://example.com/users/john/likes" I want to serve this as "https://john.example.com/likes"

Here's what is tried so far: I am able to create the location like

`location ~ ^/users {
    #TODO: some magic
   }`

tried many ways to capture the "john" part of the uri using regex but with no luck a very new in regex any thoughts on how to achieve it ?

Update: As pointed out in the answer I need to serve the requests from nginx conf here's is the configuration I am using please note i am testing this under the subdomain:

server {

  listen 80;
  server_name staging.example.com;
  return 301 https://staging.example.com$request_uri;
}


map $name $uri_prefix {

  ~(.+)$ /users/$1;
}


# This is the new server block I created which will serve the subdomain requests I think i can write conditions in one server block

server {

  listen 443 ssl;
  server_name ~^(?<name>[^\.]+)\.example\.com$;
  client_max_body_size 1000m;
  add_header X-UA-Compatible "IE=Edge,chrome=1";
  root /home/something/app/;

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  ssl_certificate /etc/nginx/ssl/app.crt;
  ssl_certificate_key /etc/nginx/ssl/app.key;

  error_page 500 502 503 504 /500.html;

  location / {

    try_files $uri @prerender;
  }

  location @prerender {

    set $prerender 0;
    if ($http_user_agent ~* "googlebot|bingbot|yandex|baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {

      set $prerender 1;
    }
    if ($args ~ "_escaped_fragment_") {

      set $prerender 1;
    }
    if ($http_user_agent ~ "Prerender") {

      set $prerender 0;
    }
    if ($uri ~* "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff|svg|eot)") {

      set $prerender 0;
    }

    #resolve using Google's DNS server to force DNS resolution and prevent caching of IPs
    resolver 8.8.8.8;

    if ($prerender = 1) {

      #setting prerender as a variable forces DNS resolution since nginx caches IPs and doesnt play well with load balancing
      set $prerender "staging-render.example.com:3000";
      rewrite .* /$scheme://$host$request_uri? break;
      proxy_pass http://$prerender;
    }
    if ($prerender = 0) {

      rewrite ^(.*)$ $uri_prefix$1;
    }
  }
}

server {

  listen 443 ssl;
  server_name staging.example.com;
  client_max_body_size 1000m;
  add_header X-UA-Compatible "IE=Edge,chrome=1";
  root /home/something/app/;

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  ssl_certificate /etc/nginx/ssl/app.crt;
  ssl_certificate_key /etc/nginx/ssl/app.key;

  error_page 500 502 503 504 /500.html;

  location / {

    try_files $uri @prerender;
  }

  location = /sitemap.xml.gz {

    root /home/ubuntu/site_maps;
  }

  location @prerender {

    set $prerender 0;
    if ($http_user_agent ~* "googlebot|bingbot|yandex|baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {

      set $prerender 1;
    }
    if ($args ~ "_escaped_fragment_") {

      set $prerender 1;
    }
    if ($http_user_agent ~ "Prerender") {

      set $prerender 0;
    }
    if ($uri ~* "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff|svg|eot)") {

      set $prerender 0;
    }

    #resolve using Google's DNS server to force DNS resolution and prevent caching of IPs
    resolver 8.8.8.8;

    if ($prerender = 1) {

      #setting prerender as a variable forces DNS resolution since nginx caches IPs and doesnt play well with load balancing
      set $prerender "staging-render.example.com:3000";
      rewrite .* /$scheme://$host$request_uri? break;
      proxy_pass http://$prerender;
    }
    if ($prerender = 0) {

      rewrite .* /index.html break;
    }
  }
}
2

If you want to receive HTTP redirection with such URIs, try this:

server {
    ...
    server_name www.example.com example.com;
    ...
    location ~ ^/users/([^/]+)(.*)$ {
        return 301 $scheme://$1.example.com$2;
    }
    ...
}

But it is unclear with your question, do you need to serve this subdomains too with nginx config? This can be done with an additional server block:

map $name $uri_prefix {
    ~(.+)$ /users/$1;
}

server {
    ...
    server_name ~^(?<name>[^\.]+)\.example\.com$;
    ...
    rewrite ^(.*)$ $uri_prefix$1; # do an internal URI rewriting not visible to the end user
    ...
    # process a rewrited request (now in the form "/users/username/...")
}

Do not try to combine these two server block in one, or you'll receive an infitite loop.

  • Yes i am trying to serve the subdomains too within the nginx config – Mansoor Elahi Dec 21 '18 at 2:16
  • Note that you'll need a wildcard DNS entry pointing to your server for this. – Ivan Shatsky Dec 21 '18 at 2:19
  • Yes i added a wildcard dns entry like *.example.com to allow it created a new server block but looks like the its not being called i will paste my full nginx config in the question – Mansoor Elahi Dec 21 '18 at 2:36
  • 1
    Completely incorrect. 1) Where is location ~ ^/users/([^/]+)(.*)$ { ... } block within server block for main domain? 2) Within server block for virtual domains 2a) replace rewrite .* /$scheme://$host$request_uri? break; with rewrite .* /$scheme://staging.example.com$uri_prefix$request_uri? break; 2b) return back rewrite to /index.html when $prerender = 0 (as done in main server block). 3) Are your SSL certificate and key support wildcard domains? – Ivan Shatsky Dec 21 '18 at 4:03
  • Redirect from HTTP to HTTPS also need corrections, but lets make this config work normally with HTTPS first. – Ivan Shatsky Dec 21 '18 at 4:05
0

You can try with the following rule:

if ($request_uri ~* "^/users/(.*)/(.*)"){ return 301 hhttps://$1.example.com/$2; ; }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.