0

I want to migrate an Apache setup to Nginx, but I can't get the rewrite rules working in Nginx. I had a look on the official nginx documentation, but still some trouble converting it. http://nginx.org/en/docs/http/converting_rewrite_rules.html

I've used http://winginx.com/en/htaccess to convert my rules, but this just works partly. The / part looks okay, the /library part as well, but the /public part doesn't work at all.

Apache part:



    ServerAdmin webmaster@localhost
    DocumentRoot /srv/www/Web
        
          Order allow,deny
          Allow from all
          RewriteEngine On
          RewriteRule  ^$    public/      [L]
          RewriteRule  (.*)  public/$1    [L]
        

        
          Order Deny,Allow
          Deny from all
        

        
          RewriteEngine On
          RewriteCond %{QUERY_STRING} ^pid=([0-9]*)$
          RewriteRule ^places(.*)$ index.php?url=places/view/%1 [PT,L]
          # Extract search query in /search?q={query}&l={location}
          RewriteCond %{QUERY_STRING} ^q=(.*)&l=(.*)$
          RewriteRule ^(.*)$ index.php?url=search/index/%1/%2 [PT,L]
          # Extract search query in /search?q={query}
          RewriteCond %{QUERY_STRING} ^q=(.*)$
          RewriteRule ^(.*)$ index.php?url=search/index/%1 [PT,L]
          RewriteCond %{REQUEST_FILENAME} !-f
          RewriteCond %{REQUEST_FILENAME} !-d
          # Rewrite all other URLs to index.php/URL
          RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
        

        
          Order deny,allow
          deny from all
        
    ErrorLog ${APACHE_LOG_DIR}/error.log

    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn
        
          AddHandler php5-fcgi .php
          Action php5-fcgi /php5-fcgi
          Alias /php5-fcgi /usr/lib/cgi-bin/php5-fcgi
          FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -socket /var/run/php5-fpm.sock -pass-header Authorization
        
    CustomLog ${APACHE_LOG_DIR}/access.log combined

Nginx config:


server {
  #listen   80; ## listen for ipv4; this line is default and implied
  root /srv/www/Web;
  index index.html index.php;
  server_name localhost;
  location / {
    rewrite ^/$ /public/ break;
    rewrite ^(.*)$ /public/$1 break;
  }

  location /library {
    deny all;
  }

  location /public {
    if ($query_string ~ "^pid=([0-9]*)$"){
      rewrite ^/places(.*)$ /index.php?url=places/view/%1 break;
    }
    if ($query_string ~ "^q=(.*)&l=(.*)$"){
      rewrite ^(.*)$ /index.php?url=search/index/%1/%2 break;
    }
    if ($query_string ~ "^q=(.*)$"){
      rewrite ^(.*)$ /index.php?url=search/index/%1 break;
    }
    if (!-e $request_filename){
      rewrite ^(.*)$ /index.php?url=$1 break;
    }
  }

  location ~ \.php$ {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
  }
}

I haven't written the original ruleset, so I've a hard time converting it. Would you mind giving me a hint how to do it easily or can you help me to convert it, please?

I really want to switch over to php5-fpm and nginx :)

Thanks

Shiyu Sekam
  • 13
  • 1
  • 5

1 Answers1

3

Try this block for the public location:

location /public {
    if ($args ~ "^pid=(?<placepid>[0-9]+)$") {
        rewrite ^/places /index.php?url=places/view/$placepid last;
    }
    if ($args ~ "^q=(?<getq>.+)&l=(?<getl>.+)$") {
        rewrite ^ /index.php?url=search/index/$getq/$getl last;
    }
    if ($args ~ "^q=(?<getq>.+)$") {
        rewrite ^ /index.php?url=search/index/$getq last;
    }
    if (!-e $request_filename) {
        rewrite ^(.*)$ /index.php?url=$1 last;
    }
}

In nginx, references to regex captures in query parts don't work the same way as in Apache. Here we use named captures ?<variablename> in the parts matching the query string $args. Then we use the variables in rewrite parts.

The configuration could be optimized further, as this version has unnecessary complexities (rewriting / to /public in the start).

Tero Kilkanen
  • 36,796
  • 3
  • 41
  • 63
  • Thanks, I've added it to my config, but using that I get an error when restarting Nginx. Restarting nginx: nginx: [emerg] the duplicate "pid" variable in /etc/nginx/sites-enabled/default:16 nginx: configuration file /etc/nginx/nginx.conf test failed Line 16 in my case is this one: if ($args ~ "^pid=(?[0-9]+)$") { – Shiyu Sekam Aug 19 '14 at 11:43
  • I forgot that `$pid` is a reserved variable name, I changed it to `$placepid`, so it should work now. – Tero Kilkanen Aug 19 '14 at 12:02
  • Oh,now it comes up with [emerg] unknown "url" variable – Shiyu Sekam Aug 19 '14 at 12:20
  • There was one more typo in my answer. I fixed it now. – Tero Kilkanen Aug 19 '14 at 17:35
  • That doesn't work for me ;). If I click a link on the homepage, it returns 404. The rewrite is supposed to make that work. Do you have another idea what could cause the problem? – Shiyu Sekam Aug 20 '14 at 07:11
  • Unfortunately I cannot do anything more without seeing the complete system, and this is not a proper place for that. I recommend that you study nginx documentation carefully, and also study the what are the exact requirements for your CMS, and then try to find a solution. – Tero Kilkanen Aug 20 '14 at 09:31
  • I see, thank you. Unfortunately that's a self-written framework by a guy who worked at my company, but left and is unreachable, so I'll just stick with Apache for now. At least I can try to migrate it to a solution which uses mod_event + php-fpm + php-apc. – Shiyu Sekam Aug 20 '14 at 13:12