I'm using MVC with /<module>/<controller>/<action>/ have a module at example.com/module/whatever, and I need to 'rename' it to example.com/module-a/whatever. The whole application is already written, so I can't go through and change it everywhere in my code, so I'm hoping to do it with mod_rewrite. I've tried the following
RewriteCond %{THE_REQUEST} ^GET\ /module/
RewriteRule ^module/(.*) /module-a/$1 [L,R=301]
which did what I wanted as far as redirecting all urls like example.com/module/whatever to example.com/module-a/whatever, but now I need all requests at 'module-a' to be internally rewritten as 'module'. It also needs to work for the module root (i.e. example.com/module with no trailing slash). Is this possible? I added
RewriteRule ^module-a/(.*)$ module/$1
directly beneath the above condition and rule, but when the page is accessed, it still says the module 'module-a' is not found.
Edit:
I have a few more rules below those, I wouldn't think they would affect this, but here they are anyway:
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
Solution
I ended up using
RewriteCond %{THE_REQUEST} ^GET\ /module/
RewriteRule ^module$ /module-a [L,R=301]
RewriteRule ^module/(.*) /module-a/$1 [L,R=301]
to redirect all links from module to module-a. I had to do it with 2 rules because I don't know regex well enough to combine them, handling the special case of the url example.com/module.
To rewrite internally, the original rule I had would normally work, but Zend seems to do some stuff that overrides that, so I had to handle it with routes. See rename a zend module with routes
If I understand correctly then you've gone about this from the wrong direction. I am also not clear on the purpose of your RewriteCond
You want all module-a/* requests to be processed internally as module/*, so all you need is a simple rewrite::
RewriteRule ^module-a/?(.*) /module/$1 [L]
I suspect the problem you are having is the internal links on the site all reference /module/ rather than /module-a/, but putting a 301 there will cause no end of problems (not least with search engines), and with the subsequent rewrite you may fall into circular references. You are much better off changing the link code in your app (if you have a link abstraction class), or at worst using output buffering to swap all links out before rendering the page.
Note: The second rule below the above is not being processed if the first matched, as [L] causes mod_rewrite to cease processing if that rule is matched.
Related
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.)
I wrote this nifty rule that changes a sub folder to a language key!
so i can have a nice clean URL and still get the language variable.
i.e. wwww.mywebsite.com/fr/ or wwww.mywebsite.com/en/ etc...
here is the rule
RewriteRule ^fr/(.*)$ /$1?langId=2 [L,QSA]
RewriteRule ^fr(.*)$ /$1?langId=2 [L,QSA]
it works great on its own!
but, it doesn't work when I add it to a site with url rewrite rule like this one:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ inner.php?folder=$1 [L,QSA]
can anyone suggest a rewrite rule that combines both rules?
the thing is it needs to tell the difference between one variable or two variable.
cuz sometimes i have just the folder variable, sometimes just the lang variable, and sometimes both...
it's a bit of a pickle...
10x!!
Make sure that your language rules are before the global routing rule that routes things to the inner.php script.
I currently have this .htaccess rule the works fine:
RewriteRule ^instructor/([A-Za-z0-9-]+)$ instructor.php?username=$1 [NC,L]
However, when I attempt to add a period into the mix a lot of the rules on the site break so I am assuming the character isn't escaped correctly:
RewriteRule ^instructor/([A-Za-z0-9-\.]+)$ instructor.php?username=$1 [NC,L]
Anyone point me in the right direction please?
Update
It appears to be something to do with the directory structure.
Another selection of rules that apply to this site are the following:
## Registration
RewriteRule ^instructor/register/?$ instructor-form/index.php [L]
RewriteRule ^instructor/register/stage([1-5]+)$ instructor-form/stage$1.php [L]
These work fine (the directory here is instructor-form/
However, there is also a directory called instructor/ which these rules point to:
RewriteRule ^instructor/dashboard/?$ instructor/index.php [L]
RewriteRule ^instructor/account-details/?$ instructor/account-details.php [L]
RewriteRule ^instructor/change-password/?$ instructor/change-password.php [L]
These are the rules that are affected when adding the . into the first rule. The rules are all in order and work fine without the . in the [A-Za-z0-9-] char block. When added the physical instructor/ folder seems inaccessible.
You wrote so much text in your question but forgot to mention important details: what is actually broken? Because I do not have clear answer for that I will be speculating here based on the information you have provided so far.
RewriteRule ^instructor/([A-Za-z0-9-\.]+)$ instructor.php?username=$1 [NC,L]
The problem with this rule is that it will also rewrite already rewritten php files: instructor/index.php, instructor/account-details.php, instructor/change-password.php etc.
I think you are relaying on [L] flag too much .. or do not really know how mod_rewrite and [L] flag work. And that is why you are having this issue -- your rule with a dot in pattern rewrites already rewritten URLs.
Useful link: RewriteRule Last [L] flag not working?
You need to add some condition (global rule or condition specific to this rule only) to prevent rewriting already rewritten URLs or existing files.
1. Global rule -- place it somewhere on the top before other rules. Keep in mind that this may not work as intended depending on your website structure and rewrite logic (e.g. when you need to actually rewrite requests to already existing files or folders):
# do not do anything for already existing files
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .+ - [L]
2. Condition specific to that rule only:
a) do not rewrite if requested URI is physical file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^instructor/([A-Za-z0-9-\.]+)$ instructor.php?username=$1 [NC,L]
OR
b) do not rewrite .php files
RewriteCond %{REQUEST_URI} !.+\.php$
RewriteRule ^instructor/([A-Za-z0-9-\.]+)$ instructor.php?username=$1 [NC,L]
This is my .htaccess code:
RewriteBase /kajak/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^moduli/([^/]+)/(.*)$ moduli/$1/index.php/$2 [L]
Now / is appended to every URL. For example, http://127.0.0.1/moduli/novice becomes http://127.0.0.1/moduli/novice/.
How can I prevent getting / at the end?
While I do not know the answer to your question, I will note two oddities about your question and your code that may be related to the problem at hand.
With the RewriteBase you have in your code, those rules should not even be being triggered.
While I am new to regex myself, I look at ([^/]+) and am a little confused as to why you are capturing it. I know that ^ matches the START of the string, which would never be true since you already have another one at the real start of the string.
This being said, I would probably write the code as below:
RewriteBase /moduli/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/(.*)$ $1/index.php/$2 [L]
This would rewrite URLs as below:
http://www.website.com/moduli/novice/view
http://www.website.com/moduli/novice/index.php/view
Based on your block of code, this seems to be what you are trying to do. If it is not, then I am sorry.
I don't think that's related to your rewrite rule, (it does not match it).
The / is added because when you request http://example.com/xx/zz and the web server detects zz is a directory, it transforms it to http://example.com/xx/zz/ through a 301 redirect (the browser makes another request - check you apache logs).
Read about the trailing slash redirect thing here.
The, you must aks yourself, what do you want to happen when the url requested is http://127.0.0.1/moduli/novice/ (Do you want it to be be catched by your redirect or not? Currently it's not catched because of RewriteCond %{REQUEST_FILENAME} !-d)
BTW, I don't quite understand your RewriteBase /kajak/ line there - are you sure it's correct?
Hi people#stackoverflow,
Maybe I have a fundamental misconception about the working of RewriteRule. Or maybe not. Nevertheless, I'm trying to figure this out now for two days, without any progress.
This is the currrent situation:
I have a Joomla website with SEF and mod_rewrite turned on.
This results in the URL:
mysite.com/index.php?option=com_remository&Itemid=7
being rewritten to:
mysite.com/sub-directory/sub-directory/0000-Business-files/
These are the lines that are currently used in my .htaccess (all standard Joomla)
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^([^\-]*)\-(.*)$ $1 $2 [N]
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR]
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ index.php [F,L]
# RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{REQUEST_URI} (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$ [NC]
RewriteRule (.*) index.php
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
This is what I want to achieve:
When a visitor uses this URL
mysite.com/sub directory/sub directory/0000 Business files/
it should lead him to the right page.
Although I know it's not the best idea to use spaces in a URL, I'm confronted with the fact that these 'spacious' URL's are used in a PDF, that's already been issued.
I thought I could use mod_rewrite to rewrite these URL's. But all I get is 'page not found'
I've added this rule on top of the .htaccess file:
RewriteRule ^([^\-]*)\-(.*)$ $1 $2 [N]
But this is not working. What am I doing wrong? Or, also possible, am I missing the point on when and how to use mod_rewrite?
rgds, Eric
First off, the default behavior of apache is usually to allow direct URLs that map to the underlying file system (relative to the document root), and you should use RewriteRule when you want to work around that. Looking at your question, it seems like you want to browse the filesystem and so you should not use a RewriteRule.
If mysite.com/sub+diretory/sub+directory/0000+Business+files/ doesn't work (without your rule), I'm wondering: do you have that directory structure on your server? I.e. does it look like this?
[document root]/index.php
[document root]/sub directory/sub directory/0000 Business files/
If not, I'm not sure I understand what you're trying to achieve, and what you mean by the visitor being "lead to the right page". Could you provide an example URL that the user provides, and the corresponding URL (or file system path) that you want the user to be served.
Regarding your rewrite rule, I'm not even sure that it is allowed, and I'm surprised you don't get a 500 Internal Server Error. RewriteRule takes two arguments (matching pattern and substitution) and optionally some flags, but because of the space between $1 and $2 you're supplying three arguments (+ flags).
EDIT: I got the pattern wrong, but it still doesn't make much sense. It matches against any URL that has at least one dash in it, and then picks out the parts before and after the first dash. So, for a URL like "this-is-a-url-path/to-a-file/on-the-server", $1 would be "this" and $2 would be "is-a-url-path/to-a-file/on-the-server". Again, if I had some example URLs and their corresponding rewrites, I could help you find the right pattern.
On a side note, spaces aren't allowed in URLs, but the browser and server probably does some work behind the scenes, allowing your PDFs to be picked up correctly.