Why url rewriting not working? - php

I want to change my url from
http://localhost/delhian/destinations_list.php?ref=monuments_in_delhi
to
http://localhost/delhian/destinations_list/monuments_in_delhi
I have written the following htaccess rules.
RewriteEngine on
RewriteRule ^destinations_list/([A-Za-z_]+)/?$ destinations_list.php?ref=$1
I don't know what I'm doing wrong here but this isn't working.
When I'm accessing the URL
http://localhost/delhian/destinations_list/monuments_in_delhi
It is showing me Undefined index ref.
Can anyone tell me what I'm missing here, why it is not working and what is the meaning of this message Undefined index ref?

Add that, at the top of your htaccess, to disable MultiViews:
Options -MultiViews
The Apache docs on mod_negotiation, describes what the Multiviews Option does, when enabled:
If the
server receives a request for /some/dir/foo and /some/dir/foo does not
exist, then the server reads the directory looking for all files named
foo.*, and effectively fakes up a type map which names all those
files, assigning them the same media types and content-encodings it
would have if the client had asked for one of them by name. It then
chooses the best match to the client's requirements, and returns that
document.

Related

How I can redirect when request to download a file in Apache http server

I want to redirect to another url when request come to apache http for download a file
for example, client call https://example.com/download/apps/v1.01.apk
/download/apps/v1.01.apk is a real path
I want when call url apache prevent to download it and redirect to another url
For this, you will need to use a .htaccess file.
Create a .htaccess file, in the root of your project and type this into the file:
RewriteEngine on
Options -Indexes -Multiviews
RewriteRule ^(v1\.01\.apk)$ your-new-url.php
It's worth keeping in mind that when the web server first receives a request, the URL is just a string, and the server has to decide what to do.
One of the things it can do is look for a file on disk whose name matches the URL. If it finds a file, it can decide what to do with that information, perhaps combined with other information the browser sent in the request, or information it finds about the file.
Eventually, the server will come up with a response - maybe a response with the content of the file it found; maybe the result of running a particular script; maybe a response indicating a redirect to a different URL.
With most web server software, you can configure all of these decisions, in very flexible ways. So you can say "if the URL has a v in it, look for a file in this folder; if it exists, run this PHP script with the file name as an argument; if it doesn't, issue a redirect response to a URL where the v is replaced with an x".
For Apache, you will see a lot of advice to use .htaccess files to do this. These are not the primary configuration for Apache, but they are a convenient place to put extra configuration when you are using a shared server and can't edit the main configuration for security reasons.
The specific configuration line used to trigger a redirect response in Apache looks like this:
RewriteRule pattern-to-match-against-request url-to-redirect-to [R]
The first argument is a "regular expression" which can be as general or specific as you want. Note that . means "any character", so if you want to match a dot specifically, write \.
The second argument can contain variables like $1 and $2 which refer to parts of the requested URL "captured" by putting them in brackets in the pattern.
The [R] at the end can also have a type, like [R=temp] or [R=307], which will change how the browser handles the redirect, caches it, and so on. There are also other flags your can add, like [R,NC] for "Redirect, Not Case-sensitive".
Finally, you can add any number of RewriteCond lines before a rule, such as RewriteCond -f %{REQUEST_URI} meaning "if a file exists with the same name as the requested URL.

File being matched first instead of .htaccess rule

Whenever I have a file in my webserver and rewrite rule for the same path in my .htaccess, the rule is ignored and the file is automatically served.
I have only one file in the public_html of my webserver - test.php as follows:
<?php
echo "hello ".$_GET['action']
?>
Initially my .htaccess is empty and so visiting http://<domain-name>/test.php?action=world echoes hello world as expected. Also my webhost is so configured that visiting /test?action=world (with empty .htaccess) also echoes hello world.
Now I add the following .htaccess in public_html:
RewriteEngine On
RewriteRule ^test/(\w+)$ test.php?action=$1 [NC,L]
I expect that visiting /test/world will echo hello world, but that does not happen! I get only hello in the response. Now my initially thought is that mod_rewrite is not enabled, so to test that I change the .htaccess to:
RewriteEngine On
RewriteRule ^testmod/(\w+)$ test.php?action=$1 [NC,L]
Now to my surprise visiting /testmod/world actually echoes hello world! This shows that mod_rewrite is indeed available, and confirms that the rewrite rule is ignored when a file actually exists for the requested url.
My mental model is that Apache goes through the rules in the .htaccess, and for any rewrite rule matching the requested rule, Apache internally redirects to path specified in the rule. But that does happen here. It looks like first it checks if there exists any file for the requested url, and if not present, then look at the rewrite rules. Or something entirely else is happening here, maybe because of my webhost's configuration? (FYI, I'm using Bluehost as my webhost).
Add this to disable MultiViews:
Options -MultiViews
The Apache docs on mod_negotiation, describes what the Multiviews Option does, when enabled:
If the
server receives a request for /some/dir/foo and /some/dir/foo does not
exist, then the server reads the directory looking for all files named
foo.*, and effectively fakes up a type map which names all those
files, assigning them the same media types and content-encodings it
would have if the client had asked for one of them by name. It then
chooses the best match to the client's requirements, and returns that
document.
Use:
Options -MultiViews
RewriteEngine On
RewriteRule ^test/(\w+)$ test.php?action=$1 [NC,L]

Treating index and index.php as the same file

