how do I hide file extension in PHP? - .htaccess

I tried many commands like the following
RewriteRule ^(.*?)/(.*?)/(.*?)$ $1.php?$2=$3 [L]
in .htaccess to hide the php extension from the URL but do not work, I have the following site.org/home.php and I want it to site.org/home, how can I do this? Is it possible to do it without modifying .htaccess file as well?
I tried this as well in the .htaccess file and doesn't work
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^(.*)$ $1.php
</IfModule>

You don't actually "hide" the extension using .htaccess (if that is what you are expecting). You must first remove the .php extension in your HTML source, in your internal links (Apache/.htaccess should not be used to do this). The extension is now "hidden" (but the links don't work).
You then use .htaccess to internally rewrite the extensionless URL back to the .php extension in order to make the URL "work".
For example:
RewriteEngine On
# Rewrite to append ".php" extension if the file exists
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.+) $1.php [L]
Given a request for /home, the above will internally rewrite the request to /home.php if home.php exists as a physical file in the document root.
Note that this rule does assume your URLs do not end in a slash. eg. It expects /home and not /home/. if you request /home/ then it will result in a 404, since /home/.php does not exist.
The preceding condition first checks that the requested URL + .php exists as a physical file before rewriting the request. This is necessary in order to prevent a rewrite loop (500 error).
If your URLs do not contain dots (that are otherwise used to delimit the file extension) then the above can be optimised by excluding dots in the matched URL-path. ie. Change the RewriteRule pattern from (.+) to ^([^.]+)$. This avoids your static resources (.css, .js, .jpg, etc.) being unnecessarily checked for the corresponding .php file.
If you are changing an existing URL structure that previously used the .php extension and these URLs have been indexed by search engines and/or linked to by third parties then you should also redirect requests that include .php in order to preserve SEO. This redirect should go before the above rewrite, immediately after the RewriteEngine directive:
# Redirect to remove ".php" extension
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.+)\.php$ /$1 [R=301,L]
The preceding condition that checks against the REDIRCT_STATUS environment variable ensures that only direct requests are stripped of the .php extension and not rewritten requests by the later rewrite (which would otherwise result in a redirect loop).
NB: Test with a 302 (temporary) redirect first to avoid potential caching issues.
RewriteRule ^(.*?)/(.*?)/(.*?)$ $1.php?$2=$3 [L]
This does considerably more than simply "removing" (or rather "appending") the .php extension.
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^(.*)$ $1.php
</IfModule>
This will result in a rewrite-loop, ie. a 500 Internal Server Error response as it will repeatedly append the .php extension again and again to the same request.
(The <IfModule> wrapper is not required.)

Related

Redirect all URLS to new URL EXCEPT for /backend/ with .htaccess

I want to redirect all incoming queries to a new domain, except for /backend
I have this in my .htaccess, everything works, except for the /backend. I tried a few combinations, it just doesnt work.
I fear /backend is a virtual address....
what can i do?
HERE IS THE CODE:
RewriteCond %{HTTP_HOST} ^example.de$ [OR]
RewriteCond %{HTTP_HOST} ^www.example.de$
RewriteCond %{REQUEST_URI} !^/backend/$
RewriteRule (.*)$ https://www.bing.de/ [R=302,L]
PLEASE HELP. Thank you. Patrick
I fear /backend is a virtual address....
In which case you most probably have other mod_rewrite directives that rewrite the request to a front-controller (such as index.php) - and that's the problem. Whilst your existing rule includes an exception for /backend/ (the originally requested URL), so the rule is skipped on the first pass by the rewrite engine, once the request is rewritten to the front-controller (eg. index.php) the rewrite engine begins a 2nd pass which results in the rule being successfully executed since the URL is now /index.php (or whatever your front-controller is) and not /backend/.
You either need to:
modify the other directives that rewrite the request to the front-controller, so as not to trigger a 2nd pass through the rewrite engine. (You've not included your complete .htaccess file, so I'll discount this approach for now.)
OR, make sure you only examine the originally requested URL and not the rewritten URL. (The REQUEST_URI server variable is modified as the request is rewritten.)
However, I would assume that your /backend/ page also links to static assets (such as images, CSS, JS)? In which case, you also need to make exceptions for any additional static assets that are used by the page, otherwise these will also be redirected. For the sake of this example, I will assume all you static assets are located in an /assets subdirectory.
Try the following instead, near the top of your root .htaccess file:
RewriteCond %{HTTP_HOST} ^(www\.)?example\.de [NC]
RewriteCond %{THE_REQUEST} !\s/backend/\s
RewriteRule !^assets/ https://www.bing.de/ [R=302,L]
Note that this rule must go before the rewrite to the front-controller.
The THE_REQUEST server variable contains the first line of the HTTP request headers and importantly, does not change as the request is rewritten. This contains a string of the form GET /backend/ HTTP/1.1 (containing the request method, URL and protocol).
If there are no external assets then change the RewriteRule pattern from !^assets/ to simply ^, to match everything.

