📜 ⬆️ ⬇️

nginx, user subdomains and rewrite

In a wide variety of web projects, the challenge arises of organizing user subdomains on the fly. When using nginx the following construction comes to the rescue:
 server {
     listen 80;
     server_name example.com * .example.com;
     location / {
         root /var/www/example.com/$subdomain;
         index index.html index.php;
     }
     set $ subdomain "";
     if ($ host ~ * ^ ([a-z0-9 - \.] +) \. example.com $) {
         set $ subdomain $ 1;
     }
     if ($ host ~ * ^ www.example.com $) {
         set $ subdomain "";
     }
 }
By itself, it is not new and was already mentioned in Habré. Nevertheless, the question of organizing rewrite for user subdomains was not considered. Immediately I would like to draw your attention to the fact that the problem to be solved is to organize various rewrite for a small number of user subdomains. The main problem with applying rewrite rules for a particular subdomain is that we often have to use two if. The first is for the explicit assignment of a subdomain, the second is part of the rule itself. For example:
 if (! -e $ request_filename) {
   rewrite ^ (. +) $ /index.php?q=$1 last;
 }
Unfortunately, for the time being, nginx does not allow the use of nested if constructs or the AND operator in them. Thus, we will have to go for a little trick. We will create in the folder with nginx configs (in FreeBSD, this is / usr / local / etc / nginx, in Linux, I suspect, / etc / nginx) the checks.conf file as follows:
 set $ f "| f";
 set $ e "| e";
 set $ d "| d";

 if (! -f $ request_filename) {
     set $ check $ check $ f;
 }
 if (! -e $ request_filename) {
     set $ check $ check $ e;
 }
 if (! -d $ request_filename) {
     set $ check $ check $ d;
 }
 set $ check $ subdomain $ check;
What is he doing? in fact, it puts the name of the current subdomain into the $ check variable, appending flags at the end relative to our query (i.e. if -f is true, the “| f” is added, if -e is true, then | e ”, etc. ) Now let's organize the use of this file for subdomains. Add the following line to our configuration file:
 location / {
    root /var/www/example.com/$subdomain;
    index index.html index.php; 
  include example.com/*.conf; 
} Let's create an example.com directory in the nginx configs folder. It will store rewrite rules for each subdomain (one per file, the absence of a file means that rewrite is not needed for this subdomain) As an example, I’ll give the contents of a similar file for the docs subdomain on which DokuWiki is running:
 if ($ subdomain = "docs") {
     rewrite ^ (/) _ media /(.*) $ 1lib / exe / fetch.php? media = $ 2 last;
     rewrite ^ (/) _ detail /(.*) $ 1lib / exe / detail.php? media = $ 2 last;
     rewrite ^ (/) _ export /( (2/) +) / (.) $ 1doku.php? do = export_ $ 2 & id = $ 3 last;
 }

 include service / checks.conf;

 if ($ check ~ * ^ docs. * [f]. * $) {
     rewrite ^ (/) (. *)? (. *) $ 1doku.php? id = $ 2 & $ 3 last;
     rewrite ^ (/) $ $ 1doku.php last;
 }
The file itself consists of two parts. The first part (before include) consists of unconditional rewrite. We could put them into the user domain config itself, but keeping all the eggs in one basket is more convenient in our case. The second part (after include) is identical to what would have been written in the form of if (! -F .... ) . Obviously, if we needed to check the form -e, it would be enough to replace one character in our regexp. Unfortunately, this method does not solve another problem when using automatic user subdomains - namely, restricting access to certain folders of the site by basic authentication ( analogue .htaccess). This is due to the fact that the directive location in which the assignment of such rules is carried out is unacceptable inside the if.PS statement. This is my first article on Habré, if there are comments - I will gladly try to take them into account

')

Source: https://habr.com/ru/post/30149/


All Articles