Apache mod_rewrite not mapping expression to parameter - php

I have a site which uses apache mod_rewrite and has been working for the last 6 months with no error.
I have the following rewrite rule:
RewriteRule ^products/([a-z\-]+)/$ /products.php?category=$1 [NC,L]
Here is the code in my page products.php
$category = $_GET['category'];
if (isset($category)) {
// do some processing here
}
else {
header("Location: /500.html");
exit;
}
An example of a link which hits this rule is /products/lighting-poles/
Does anyone know why the actual rewrite is still occurring but not mapping the ([a-z\-]+) to category=$1?
Extra info
I noticed that the .htaccess file on the host has commented out the line Options +FollowSymLinks so I first tried to re-enable this only to have the site return an apache white screen 500 error.
More from the .htaccess file
<IfModule mod_rewrite.c>
#Options +FollowSymLinks
RewriteEngine On
RewriteBase /
# Add a trailing slash to paths without an extension
RewriteCond %{REQUEST_METHOD} !POST
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule ^(.*)$ $1/ [L,R=301]
# other rules including problem rule here
</IfModule>

This sounds morbidly like a multiviews issue. Multiviews is a content-negotiation thing where if it's turned on, it'll try a few different extra things in the URL-file mapping pipeline to try to find a file that maps to a URL. Here you have a URL like /products/blah, yet, you have a file called products.php, so multiviews might try to map products to /products.php/blah. Thus bypassing the rewrite rule entirely, and you don't see the category parameter.
Where the options are, try adding:
Options -Multiviews

Related

PHP URL Rewrite - No getting Query String Parameter

I am working on a site and learning PHP at the same time so it is relatively new to me. I am working on URL rewrite currently, however, I am not getting the desired result.
I am trying to change: example.com/CMS/listing?id=1 into example.com/CMS/listing/1.
Using the .htaccess file held in the root of the files, I have the following:
RewriteEngine On
RewriteBase /
RewriteRule CMS/listing/([0-9]+) CMS/listing.php?id=$1
And on the site, I have a simple echo function which gets the query string param for id. When I navigate to example.com/CMS/listing?id=1 the function displays 1, however, when I go to example.com/CMS/listing/1 it does not show anything. Is there something I'm missing or doing wrong?
# Get QString Param
$id = $_GET["id"];
echo $id;
Footnote
.htaccess is held at the root, and listing.php is within a folder called CMS.
It looks like you have a conflict with MultiViews. You should disable MultiViews at the top of your .htaccess file:
Options -MultiViews
If MultiViews is enabled then when you request /CMS/listing/1, mod_negotiation will map the request to /CMS/listing.php (appending the file extension, without any URL parameter) before your mod_rewrite directive is able to process the request. (/1 is seen as additional pathname information or PATH_INFO on the URL.)
A URL like /CMS/listing?id=1 (without the file extension) will only work if MultiViews is enabled. In this case, the query string is already present on the URL.
You could also redirect all traffic through to index.php and handle it all in PHP. That is how other CMS' and framework usually do it.
This is the Laravel approach - you don't have to do it this way, but later on when you want to do custom urls on news post or any other this, you have to setup new rules. This way you can just add them to the database and create some kind off route handler. If you want to keeps it simple you could then just create a table in the database where you store urls and a field for the file to be called.
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>

how to modify .htaccess file to give QUERY_STRING?

