Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
i am newbie of php
How to create simple remove .php extension with .htaccess page?
My aims is type this url http://site/Test
it can visit hello.php content, anyone know how to do that?? thx
I have one folder that call "Test", there are two file on "Test" Folder
Test/
-hello.php
-.htaccess
hello.php
<?php echo "Hello World"; ?>
.htaccess
RewriteEngine on
RewriteRule ^(.*)$ $1.php
finally, it is not successful
it display the following error message
**Internal Server Error**
The server encountered an internal error or misconfiguration and was unable to complete your request.
anyidea to solve this??? Thank you very much
My aims is type this url http://site/Test it can visit hello.php content, anyone know how to do that?
This isn't simply "file extension removal". If it was then /Test would serve the content from /Test.php. In your example, you are wanting to serve the contents of an entirely different file.
Rewriting the request with mod_rewrite
Since you are requesting a directory (/Test/) and wanting to serve a file from within that directory and the .htaccess file itself is actually located in that directory, you would need to write your RewriteRule like this:
RewriteRule ^$ hello.php [L]
In .htaccess (directory context), the RewriteRule pattern matches the URL-path relative to the location of the .htaccess file. So, in this case the URL-path we are matching against is simply an empty string, ie. ^$, since we are wanting to match /Test/<nothing>.
Likewise, when the susbtitution string (ie. hello.php) is relative (as it is here), it is relative to the location of the .htaccess file. So, in this case it effectively rewrites the request to /Test/hello.php (it's actually the absolute filesystem path, eg. /var/www/user/public_html/Test/hello.php - after the directory-prefix is added back).
Additional issues with this example
Since you are rewriting a request that would otherwise map to a physical directory there are a couple of potential issues you need to be aware of...
You should request the directory with a trailing slash, ie. /Test/, not /Test (as you stated in your initial example), otherwise mod_dir will issue a 301 redirect to append the slash before your rewrite is successful.
(There are ways to avoid the trailing slash, but this does increase the complexity and requires further manual rewrites.)
An additional complication occurs if there is a DirectoryIndex document in this subdirectory. eg. /Test/index.php. In this case mod_dir issues an internal subrequest to the DirectoryIndex document (eg. index.php) and this takes priority over your internal rewrite. (Your rewrite does still occur, but mod_dir "wins".) If this is the case then you can rewrite the DirectoryIndex document instead of an empty URL-path. For example:
RewriteRule ^index\.php$ hello.php [L]
This is perhaps counter-intuitive, as we are now rewriting the internal subrequest that mod_dir has issued in a later pass through the file.
You could handle both scenarios and make index.php optional. For example:
RewriteRule ^(index\.php)?$ hello.php [L]
RewriteRule ^(.*)$ $1.php
Your example would result in an internal rewrite loop (500 Internal Server Error response) since the pattern ^(.*)$ also matches the rewritten URL and it gets stuck in an endless loop. (The rewriting process doesn't just consist of a single pass through the file. The process repeats until the URL passes through unchanged.)
(Incidentally, this IS an extensionless URL type of rewrite, but it doesn't help you achieve what you stated in your example.)
There are various ways to prevent this "endless loop":
Use a more specific regex, that won't also match the rewritten URL. eg. a regex that excludes a dot such as ^([^.]+)$.
Use a RewriteCond (condition) directive that prevents the rule being triggered on the rewritten URL. eg. Exclude .php files or check that the request does not map to a file, etc.
Use the END flag on the RewriteRule to stop all further processing by the rewrite engine.
Alternative - change the DirectoryIndex
Instead of using mod_rewrite, as explained above, to internally rewrite the request, we could instead change the DirectoryIndex document.
This only works in this particular case where you are requesting a directory and wanting to serve a file from that directory (although strictly speaking the file could be anywhere).
The DirectoryIndex is the document that mod_dir will look for when requesting a directory (eg. /test/). By default, it looks for index.html (and often index.php) and possibly others. If a DirectoryIndex document is not found, you get a 403 Forbidden when requesting that directory (assuming auto-directory indexes are disabled).
For example, you could set the following:
DocumentIndex hello.php
And now when you request /Test/, mod_dir will serve hello.php in that directory.
However, this method (by itself) is limiting and potentially confusing for readers of your code (if changing the DirectoryIndex on a directory by directory basis). It is generally expected that the DirectoryIndex document(s) is consistent throughout your site.
Related
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]
I am new to htaccess files, and I understand how to do basic rewrites of URLs such as removing index.php, extensions, etc. I am also able to use $_SERVER["PATH_INFO"] to work with anything trailing the file.
What I struggle with is how it would be possible to do this with a trailing faux-directory structure on another file other than the (not-shown) index.php. Lets say I have
domain.com/render.php/this
and I want it to read
domain.com/render/this
My workaround is currently to do all my logic in my index.php file, but I would like to break it up into several files, so that I would have index.php doing my home-page stuff, and render.php something completely different.
Thank you for you time.
It depends on your overall directory structure. Take a look at Apache .htaccess to hide both .php and .html extentions, for example.
If you already have /render/this configured to go to /render.php/this, and all you have to do is perform redirection the other way, then try this:
RewriteEngine On
RewriteCond %{REQUEST_URI} \b\.php\b
RewriteRule ^([^/.])\.php/(.*)$ $1/$2 [R]
(The \b part matches at a word boundary, as per pcrepattern(3), which is from the pcre library that both Apache httpd as well as nginx use in support of regular expressions.)
I have clean path with the same name as existing directory.
I use these .htaccess rules to support clean path for the path:
RewriteCond ${REQUEST_URI} ^/mydir
RewriteCond ${REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
everything works correctly (I have a "mydir" clean path working and I can access existing files in the /mydir directory directly), but apache appends the trailing slash all the time to requests.
I request http://domain.com/mydir, and it redirects me 301 to http://domain.com/mydir/.
What is the reason?
Trailing slash after /mydir/ is added by an Apache module called mod_dir that adds a trailing slash after all the directories. This is due to this setting turned on by default:
DirectorySlash On
You can turn it off using:
DirectorySlash Off
However it might expose some directories by showing their listings.
Security Warning
Turning off the trailing slash redirect may result in an information
disclosure. Consider a situation where mod_autoindex is active
(Options +Indexes) and DirectoryIndex is set to a valid resource (say,
index.html) and there's no other special handler defined for that URL.
In this case a request with a trailing slash would show the index.html
file. But a request without trailing slash would list the directory
contents.
Apache's proper URL always ends in a slash /. Because it treats URL's as if they were a disk file path (which always ends in a slash). If it's not there, the server needs to take one additional step to internally add it. I say let it be.
Plus Google (supposedly) likes the trailing slashes.
I say keep it as is.
Please read more: http://cdivilly.wordpress.com/2014/03/11/why-trailing-slashes-on-uris-are-important/
and here: http://bit.ly/1uSvbfy :)
I'm trying to create nice urls with .htaccess files and have come across a weird issue.
I want to change portfolio.php?id=2 to /portfolio/2/
seems pretty simple solution
RewriteRule ^portfolio/([0-9]+)/$ /portfolio.php?id=$1 [L]
this does redirect to the correct script but when i try and run <?=$_GET['id'];?> it is undefined. but if change the script to something that does not equal the fake directory it works.
RewriteRule ^portfolio/([0-9]+)/$ /portfolioitem.php?id=$1 [L]
and just to make sure that it wasn't being caught by any other rules I tested this
RewriteRule ^portfolioitem/([0-9]+)/$ /portfolioitem.php?id=$1 [L]
and again it failed to pick up the id paramater!
any ideas?!
Cheers
This sounds suspiciously like a Multiviews related problem coupled with some PATH_INFO. The Multiviews option is part of mod_negotiation and it will try to match a requested URL path to a file path. It sees:
/portfolio/2/
And sees that there's a /portfolio.php file in the filesystem and assumes that this is what you want (which it is, but not in the same way). I'm willing to bet that instead of looking at $_GET['id'], which is blank of course since there are no GET params, if you look at $_SERVER['PATH_INFO'], you'll see it set to /2/. This is equivalent to going to:
/portfolio.php/2/
where the /2/ part gets passed to portfolio.php as part of the PATH_INFO. And since mod_negotiation is further up in the processing pipeline than mod_rewrite, your rewrite rules never get applied.
Try turning off multiviews. You can do this in your htaccess file using the Options directive (assuming your host has allowed Options):
Options -Multiviews
I've been tasked to clean up 30,000 or so url errors left behind from an old website as the result of a redesign and development.
I normally use .htaccess to do this, but I doubt it would be wise to have 30,000 301 redirects inside the .htaccess file!
What methods have some of you used to solve this problem?
Thanks in advance.
Here as you can do with apache httpd
RewriteMap escape int:escape
RewriteMap lowercase int:tolower
RewriteMap my_redir_map txt:map_rewrite.txt
RewriteCond ${my_redir_map:${lowercase:${escape:%{HTTP_HOST}%{REQUEST_URI}}}} ^(.+)$
RewriteRule .* http://%1 [R=301,L]
I use this rewrite rules usually directly inside apache httpd configuration.
Inside the map_rewrite.txt file you have a tab delimited file with the list of redirect in the following format:
www.example.it/tag/nozze www.example.it/categoria/matrimonio
www.example.it/tag/pippo www.example.it/pluto
www.example.it/tag/ancora www.google.com
Would be much easier if you can generalize the approach because the redirect have a common pattern. But if not, in this case you only need to add the redirected url into the list.
Take care to study the RewriteMap configuration, because you can also write the list into a different format, for example like a database table.
Please pay attention to this: I have added escape and lowercase only because there are accents into the urls I need to write. If your urls doesn't have accents, you can remove both.
If you want implement these redirects in php, here the code you need:
<?php
$dest_url = "http://example.com/path...";
header("HTTP/1.1 301 Moved Permanently");
header("Location: ".$dest_url);
Create a PHP page to operate as a 404 handler. It should inspect the incoming URL, check if it should map from an old page to a new page, then issue a 301. If there is no mapping then present a 404.
Simply set this page as the 404 handler in your .htaccess and there you go. IIRC this is how Wordpress used to handle 'clean' URLs on IIS before IIS7 brought in URL rewriting without needing a 3rd-party dll.
I have made a redirect class that is on the 404 page that will check the database if there is a valid page to 301 redirect to and redirect it instead of giving the 404 page. If it can't figure that out, it marks it in the database as a 404 page, so it can be fixed later.
Thanks for help guys. I've carried out the suggested course of action from freedev but have created a separate config file within Apache.
Within the httpd.conf file I have added:
# Map settings
Include "conf/extra/map.conf"
The map.conf file:
RewriteEngine On
RewriteEngine on
RewriteMap url_rewrite_map txt:conf/map.map
RewriteCond ${url_rewrite_map:$1|NOT_FOUND} !NOT_FOUND
RewriteRule ^(.*) http://website.com/${url_rewrite_map:$1} [R=301]
The map.map file is formatted as:
/oldname/ /newname
I've added quite a few of the urls for the redirection and so far so good, it isn't having a massive impact on the server like it did when added to .htaccess