.htaccess - rewrite anything else to index.php - apache

I have app and public folders in my project. I want paths that starts with (css|im|js|lib)/ to be redirected to public folder, and anything else - to index.php file.
For example, http://mysite.com/css/s.css should be redirected to SITE_ROOT/public/css/s.css and http://mysite.com/absde should be redirected to SITE_ROOT/index.php
Here's working config for nginx:
server {
listen 80;
server_name mysite.com;
root /home/mysite/html;
location ~ \/(css|im|js|lib)\/ {
root /home/mysite/html/public;
expires 30;
try_files $uri =404;
}
location {
rewrite ^(.*)$ /index.php break;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
Now I try to rewrite this for apache, I write something like that in .htaccess:
RewriteEngine On
RewriteRule ^(css|im|js|lib)\/(.*)$ public/$1/$2 [L]
RewriteRule . index.php [L]
This does not work. It seems RewriteRule . index.php applies before the second line so that everything goes to index.php. But why?
Nothing changes if I change the third row to
RewriteRule ^(.*)$ index.php [L]
And that means that the type of equation doesn't affect on the order of rules.
And only if I remove ^ symbol from the regex in the second line, site starts working as expected. But I don't want to remove it! Now http://mysite.com/abcde/css/s.css rewrites to css/s.css, and it shouldn't be that way. Also the second line starts working if I remove the third one (that means it's correct by itself).
That's so stupid simple but I can't find a mistake in theese three rows. Please help.

The problem is that internal redirects are treated as new requests, and so the rules are being evaluated again, where the first rule now won't match anymore, but the second one does, and so you'll always end up at index.php.
One way to avoid this would be to bind the last rule to the condition that it doesn't start with /public/:
RewriteCond %{REQUEST_URI} !^/public/.*
RewriteRule . index.php [L]

Related

How to convert rewrites from advanced .htaccess to nginx conf rules

Recently switched to nginx from Apache. This works under apache perfectly fine, but don't know how to add it for nginx. Have tried htaccess to nginx converters, but they get me redirect loop.
I have WordPress in root and custom code under subdirectory.
This is the working .htaccess file on Apache:
# rewrite engine on and setting up base
RewriteEngine On
RewriteBase /leffa/
# replace + with _
RewriteRule ^(.+?)\+(.+)$ $1-$2 [R=301,L,NE]
# external redirect from action URL to pretty one
RewriteCond %{THE_REQUEST} /index(?:\.php)?\?q=([^\s&]+)&(kuvauksesta)= [NC]
RewriteRule ^ %1/%2? [R=302,L,NE]
RewriteCond %{THE_REQUEST} /index(?:\.php)?\?q=([^\s&]+)\s [NC]
RewriteRule ^ %1? [R=302,L,NE]
# skip all files and directories from rewrite rules below
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# internal forward from pretty URL to actual URL (extra parameter)
RewriteRule ^([^/.]+)/([^/.]+)?$ index.php?q=$1&$2=1 [L,QSA]
# internal forward from pretty URL to actual URL
RewriteRule ^(.+)/?$ index.php?q=$1 [L,QSA]
This rewrites all the urls like http://www.rollemaa.org/leffa/index.php?q=the+boy to pretty ones like http://www.rollemaa.org/leffa/the-boy.
The situation is, I have main file set up like this:
server {
listen 80;
access_log /var/log/nginx/rollemaa.access.log;
error_log /var/log/nginx/rollemaa.error.log;
root /var/www/rollemaa.org/public_html;
index index.html index.htm index.php;
server_name rollemaa.org www.rollemaa.org;
include hhvm.conf;
include global/wordpress.conf;
# Ensure requests for pagespeed optimized resources go to the pagespeed
# handler and no extraneous headers get set.
location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" { add_header "" ""; }
location ~ "^/ngx_pagespeed_static/" { }
location ~ "^/ngx_pagespeed_beacon" { }
# Static File Caching
location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
}
#location /leffa/ {
#try_files $uri $uri/ /leffa/index.php?q=$args;
#rewrite ^/leffa/(.+?)\+(.+)$ /leffa/$1-$2 redirect;
#rewrite ^/leffa/(.*)$ /leffa/%1/%2? redirect;
#rewrite ^/leffa/(.*)$ /leffa/%1? redirect;
#if (-e $request_filename){
# rewrite ^/leffa/([^/.]+)/([^/.]+)?$ /leffa/index.php?q=$1&$2=1 break;
#}
#rewrite ^/leffa/(.+)/?$ /leffa/index.php?q=$1 break;
#}
}
As you can see, I have commented out the rewrite part, because it's not working.
Any nginx gurus out there who could help me with this? Much appreciated in advance!
You can use the following rewrite rule.
location /leffa/ {
index index.php index.html;
rewrite ^/leffa/([^/]*)/?$ /leffa/index.php?q=$1;
}
It will rewrite URLs like /leffa/the-boy/ and /leffa/the-boy to /leffa/index.php?q=the-boy. URLs with sub-subdirectories such as /leffa/the-boy/something-here will be ignored.
Note: + in the URL is not converted to a space (as it would be when directly accessing /leffa/index.php?q=the+boy). Accessing /leffa/the+boy/ will result in the query parameter q being "the+boy".
If you want to use spaces in the query string, you will have to use the %20 URL encoded format for spaces. /leffa/the%20boy and /leffa/the%20boy/ will result in the query parameter q being "the boy".

Nginx, rewrite multiple subfolders

I try to move my server from Apache towards a Nginx based setting. However, I get into problems getting a part of my htaccess Apache magic to work in Nginx.
The .htaccess code I would like to transfer is:
RewriteRule ^([a-zA-Z0-9_]+)/$ /index.php?page=$1 [L,QSA]
RewriteRule ^([a-zA-Z0-9_]+).html$ /index.php?page=$1 [L,QSA]
RewriteRule ^([a-zA-Z0-9_]+)/([0-9]+)/.*/([a-zA-Z0-9_]+)$ /index.php?page=$1&id=$2&sub=$3 [L,QSA]
RewriteRule ^([a-zA-Z0-9_]+)/([0-9]+)/.*$ /index.php?page=$1&id=$2 [L,QSA]
I used an online converter that gave me the following location block:
location / {
rewrite ^/([a-zA-Z0-9_]+)/$ /index.php?page=$1 break;
rewrite ^/([a-zA-Z0-9_]+).html$ /index.php?page=$1 break;
rewrite ^/([a-zA-Z0-9_]+)/([0-9]+)/.*/([a-zA-Z0-9_]+)$ /index.php?page=$1&id=$2&sub=$3 break;
rewrite ^/([a-zA-Z0-9_]+)/([0-9]+)/.*$ /index.php?page=$1&id=$2 break;
}
Sadly, I'm only able to get a single location rewrite to be working at a time (the one I put "last;" behind). I don't seem to be able to do this dynamic rewriting of a multiple subfolder URL into arguments for a single PHP script.
Any help on this? What is the Nginx way of doing such a rewrite? I tried using several location's for different subfolders but I would rather have a generic solution that work no-matter what url's are thrown at it.
Use a different location block for each rule:
location ~ ^/[a-zA-Z0-9_]+/$ {
rewrite ^/([a-zA-Z0-9_]+)/$ /index.php?page=$1 last;
}
location ~ ^/[a-zA-Z0-9_]+.html$ {
rewrite ^/([a-zA-Z0-9_]+).html$ /index.php?page=$1 last;
}
location ~ ^/[a-zA-Z0-9_]+/[0-9]+/.*/[a-zA-Z0-9_]+$ {
rewrite ^/([a-zA-Z0-9_]+)/([0-9]+)/.*/([a-zA-Z0-9_]+)$ /index.php?page=$1&id=$2&sub=$3 last;
}
location ~ ^/[a-zA-Z0-9_]+/[0-9]+/.*$ {
rewrite ^/([a-zA-Z0-9_]+)/([0-9]+)/.*$ /index.php?page=$1&id=$2 last;
}
location = /index.php {
# your proxy rules here...
}
The rewrite rules above use the last option, which is explained in the nginx docs:
last
stops processing the current set of ngx_http_rewrite_module
directives and starts a search for a new location matching the
changed URI;

Apache mod_rewrite to Nginx rewrite rules

My site is running on Nginx and I am trying to add a software in the sub-directory of the site that uses Apache's mod_rewrite rules. E.g. www.mydomain.com/mySubfolder
Here is the Apache .htaccess
#Options -Indexes
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/system.*
RewriteRule ^(.*)$ index.php?/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?/$1 [L]
</ifModule>
So far I managed to get the main page to work but when requesting the login page, it is causing a URL redirect loop. E.g. www.myDomain.com/login
With this:
location /mySubfolder {
if (!-e $request_filename) {
rewrite ^(.*)$ /mySubfolder/index.php?q=$1 last;
break;
}
}
I have been reading and trying to learn how to convert Apache to Nginx and even used the .htaccess to Nginx converter I found at http://winginx.com/htaccess but the tool doesn't seem to recognize the %{REQUEST_URI} ^/system.* part. Upon my research and study, I came up with:
location /mySubfolder {
if ($request_uri ~ "^/(system.*)$") {
rewrite ^/(.*)$ index.php?/$1 last;
}
if (!-e $request_filename) {
rewrite ^(.+)$ /mySubfolder/index.php?q=$1 last;
break;
}
}
I am a complete noob at this and was even wondering if I am even close to accomplish this conversion to work. Please help.
Thank you.
was even wondering if I am even close to accomplish this conversion to
work
You've basically taken the wrong approach to use in Nginx.
Although it is kind of natural to assume that the rewrite rules in Apache would be mapped to the rewrite in Nginx, they aren't. Instead they are mostly mapped to the location rules.
Your block for mySubfolder should look like:
location ^/mySubfolder {
try_files /mySubfolder/index.php?$args =404;
}
You aren't actually rewriting anything - you are just telling nginx that any requests that start with /MySubfolder should be served by the files listed in try_files. btw you have to tell Nginx to pass the query string through which is what the args is doing.
You can append the original URL (i think) though it may be easier just to use $_SERVER['REQUEST_URI'] inside your script.
I believe the rewrite rule you have to the same start URI is causing the /mySubFolder to keep matching.
In Nginx rewriting is only used when you want to make external URL paths be served by different internal urls, and normally the rewrite rule is not inside a location block.
For example I have a file server, that serves up images and other files. I have these rewrite rules in the server block:
rewrite ^/image/(\d+)/(\w+)/(.+)\.([^\.]*)$ /proxy/proxyImage.php?typeID=$1&mode=$2&imagePath=$3.$4&resizeAllowed=TRUE&type=image last;
rewrite ^/image/(\d+)/(.+)\.([^\.]*)$ /proxy/proxyImage.php?typeID=$1&imagePath=$2.$3&resizeAllowed=TRUE last;
rewrite ^/file/(\d+)/(.+)\.([^\.]*)$ /proxy/proxyFile.php?typeID=$1&imagePath=$2.$3&resizeAllowed=FALSE last;
to make the external URLs look nice. But then they are all served by the location block:
location ~* ^/proxy {
try_files $uri =404;
fastcgi_pass unix:/opt/local/var/run/php54/php-fpm-images.sock;
include /documents/projects/intahwebz/intahwebz/conf/fastcgi.conf;
}
The location block doesn't need to know about the URL rewrites because they are done before the location block is encountered.

Converting apache rewrite rules (.htaccess) to nginx

Background:
I want to setup Bugify on my Ubuntu Server running nginx. I followed the instructions, installed the dependencies and the installation was successful. Once I enter my licence key and click on "Install Bugify" it's redirecting to http://dev.mysite.com/login?new and the only thing I'm seeing is 404 Not Found.
I know that nginx isn't officially supported but according to the support forum it should be possible to run it.
Question:
There's a .htaccess file with rewrite rules in the webapp's public directory and I guess the problem causing the 404 error is that nginx isn't able to work with the .htaccess file, so I'll have to convert the rewrite rules to the nginx syntax.
I'm not really familiar with apache's rewrite rules so I'd need some help figuring this out.
The content of the .htaccess file is:
# Rewriting
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
I was using this tool to convert the rules but it's having some troubles with the - flags.
#ignored: "-" thing used or unknown variable in regex/rew
Thanks in advance!
Bugify uses the Zend Framework, so the rewrite rules for ZF should work for Bugify also. I have copied the suggested nginx config below from http://wiki.nginx.org/Zend_Framework
server {
listen 80;
server_name www.example.com;
root /var/www/www.example.com/myapplication;
index index.html index.htm index.php;
location / {
# This is cool because no php is touched for static content
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
fastcgi_pass unix:/usr/local/zend/tmp/php-fastcgi.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/www.example.com/myapplication$fastcgi_script_name;
include fastcgi_params;
}
}

mod_rewrite is ignoring rules in subdirectories

Wanted rewrite behaviour (internal rewrite!)
http://<subdomain>.domain.tld/<path> -> /<subdomain>/<path>
http://www.domain.tld/path/file.php -> /www/path/file.php
http://project.domain-tld/index.php -> /project/index.php
Folder structure:
/ root
.htaccess
/www www.domain.tld
index.php
/www
file.php
/foo
/bar
file.php
/project project.domain.tld
index.php
someRandomFiles
/somesubdomain somesubdomain.domain.tld
index.php
someRandomFiles
/anothersubdomain anothersubdomain.domain.tld
index.php
someRandomFiles
Full .htaccess
# Unicode
AddDefaultCharset utf-8
# Activate mod_rewrite
RewriteEngine on
RewriteBase /
# Subdomains
# Extract (required) subdomain (%1), and first path element (%3), discard port number if present (%2)
RewriteCond %{HTTP_HOST}<>%{REQUEST_URI} ^([^.]+)\.janbuschtoens\.de(:80)?<>/([^/]*) [NC]
# Rewrite only when subdomain not equal to first path element (prevents mod_rewrite recursion)
RewriteCond %1<>%3 !^(.*)<>\1$ [NC]
# Rewrite to /subdomain/path
RewriteRule ^(.*) /%1/$1 [L]
My .htaccess seems to work. You can live test it here:
http://test.janbuschtoens.de/
rewrites to /test/
http://www.janbuschtoens.de/
rewrites to /www/
But there is some strange behaviour in subdirectories. mod_rewrite seems to ignore the rule if the first directory in the requested path has the same name as the subdomain itself. For example:
http://www.domain.tld/foo/bar/file.php -> /www/foo/bar/file.php - Fine!
http://www.domain.tld/ -> /www/ - Fine!
http://www.domain.tld/www/ -> /www/ - Should be: /www/www/
http://www.domain.tld/www/www/ -> /www/www/ - Should be: /www/www/www/
For another live test:
http://test.janbuschtoens.de/ rewrites to /test/
http://test.janbuschtoens.de/test/ rewrites to /test/
It seems like the rule gets ignored.
This is the only good rule that I was able come up with, otherwise after initial rewriting (which is very easy) it goes into the loop (and that is the problem). For example: www.domain.com/www/123.png gets properly redirected into /www/www/123.png, but then goes to the next loop, where it get's redirected to /www/www/www/123.png and then again and again.
This rule ONLY gets invoked if FINAL filename DOES EXIST.
RewriteCond %{HTTP_HOST} ^(.+)\.domain\.com$
RewriteCond %{DOCUMENT_ROOT}/%1/$1 -f [OR]
RewriteCond %{DOCUMENT_ROOT}/%1/$1 -d
RewriteRule ^(.*)$ /%1/$1 [QSA,L]
For example: if you request www.domain.com/www/123.png, and file/folder WEBSITEROOT/www/www/123.png exist, then it will be rewritten, otherwise nothing.
The same here: if you request meow.domain.com/ .. but have no WEBSITEROOT/meow/ folder on your drive, it gets nowhere.
Please note, this still will not help much if you have subfolder with the same name as subdomain. For example: if you request www.domain.com it should be rewritten to WEBSITEROOT/www/ ... but if you also have WEBSITEROOT/www/www/ then (because of loop) it will be rewritten to WEBSITEROOT/www/www/ instead.
Unfortunately I have not found the way how to bypass it. If you wish -- you can try combining your rules with mine.