I have the below htaccess file in my website and it was working perfectly for last two years. Recently i migrated the server to a new hosting partner and seems it not working as expected. I have confirmed that the server is supporting mod_rewrite module. And i could see the [QUERY_STRING] => is null what ever URL i specify, and all the URLs are routing to the home page. Can any one tell what i need to modify. i saw a lot many answers in stackoverflow and nothing worked for me. I am just a begginer in this htaccess file.
Options +FollowSymLinks
RewriteEngine On
Options -Indexes
# REWRITING index.php AS index #
RewriteRule ^index/?$ index.php [NC]
# Route The Pages #
RewriteRule ^index/([{a-z}]+)/?$ index.php?$1 [NC,L]
RewriteRule ^index/home/([0-9]+)/?$ index.php?home&p_id=$1 [NC,L]
RewriteRule ^index/page/([{a-z}{\-\}{0-9}]+)/?$ index.php?page&show=$1 [NC,L]
RewriteRule ^index/gallery/([{image}{video}]+)/?$ index.php?gallery&type=$1 [NC,L]
RewriteRule ^index/gallery/([{image}{video}]+)/([0-9]+)/?$ index.php?gallery&type=$1&album=$2 [NC,L]
If you are matching video or image then there is no reason to have {video} as { and }will match literally{video}`.
Have your .htaccess this way:
Options +FollowSymLinks -Indexes -MultiViews
RewriteEngine On
# REWRITING index.php AS index #
RewriteRule ^index/?$ index.php [NC,L]
# Route The Pages #
RewriteRule ^index/([a-z]+)/?$ index.php?$1 [NC,L,QSA]
RewriteRule ^index/home/([0-9]+)/?$ index.php?home&p_id=$1 [NC,L,QSA]
RewriteRule ^index/page/([a-z0-9-]+)/?$ index.php?page&show=$1 [NC,L,QSA]
RewriteRule ^index/gallery/(image|video)/?$ index.php?gallery&type=$1 [NC,L,QSA]
RewriteRule ^index/gallery/(image|video)/([0-9]+)/?$ index.php?gallery&type=$1&album=$2 [NC,L,QSA]
Options +FollowSymLinks
RewriteEngine On
Options -Indexes
The empty query string is consistent with MultiViews being enabled (perhaps as a result of a server update). Try disabling MultiViews at the top of your .htaccess file:
Options +FollowSymLinks -Indexes -MultiViews
RewriteEngine On
If MultiViews is enabled then a request for /index/<something> would result in an internal subrequest to /index.php/<something> and none of your remaining directives will match.
However, you do still need to update your regex to something like what anubhava suggests, since your current regex is probably matching a lot more than you intend. But your current patterns are ambiguous. For example, what should [{a-z}{\-\}{0-9}]+ match? It looks like you perhaps intended it to be a <letter>-<digit>? However, it currently matches any combination of letters, digits and hyphens (which is how anubhava has interpreted it)?

How can I get mod_rewrite to rewrite everything?

What I've been trying to achieve is to get my .htaccess file to rewrite ALL URLS.
No matter what I do, however, I cannot get it ignore existing directories. And by that, I mean, act as if they don't exist.
For example, say I have the following file structure:
/
dir1
file1.php
dir2
file2.php
.htaccess
And suppose I want to redirect all traffic to dir1/file1.php?url=path.
This never works for me if the path is an existing directory.
For example, if I navigate to url/path/stuff/dir2, the "redirecting" works, but the URL in the address bar changes to url/path/stuff/dir2/?url=dir2 for some unfathomable reason.
Here is my .htaccess:
Options -MultiViews
Options -Indexes
Options +FollowSymLinks
# so navigating to a url with a trailing slash won't cause problems
DirectorySlash Off
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dir1/file1.php?url=$1 [QSA,L]
You (updated) .htaccess is saying: IF (it is not an existing file) THEN { rewrite the URL }. Seems like you want
RewriteEngine on
RewriteCond %{REQUEST_URI} !dir1/file1.php
RewriteRule ^(.*)$ dir1/file1.php?url=$1 [QSA,L]
In this case, the RewriteCond just prevents infinite looping. The RewriteRule gets applied once and only once. Rewrite module will keep cycling thru all the rules until a cycle does not result in a changed to the URI.

Htaccess, Directory-Style not rewriting to query-style

I have a very basic htaccess, attempting to convert directory-style to query style.
i.e.
a. /public_html/main/folder1/folder2 ... etc
b. /public_html/main.php?1=folder1&1=folder2
No matter what regex I try, to matter what rewrite rule I try - I can't make any progress on this problem.
I've searched the web, many times so far. I've tried 10 different 'recommended' solutions found in other forums.
I don't know where else to look.
Here's my current htaccess:
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^public_html/([A-Za-z0-9]+)/([0-9]+)/?$ main.php?name=$1&page=$2 [NC]
Here's my httpd.conf Htaccess directives.
(Directory "/Users/admin/Sites")
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
Allow from all
(/Directory)
(Directory "/Users/admin/Sites/MFCS/V3/public_html/mfcs/public_html")
AllowOverride All
(/Directory)
I replaced the greater than / less than on the directory tags for this example.
the httpd.conf does have the proper tags in it.
Give this a try:
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^/main/(.*)/(.*)/?$ /main.php?name=$1&page=$2 [L]
This will redirect requests to:
http://www.example.com/main/folder1/folder2
To:
http://www.example.com/main.php?name=folder1&page=folder2
If this is not the outcome your looking for please provide a sample before and after. On another note did you make sure to enable mod_rewrite? I also removed the public_html from the URI because it's normally not visible to the public.

Php: My framework disables direct file access, but I need to avoid this, how?

.htaccess looks like this:
Options +FollowSymLinks +ExecCGI
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !(\.png|\.jpg|\.gif|\.jpeg|\.bmp|\.ico)$
RewriteRule ^(.*)$ entryPoint.php [QSA]
</IfModule>
this enforces all request running though entryPoint.php. This processes all files, redirects, etc. Images are free to go, there can be direct references to them. But what about CSS, JS files? I cant add exceptions - because it would reveal the directory structure. All I want is:
script src="ds.jss" while they can be at "js/" or "module/x/js/". Same with CSS.
I understand I can do it with entryPoint.php: file_get_contents and outputs. It does work, but its too slow. First we tried it with pictures too.
How to enable a "direct access"?
Options +FollowSymLinks +ExecCGI
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ entryPoint.php [QSA]
</IfModule>
Try adding these rewrite conditions...
If you don't want to do that within the php file, you need to add a rule:
Options +FollowSymLinks +ExecCGI
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^ds\.jss$ module/x/ds.jss [L]
RewriteCond %{REQUEST_URI} !(\.png|\.jpg|\.gif|\.jpeg|\.bmp|\.ico)$
RewriteRule ^(.*)$ entryPoint.php [QSA]
</IfModule>
The important part is the L flag which stands for Last Docs. It will prevent the other rules to run.
If you want to resolve the filename dynamically but you don't want to use PHP to provide the actual file but your apache server, you can still use PHP to resolve the filename by creating a dynamic rewrite map Docs, search for External Rewriting Program.

Categories