Would it be possible to write a RewriteCond to accomplish this differently - .htaccess

I have this rewrite cond:
RewriteCond %{REQUEST_URI} !.*\.(css|js|php|html|png|jpg|gif)|notes|messages|/delete/|/achors_data/|/composer/|/pagination/|/mom_mp3/|/swf/|/js/|/stories/|/wall/|/news_feed/|/notifications/|opencv|hdflvplayer|hdflvplayer2|videojs|ffmpeg|mediaplayer|uploadify|/v/|/video/|/options/|show_msg_dialogs|facedetector|classes|right_column_modules|functions|maurice|pokes|opticrop|geoip_city|/autocomplete/|chrono|ajax|editprofile|tag|Svetlozar.NET
It has to be maintained with each new directory that is created on root as I have a rewrite rule that redirects everything from non existing directories (root/mydirectory/ and root/mydirectory_b/) to root/specialdirectory/ except what's on the condition which is just any existing directory in root which does not need to have the rule of going to specialdirectory applied.
My question is if it would be possible to write the rewritecond or take another approach to accomplish the same, not having to write manually each new directory in the .htaccess that is being created in root.
So this is the rewrite rule with the cond that makes everything (root/anydir/) go to
root/master
RewriteCond %{REQUEST_URI} !.*\.(css|js|php|html|png|jpg|gif)|notes|messages|/delete/|/search/|/buttons/|/achors_data/|/composer/|/pagination/|/mom_mp3/|/swf/|/js/|/stories/|/wall/|/news_feed/|/notifications/|opencv|hdflvplayer|hdflvplayer2|videojs|ffmpeg|mediaplayer|uploadify|/v/|/video/|/options/|show_msg_dialogs|facedetector|classes|right_column_modules|functions|maurice|pokes|opticrop|lists|geoip_city|/autocomplete/|chrono|ajax|editprofile|tag|Svetlozar.NET
RewriteRule ^([A-Za-z-0-9-_.]+)?$ master/$2
Then there is the problem in which the directory friends only outside all of the directories in root should perform a certain action anything/friends goes to anything/view_friends.php
What I would like is to be able to write a RewriteCond that takes in consideration every existing directory in root - a wildcard for that.
So I would end up writing something like the following with no maintenance
RewriteCond %{REQUEST_URI} ! * existing directories - except just one
instead of:
RewriteCond %{REQUEST_URI} !.*\.(css|js|php|html|png|jpg|gif)|pokes|opticrop|notes|/delete/|/search/|/buttons/|/achors_data/|/composer/|/pagination/|/mom_mp3/|/swf/|/js/|/stories/|/wall/|/news_feed/|/notifications/|opencv|hdflvplayer|hdflvplayer2|videojs|ffmpeg|mediaplayer|uploadify|/v/|/video/|/options/|show_msg_dialogs|facedetector|classes|right_column_modules|functions|maurice|lists|geoip_city|/autocomplete/|chrono|ajax|editprofile|tag|Svetlozar.NET
RewriteRule ^([A-Za-z-0-9-_.]+)/friends $1/view_friends.php
directories must exist as real directories for the rewritecond to apply as I use phantom directories for the first rewriterule.