htaccess directory management

im going to ask a really simple question. i dont want my link to show this when i run my page :
http://localhost/example/assets/gallery.php
what i want is :
http://localhost/example/assets/
so how to do it in .htaccess file ?
i would really appreciate it if you can help because im so confused after reading forums .
my htaccess is like this right now but you know it only helps to remove extension :
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
How to make assets/gallery.php -> assets/
In the assets folder make a .htaccess file
Paste in this code :
DirectoryIndex gallery.php
This code changes the Directory Index (like a index.php file) to the gallery.php file meaning gallery.php is now like the index.php file.
The DirectoryIndex method that #RyanTheGhost suggests in his answer should have worked for the specific example you posted (where you request a directory and are serving a file from within that directory). However, the mod_rewrite directives you currently have in the document root1 will conflict with any requests for directories2 (although the DirectoryIndex should take priority).
However, the DirectoryIndex method is not very practical if you have many such files. And if you are not requesting a directory then this method naturally won't work anyway.
You could instead rewrite the URL using mod_rewrite in your existing .htaccess file, before your current directives.
1 I'm assuming your .htaccess file is in the document root.
For example:
# Rewrite "/example/assets/" to "/example/assets/gallery.php"
RewriteRule ^example/assets/$ example/assets/gallery.php [L]
Or, to avoid repitition:
# Rewrite "/example/assets/" to "/example/assets/gallery.php"
RewriteRule ^example/assets/$ $0gallery.php [L]
Where the $0 backreference contains the entire URL-path that is matched by the RewriteRule pattern. ie. example/assets/ in this case. NB: There is no slash prefix on the RewriteRule pattern or the substitution string.
Note that since you are requesting a directory (ie. /example/assets/) you need to ensure there is no DirectoryIndex document in that directory (eg. index.html or index.php), otherwise this will be served (by mod_dir) instead, overriding your internal rewrite above.
2 Your current directives that append the .php extension are arguably incorrect:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
This rule appends the .php extension to any request that does not map to a physical file, even if the file with a .php extension does not exist either. This can result in the incorrect URL being reported back to the user in the 404 error document (depending on how this is implemented). For example, the default Apache 404 error document will report that /foo.php does not exist, when the user requested /foo.
This rule will also rewrite directories (since they are "not files") which will result in a 404 (as opposed to a 403 or directory listing, if enabled). Although a DirectoryIndex document will override this.
Additionally, the NC flag is superfluous and there is no need to backslash-escape the literal dot inside a character class.
You could instead check that the corresponding .php file exists before rewriting, instead of checking that the requested URL does not map to a file.
For example:
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^.]+)$ $1.php [L]
The request is now only rewritten when the corresponding .php file exists, which naturally avoids any conflicts with directories.

Redirect specific URL to another URL on another subdomain

I have 5 URLs on a subdomain website http://subdomain.example.com, and I want them to redirect to 5 other URLs on my main website, https://www.example.com/.
Important: URLs do NOT have the same structure!
Example:
http://subdomain.example.com/url1 should redirect to https://www.example.com/ipsum
http://subdomain.example.com/url2 should redirect to https://www.example.com/lorem
etc.
How can I handle that?
UPDATE:
There is a play folder (name of the subdomain) which contains the subdomain website files and a htdocs folder which contains the www website files.
Here is the .htaccess file in my play folder:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Since the subdomain has it's own .htaccess file, you don't need to specify the hostname as part of the redirect. And since you already have mod_rewrite directives in the subdomain's .htaccess file, you should also use mod_rewrite for these redirects (to avoid conflicts). Otherwise, you'll need to specify these redirects one-by-one.
Try the following at the top of your subdomain's /play/.htaccess file. Note that this needs to go before the existing directives in the file.
# Specific redirects
RewriteRule ^url1$ https://www.example.com/ipsum [R=302,L]
RewriteRule ^url2$ https://www.example.com/lorem [R=302,L]
The above would match a request for http://subdomain.example.com/url1 and redirect accordingly, etc.
Note that the RewriteRule pattern (regular expression) does not start with a slash when used in a per-directory (.htaccess) context.
Note that these are 302 (temporary) redirects. Change them to 301 (permanent) - if that is the intention - only once you have confirmed they are working OK (to avoid caching issues).
Try this...
Redirect 301 http://subdomain.example.com/url1 https://www.example.com/ipsum
Redirect 301 http://subdomain.example.com/url2 https://www.example.com/lorem

.htaccess redirect all subfolders to specific path