I'm working on a PHP project using Apache 2.2.22 and PHP 5.3.10 and I'm running into an issue where index and index.php are being treated as the same file.
I have an admin/index.php that redirects to admin/index to allow my mod_rewrite rules in .htaccess to take over and reroute the request into a custom framework. The problem is, when the browser goes to admin/index it goes into an infinite redirect loop because the request is being sent to admin/index.php which redirects to admin/index
I've tried removing the htaccess file to see if there was a problem with my mod_rewrite rules that was causing it and it didn't change anything. It just redirects to admin/index endlessly.
I've never heard of this behavior before, skimming over some Google results and skimming through the apache configuration files didn't show anything really obvious. Has anyone seen this before and know how to fix it?
EDIT:
Below is the code being used by the index.php to redirect to index.
<?php
header("Location: index");
die();
This may be due to MultiViews being enabled:
The effect of MultiViews is as follows: if the server receives a
request for /some/dir/foo, if /some/dir has MultiViews enabled, and
/some/dir/foo does not exist, then the server reads the directory
looking for files named foo.*, and effectively fakes up a type map
which names all those files, assigning them the same media types and
content-encodings it would have if the client had asked for one of
them by name. It then chooses the best match to the client's
requirements.
— https://httpd.apache.org/docs/2.2/content-negotiation.html#multiviews
Try adding Options -MultiViews to your .htaccess
Enable rewrite Logging inside Apache and raise the log level. That way apache will tell you exactly, step by step, what request is rewritten how, in which order and why.

php Apache server url rewrite issue

The problem is the following:
There is one server that I deploy to and for some reason the server does not respond to urls as usual. What I mean is when I have a file called somefile.php uploaded to mysite.com/ and I type in browser mysite.com/somefile the file somefile.php gets called instead of saying 404 not found. I think that this is weird and for some reason it prevents my .htaccess file to rewrite correctly, because the file somefile.php gets called and if there is information after mysite.com/somefile like mysite.com/somefile/someotherfile, someotherfile gets ignored and somefile.php gets displayed. I have all other .htaccess files deleted even in parent directories of the server and still the same result. I hope that you can hep me.
On localhost this problem is not observed. I get 404 not found as I should...
Sounds like you have MultiViews currently enabled. Try disabling them.
Multiviews
MultiViews is a per-directory option, meaning it can be set
with an Options directive within a , or
section in httpd.conf, or (if AllowOverride is properly set) in
.htaccess files. Note that Options All does not set MultiViews; you
have to ask for it by name.
The effect of MultiViews is as follows: if the server receives a
request for /some/dir/foo, if /some/dir has MultiViews enabled, and
/some/dir/foo does not exist, then the server reads the directory
looking for files named foo.*, and effectively fakes up a type map
which names all those files, assigning them the same media types and
content-encodings it would have if the client had asked for one of
them by name. It then chooses the best match to the client's
requirements.
http://httpd.apache.org/docs/2.2/content-negotiation.html#multiviews

mod_rewrite for dynamically mapping SEO friendly links directly to individual files, without routing via front controller

I'm looking for an SEO friendly url rewrite rule that would work for any common PHP site that doesn't have a front controller. It would map the SEO friendly url directly to the PHP file that is found to exist on the server and convert the remaining URL branches to standard URL parameters.
For example:
/folder1/folder2/folder3/page/var1/val1/var2/val2/var3/val3
would map to:
/folder1/folder2/folder3/page.php?var1=val1&var2=val2&var3=val3
Now, here's the tricky part. Since the rewrite rules need to be completely agnostic to all the names of folders, pages, and variables, it would need to base the rewrite of the URL parameters on the exact location along link where can be found a file that exists along the path. For instance, consider if the following file happened to exist (hypothetically) off the document root: /folder1/folder2.php
In this case, the following remapping would be legitimate and acceptable:
/folder1/folder2.php?folder3=page&var1=val1&var2=val2&var3=val3
This would be the ultimate rewrite rule for many traditional websites that have already been built that want their URLs and parameters to instantly become URL-friendly.
The only examples that I have found involve mapping everything to work with a single front controller or otherwise hard-coded files in the rule that are expected to exist rather than have mod_rewrite detect their existence dynamically. They're related, but not flexible for any file that is found to exist:
http://www.sitepoint.com/forums/showthread.php?t=363420
apache mod_rewrite one rule for any number of possibilities
Recursive mod_rewrite for search engine friendly urls
The Apache web server does already know such a concept:
MultiViews:
The effect of MultiViews is as follows: if the server receives a request for /some/dir/foo, if /some/dir has MultiViews enabled, and /some/dir/foo does not exist, then the server reads the directory looking for files named foo.*, and effectively fakes up a type map which names all those files, assigning them the same media types and content-encodings it would have if the client had asked for one of them by name. It then chooses the best match to the client's requirements.
Path Info:
This directive controls whether requests that contain trailing pathname information that follows an actual filename (or non-existent file in an existing directory) will be accepted or rejected. The trailing pathname information can be made available to scripts in the PATH_INFO environment variable.
For example, assume the location /test/ points to a directory that contains only the single file here.html. Then requests for /test/here.html/more and /test/nothere.html/more both collect /more as PATH_INFO.
All you then need to adjust is to take the path info part and parse it.
Besides that, if you really want to implement that behavior with mod_rewrite, try this:
RewriteCond %{DOCUMENT_ROOT}/$0.php !-f
RewriteRule ^(.+)/([^/]+)/([^/]+)$ /$1?$2=$3 [N,QSA]
RewriteCond %{DOCUMENT_ROOT}/$0.php -f
RewriteRule .+ /$0.php [L]

Categories