I'm not following what you want exactly. Would easier if you could post the entire htaccess instead of just fragments. Also giving some sample urls would help.
But I'll just go tell you what I use.
RewriteCond %{DOCUMENT_ROOT}/$1 -d
RewriteRule ^([^/]+)(/(.*))?$ - [L]
This rule get the first past of the url, before the first /, and check if there is an existing directory (in the root) with that name. If so, it will stop processing any rewrite-rules below it (that's what the - [L] part does).

Related

How To check and remove if any subfolder exists in a Folder by Htaccess?

I have a file structure like this.
Folder
- .htaccess
- Subfolder
- Otherfolder
- file1.html
- file2.html
- filea.html
- fileb.html
I can have many folders at the place of 'otherfolder' and I don't want to add code for each subfolder of 'Subfolder'.
i want to remove all other subfolders names except folder.
I just want to get URL like - mywebsite.com/folder/file.html
Edit
currently I am using this code snippet in .htaccess
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^subfolder/([^.]+)\.html$ /folder/$1 [L,R]
RewriteCond %{REQUEST_URI} !/folder/subfolder/
RewriteCond %{REQUEST_URI} !\.(css|js|jpg|gif|png|jpeg)$
RewriteRule ^(.+)/?$ /folder/subfolder/$1.html [L]
I can have many folders at the place of 'otherfolder' and I don't want to add code for each subfolder of 'Subfolder'.
This isn't possible in .htaccess alone. The problem is not in removing the subfolder from the URL (although this should already have been done in the internal link), the problem is internally rewriting the request back to the appropriate subfolder. There is no built-in mechanism to "search" for arbitrary files in .htaccess.
If you have a limited number of known subfolders then you can do this, but you need to add a rule (in the root .htaccess file) for every subfolder. However, this is not particularly efficient since you need to manually test for the existence of that file in each subfolder. You also have a potential problem of name collision. Obviously, if you effectively "flatten" the filesystem the file file1.html can only exist once on the filesystem, amongst all subfolders. If there is more than one file1.html then the first match wins.
In principle, you would need to do something like the following to rewrite a request for /folder/<file>.html back to /folder/subfolder/otherfolderN/<file>.html.
# Test "subfolder/otherfolder1"
RewriteCond %{DOCUMENT_ROOT}/folder/subfolder/otherfolder1/$0 -f
RewriteRule ^[^/.]\.html$ subfolder/otherfolder1/$0 [L]
# Test "subfolder/otherfolder2"
RewriteCond %{DOCUMENT_ROOT}/folder/subfolder/otherfolder2/$0 -f
RewriteRule ^[^/.]\.html$ subfolder/otherfolder2/$0 [L]
# Test "subfolder/otherfolder3"
RewriteCond %{DOCUMENT_ROOT}/folder/subfolder/otherfolder3/$0 -f
RewriteRule ^[^/.]\.html$ subfolder/otherfolder3/$0 [L]
The parent /folder/ could be abstracted out of the RewriteCond TestString if you wish, but the subfolder and otherfolderN would need to be hardcoded. (Although subfolder could be manually assigned to an environment variable to save repetition.)
Aside:
RewriteCond %{REQUEST_URI} !/folder/subfolder/
RewriteCond %{REQUEST_URI} !\.(css|js|jpg|gif|png|jpeg)$
RewriteRule ^(.+)/?$ /folder/subfolder/$1.html [L]
A "problem" with this code is that it rewrites the request regardless of whether the target file exists or not. This is OK if you are rewriting all requests to a single subfolder, but if you have multiple subfolders then you must check for the target file's existence before rewriting.
This also rewrites the request even if it already maps to an existing file. So any legitimate files in the /folder/ directory (eg. filea.html and fileb.html in your file structure) would not be accessible.
This also rewrites every file type (except for the few file extensions listed in the preceding condition). It would, for instance rewrite a request for foo/bar/file.webp to /folder/subfolder/foo/bar/file.webp.html. If you are only wanting to rewrite .html files then include this in the RewriteRule pattern and the preceding condition is not required.

How to rewrite directory for multiple level directories

This is my .htaccess
RewriteEngine On
# browser requests PHP
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^\ ]+)\.php
RewriteRule ^/?(.*)\.php$ /$1 [L,R=301]
# check to see if the request is for a PHP file:
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^/?(.*)$ /$1.php
RewriteCond %{REQUEST_URI} !^/(views|css|js|media|partials|php)
RewriteRule (.*) /views/$1
This is my project structure:
The idea is that all my HTML files are structured in the folder views, but I don't want my URL to be http://example.com/views/index but just http://example.com/index without the views-part.
This is working fine in the following case:
http://example.com/account/
But fails as soon as I try to access a file in the accounts-folder e.g: http://example.com/account/voeg-kind-toe
That results in a 404. Seems like this .htaccess solution only works for one-level directories.
Edit:
Interesting: If I place the bottom two lines on top (so placing the code to rewrite the view-part before the code to remove the php-extension); the php-extension works but the /views//part don't.
Create .htaccess like this
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteCond %{REQUEST_URI} !^/views/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /views/$1
RewriteCond %{HTTP_HOST} ^(www.)?example.com$
RewriteRule ^(/)?$ views/ [L]
As mentioned in my comment above, providing there are no other directives/conflicts then this should still "work" in a roundabout way. However, there is an issue with the following directive in the order you have placed it:
# check to see if the request is for a PHP file:
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^/?(.*)$ /$1.php
You aren't testing for files in the /views subdirectory. But also, REQUEST_FILENAME does not necessarily contain what (I think) you think it does. When you request /account/voeg-kind-toe (an entirely virtual URL path) then REQUEST_FILENAME contains /account (it actually contains an absolute filesystem path, but I've kept it brief). So, the above is testing whether /account.php exists, not /account/voeg-kind-toe.php, or even /views/account/voeg-kind-toe.php - which is presumably the intention.
So, on the first pass, the above condition fails, no rewrite occurs, and processing continues...
The second rule then rewrites the request for /account/voeg-kind-toe to /views/account/voeg-kind-toe. Providing there are no further mod_rewrite directives, the rewrite engine then starts over. This time, /views/account/voeg-kind-toe is the input.
On the second pass, REQUEST_FILENAME is /views/account/voeg-kind-toe (since /views/account is a physical directory) and the request is rewritten to /views/account/voeg-kind-toe.php (since the filesystem check should be successful). Providing you have no other directives then processing should now stop.
This is working fine in the following case: http://example.com/account/
/account/ is simply rewritten to /views/account/ by the last rule.
Edit: Interesting: If I place the bottom two lines on top (so placing the code to rewrite the view-part before the code to remove the php-extension); the php-extension works but the /views//part don't.
The same process as above occurs, EXCEPT this all occurs in a single pass and so is less dependent on other directives that might occur later in the file.
I'm not sure what you mean by "the /views//part don't"?
Assuming you only have .php files within the /views directory and all URLs are intended to target the /views subdirectory and you don't need to reference directories directly then you could do this is a single directive and rewrite everything that does not contain (what looks like) a file extension to /views/<whatever>.php.
For example:
RewriteRule !\.\w{2,4}$ /views%{REQUEST_URI}.php [L]
The L (last) flag is required if you have other mod_rewrite directives that follow - to prevent additional processing.
This does mean you can't rely on the directory index. ie. You need to request /index (as in your example), not simply / to serve /views/index.php.
(You still need your first rule that removes .php from the requested URL - although this is only strictly necessary if you are changing an existing URL structure, where you previously used .php on the URLs.)