I have multiple sites (subdirectories). I want to redirect all URLs of the format /(*)/login to /other/login.
I have tried:
RewriteRule ^/(.*)/login /other/login
#and
^(.*)/login /other/login
I've also tried Redirect.
Additionally, I notice that some subfolders have their own .htaccess files also. Do I need to put the redirect rule in the subfolder's .htaccess file? There surely must be a more efficient way.
I notice some subfolder have their own .htaccess files also, do I need to put the redirect rule in the subfolder .htaccess files?
Any mod_rewrite directives in child .htaccess files will, by default, completely override the mod_rewrite directives in any parent .htaccess file, they are not inherited. However, you can change this behaviour. On Apache 2.2 this is quite limited as you would need to change the child .htaccess file anyway, so it would probably be easier to simply duplicate this directive in the child config. But on Apache 2.4.8+ you can do all this in the parent .htaccess file. For example:
RewriteEngine On
RewriteOptions InheritDownBefore
RewriteCond %{REQUEST_URI} !^/other
RewriteRule ^[^/]+/login$ /other/login [R=302,L]
The InheritDownBefore option results in the current mod_rewrite directives being applied before the mod_rewrite directives in any child configs.
The RewriteCond directive is required in order to prevent a redirect loop (if the /other subdirectory does not have its own .htaccess file containing mod_rewrite directives).
This is an external "redirect" (as stated in your question). The URL changes in the browser's address bar. You can possibly change this to an internal rewrite (as your current directive implies) by removing the R flag (although this may depend on your application).
If you simply want a "redirect" then you could probably use a mod_alias RedirectMatch directive instead of the above mod_rewrite directives. This runs separately to mod_rewrite, but note that any mod_rewrite directives (in child configs) are processed first. For example:
RedirectMatch 302 ^/(?!other)[^/]+/login$ /other/login
The RedirectMatch directive uses a regex, whereas Redirect (also mod_alias) uses simple prefix matching. So, you couldn't match this specific pattern using a simply Redirect.
The (?!other) part is a negative lookahead (zero-width assertion) that checks that the URL-path being matched does not start other - in order to avoid a redirect loop.
Note also that RewriteRule does not use the slash prefix on the URL-path, whereas, RedirectMatch does. And there is no need to capture the URL-path (ie. by enclosing the regex in parentheses) if this is not required.
I have try several variants (you can see marked lines, that doesn't works),
my .htaccess:
#AddType application/x-httpd-php .html .htm
RewriteEngine on
RewriteRule ^(.*)$ index.php?path=$1 [NC,L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule ^([^/]*)+^(.*)$ index.php?dir=$1&path=$2 [NC,L,QSA]
#RewriteRule ^(.*)$ index.php?path=$1 [NC,L,QSA]
#FallbackResource index.php
It works with all urls: /, /index, /index.html, /main/main.html.
Then echo var_dumps($_GET); gives:
array(1) { ["path"]=> string(10) "index.html" }
Now all requests goes into index.php.

Trying to stop urls such as mydomain.com/index.php/garbage-after-slash

I know very little about .htaccess files and mod-rewrite rules. Looking at my statcounter information today, I noticed that a visitor to my site entered a url as follows:
http://mywebsite.com/index.php/contact-us
Since there is no such folder or file on the website and no broken links on the site, I'm assuming this was a penetration attempt. What was displayed to the visitor was the output of the index.php file, but without benefit of the associated CSS layout.
I need to create a rewrite rule that will either remove the information after index.php (or any .php file), or perhaps more appropriately, insert a question mark (after the .php filename), so that any following garbage will be treated like a parameter (and will be gracefully ignored if no parameters are required).
Thank you for any assistance.
If you're only expecting real directories and real files that do exist, then you can add this to an .htaccess file. What it does is it takes a non-existent file or directory request and gives the user the index.php page with the original request as a query string. [QSA] appends any existing query string.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?$1 [PT,QSA]
I found a solution, using information provided by AbsoluteZero as well as other threads that popped up on the right side of the screen as the solution came closer.
Here's the code that worked for me...
Options -Multiviews -Indexes +FollowSymLinks
RewriteEngine On
RewriteBase /
DirectorySlash Off
# remove trailing slash
RewriteRule ^(.*)\/(\?.*)?$ $1$2 [R=301,L]
# translate PATH_INFO information into a parameter
RewriteRule ^(.*)\.php(\/)(.*) $1.php?$3 [R=301,L]
# rewrite /dir/file?query to /dir/file.php?query
RewriteRule ^([\w\/-]+)(\?.*)?$ $1.php$2 [L,T=application/x-httpd-php]
I got the removal of trailing slash from another post on StackOverflow. However, even after removing the trailing slash, the rewrite rule did not account for someone appending what looks to be valid information after the .php file
(For example: mysite.com/index.php/somethingelse)
My goal was to either remove the "/somethingelse", or render it harmless. The PATH_INFO rule locates a "/" after the .php file, and turns everything else from that point forward into a query string (which will usually be ignored by the PHP file).

Resources