ModRewrite: RewriteRule fails - apache

i'm trying to redirect two requests but only one of them works:
RewriteEngine On
RewriteRule ^cat/([^/\.]+)?$ cat.php?id=$1 [L]
RewriteRule ^user/([^/\.]+)?$ user.php?id=$1 [L]
domain.com/cat/something -> works
domain.com/user/12345 - > don't work ($_GET is empty)
It's very strange because the first (identically) rule works perfectly.
Maybe it's just because the second rule can't handle digits or something?
Thanks!

Most likely you have options MultiViews turned on. Disable it by placing this line on top of .htaccess:
Options -MultiViews
Option MultiViews is used by Apache's content negotiation module that runs before mod_rewrite and and makes Apache server match extensions of files. So /file can be in URL but it will serve /file.php.

Related

htaccess doesn't work after moving from webhost to local Synology host

I have a hosted website where I use the following htaccess file for formatting of urls, These all work fine. The host uses Apache, but unfortunately doesn't show a version number. I think it's 2.4.
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
RewriteRule ^item/([0-9]+)/(.*) /item.php?item=$1&title=$2 [L]
RewriteRule ^category/(.*) /showitems.php?category=$1 [L]
RewriteRule ^search/(.*) /searching.php?options=$1 [L]
RewriteRule ^searching/(.*) /showitems.php?search=$1 [L]
RewriteRule ^update/(.*) /showitems.php?update=$1 [L]
AddType application/x-httpd-lsphp .html .htm .shtml
I copied the entire site to my local Synology Diskstation with Apache 2.4.
The rewrite urls for category, search and update work fine. However, the urls for 'searching' and 'item' return 404 errors. 'Searching' is a header redirect from within 'searching.php'
Item is an oddity in the sense that it uses 2 get params in the result url. In trial and error mode I changed it to:
RewriteRule ^item/(.*) /item.php?item=$1 [L]
Which doesn't work either, however
RewriteRule ^itemitem/(.*) /item.php?item=$1 [L]
Works fine, which really puzzles me. This last rewrite also doesn't work when I add the second parameter again.
What am I missing? Or is there a better way to approach these rewrites in the first place that I could try?
What CBroe has commented on your post is properly the correct answer.
To be more specific and explain why then if your Apache 2.x server has MultiViews enabled it will try to match things up for you like directory names, file names on your behalf to make the user-experience easier.
However, this can in many cases confuse your rewrite rules that are expecting very specific regular expressions.
In most cases you can get away with just disabling MultiViews.
You disable it by adding to your Options in your .htaccess file.
-MultiViews
Please note that if the AllowOverrive directory does not allow this then your need to change the Apache configuration file for that vhost/directory to include the -MultiViews option.
You can read more about MultiViews here:
http://httpd.apache.org/docs/current/content-negotiation.html
The other thing and perhaps more correct way is to build your rewrite rules better and take advantage of things like the "!-f" or "!-d" parameter to let your rules know that you don't want to include files or directories and so forth.
A side note by the way on MultiViews, even though it's very fancy and neato - If you are running a production site please know that MultiViews create a hole lot of unwanted disk I/O and can slow down the Apache servers performance quite a bit! So it's always good practice to disable MultiViews.

Using mod_write for cleanurls with Lets Encrypt

I have enabled Let's Encrypt on a server running Apache on Ubuntu 14.04 and used the auto option to re-direct all http requests to https. This is working fine.
However, I now want to use mod_rewrite to use cleanurls on my site - all I need to do is remove the .php extension from all filenames. (e.g. https://example.com/contact routes to https://example.com/contact.php)
I have tried adding the following rewrite rule to the .htaccess file:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php
This configuration works fine on my localhost setup (without SSL) but does not work on the instance running Lets Encrypt.
I have tested that the .htaccess is working by adding this rule which works as expected (redirecting all www requests to the root domain)
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
I suspect that there may be some conflict between the Lets Encrypt auto setup option and my mod_rewrite rule but I am stuck as to how to make them both work together.
Any help would be much appreciated.
Disable MultiViews in .htaccess:
Options -MultiViews
MultiViews (part of mod_negotiation) is likely resulting in a conflict. This does something very similar to what you are trying to achieve using mod_rewrite. With MultiViews enabled (possibly enabled in the server config, although the default is disabled), a request for /filename, will result in Apache looking for a file that matches (that would return the appropriate mime-type) by stepping through the files in that directory (essentially trying various extensions where the basename matches).
I have checked what REQUEST_FILENAME is returning - it is the path to the filename (e.g. [REQUEST_FILENAME] => /var/www/sitename/public_html/output.php)
Yeah, that's the problem. MultiViews has already "fixed" the URL (output to output.php) before mod_rewrite has been able to do its thing.

mod_rewrite all to index.php in one environment

I know there are a million of questions about this, but I've tried the solutions in other questions and haven't got it to work in my case. I'm trying to redirect everything to index.php:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
This works in my local environment, but in my staging environment it fails and I get a 404 error. I've checked that mod_rewrite is enabled with phpinfo(). I've tried changing a few things like using ^(.*)$ instead of ^ and using /index.php instead of index.php
What else could be the problem?
Figured it out. It was a problem with the configuration of apache. Whoever set it up for the site I'm working on did it like this in the site's .conf file:
<Directory "/data/path/to/directory">
Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
# and a bunch of rewrite rules...
</Directory>
The AllowOverride None prohibits the use of .htaccess. In our local and development environments, the directory structure is different, so this code doesn't even get applied. That's why the .htaccess was working.
To solve the problem I'll either have to change the line mentioned above to AllowOverride All or add another configuration for the website I'm working on like the one above that does what I wanted to do with .htaccess.
Problems like this shouldn't come up for anyone if their environments are configured appropriately, but if anyone does run into a similar situation, check the configuration of the site in apache!

RewriteRule with query string gets rewritten to /param/param/

I have this rewriterule:
RewriteRule ^gallery/([^/]+)/?$ /gallery.php?title=$1 [L]
However, when navigating to gallery/a/, the internal redirect is to :
gallery.php/a //(instead of: gallery.php?title=a)
What would cause this behavior?
Option MultiViews might be culprit here. Option MultiViews is used by Apache's content negotiation module that runs before mod_rewrite and and makes Apache server match extensions of files. So /file can be in URL but it will serve /file.php.
Turn it off by using this line at top of your .htaccess:
Options -MultiViews

Apache redirect simple url to the same named php file

I'd like to redirect some static pages to the same named php file.
This is the code I'm using:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^services$ services.php [L,QSA]
</IfModule>
I'm getting 404 error when I open the "/services" url. If I change it to
RewriteRule ^services-anything$ services.php [L,QSA]
I can open "/service-anyting" without any problem.
Does anybody have any idea?
Thanks
Instead of your rewrite rules you can just enable MultiViews option:
Options +MultiViews
Option MultiViews is used by Apache's content negotiation module that runs before mod_rewrite and and makes Apache server match extensions of files. So /file can be in URL but it will serve /file.php.