maintenance screen with nested .htaccess files

At the top of the root .htaccess file, I have added
#RewriteCond %{REQUEST_URI} !^/maintenance_503.php [NC]
#RewriteRule .* maintenance_503.php [L]
If uncommented, it redirects the users to a maintenance screen.
However, this doesn't work for subdirectories with their own .htaccess files, and it looks like I cannot use inherit, since it appends parent rules after child rules. I'd rather not add this rule to every single .htaccess file since I want to have a single point of entry for switching it off and on. Are there any best practices for such a case?

mod rewrite exclude all but php

Is it possible to edit htacces in such a way that only the following url is rewritten and the rest isn't?
http://www.example.com/index.php?x=foobar
to
http://www.example.com/foobar/
I want the pages not having x=... as a variable to behave normally
I got the following but that doesn't work
Options +FollowSymLinks
RewriteEngine on
RewriteRule (.*)/ index.php?x=$1
RewriteCond $1 !\.(js|ico|gif|jpg|png|css|html|swf|mp3|wav|txt)$
Who can help me?
First off, the RewriteCond must be put before the RewriteRule to which it belongs.
But I think that you need another approach for your case, something like this:
RewriteRule (.*)\.php - [PT,L]
RewriteRule ^(.*)/$ index.php?x=$1
The first rule Passes Through (PT) every PHP page, so the second rule is only applied to all non-PHP requests.
That second rule only applies to a "simple path", no matter if this path has a dot in it or not (e.g. hello.gif/ will match, too).
If this does not work for you, then you might consider one of these points to start further research:
the pattern ([^\.]*) matches everything that does not have a dot in it
see RewriteCond to skip rule if file or directory exists for RewriteConds where the following RewriteRule is only used if the request does not point to an existing file or directory
Hope this helps.

htaccss redirection

I just moved a site to a subdirectory. Instead of changing every link I'd like to do a 301 redirect via htaccess. Heres an example of what I want to do:
When someone tries to go to www.example.com/test.html, I want them really to go to www.example.com/website/test.html. When someone goes to www.example.com/documents/test.pdf, I want them to go to www.example.com/website/documents/test.pdf.
I want to append the /website/ directory to every request basically. Because I moved the site from the root folder into this subdirectory.
I do have one restriction, I want to make it so that www.example.com/website1/ still goes to www.example.com/website1/. If this changes the solution please give me both solutions, because I am flexible with this.
2 basic approaches (there are some more, but they depend on your rewrite logic (other rules) so may not be suitable for every scenario):
First:
# Redirect all incoming requests into /website/ subfolder
# but excluding /website1/ folder
# First condition is to prevent infinite redirect
RewriteCond %{REQUEST_URI} !^/website/
RewriteCond %{REQUEST_URI} !^/website1/
RewriteRule ^.*$ http://www.example.com/website%{REQUEST_URI} [R=301,L]
Second:
# Redirect all incoming requests into /website/ subfolder
# but excluding /website1/ folder
# Condition is to prevent infinite redirect
RewriteCond %{REQUEST_URI} !^/website/
RewriteRule ^(?!website1/).*$ http://www.example.com/website%{REQUEST_URI} [R=301,L]

Resources