I am trying to send every request to www.example.com/user/ to www.example.com/user.php?id=0 using this
RewriteRule ^user/$ user.php?id=0
Basically, if someone is accessing www.example.com/user/ with no user id, the site will default to id = 0.
However, when I type www.example.com/user/ Apache seems to simply serve the user.php file, completely ignoring the RewriteRule. Any idea on why this is happening?
Thank you.
I should mention that this only happens if I use the same word in the URL as the php file's name. For example, if I were to use
RewriteRule ^yes/$ user.php?id=0
Going to www.example.com/yes/ would apply the RewriteRule just fine.
So it seems that Apache looks for a file with that name and ignores the RewriteRule.
And no, adding a [L] flag did not help.
Here's my .htaccess:
RewriteEngine On
RewriteRule ^user/$ user.php?id=0
RewriteRule ^user/([0-9]+)$ user.php?id=$1
try this:
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^user/$ user.php?id=0 [L,NC,QSA]
RewriteRule ^user/([0-9]+)/?$ user.php?id=$1 [L,NC,QSA]
The [L] flag causes mod_rewrite to stop processing the rule set. In most contexts, this means that if the rule matches, no further rules will be processed. This corresponds to the last command in Perl, or the break command in C. Use this flag to indicate that the current rule should be applied immediately without considering further rules.
from: http://httpd.apache.org/docs/current/rewrite/flags.html#flag_l
I think your rewrite rules are in the wrong order, and you're not using the [L] flag to tell apache not to run any more rules when a rule's been matched. Also you could use the + operator instead of * to match at least one digit in your second rule:
RewriteRule ^user/$ user.php?id=0 [L]
RewriteRule ^user/([0-9]+)$ user.php?id=$1 [L]
Related
RewriteEngine on
RewriteRule ^([^/\.]+)/?$ category.php?slug=$1
RewriteRule ^([^/\.]+)/([^/\.]+)$ product-details.php?slug1=$1&slug=$2
RewriteRule ^([^/\.]+)/?$ infrastructure-details.php?slug=$1
what I have already tried
This is my htaccess file. problem is when I am trying to execute (infrastructure-details.php?slug=$1) its move to (category.php?slug=$1) conflict with first rule of htaccess.
I tired multiple rewrite methods but its not working. Please help to solve this issue.
localhost/project/category.php?slug=pump, localhost/project/infrastructure-details.php?slug=paint second url i want to be-> localhost/project/paint both page is different. can you please specify how to write rules for this different pages.
There is no discernible pattern that differentiates these two URLs so the only way to implement these two rewrites is to hardcode them. For example:
RewriteRule ^pump$ category.php?slug=$0 [L]
RewriteRule ^paint$ infrastructure-details.php?slug=$0 [L]
Where the $0 backreference in the substitution string contains the entire match by the RewriteRule pattern (just saves some repetition).
If you need a more general solution (as your directives suggest) then there needs to be a discernible pattern in the URL that differentiates URLs that should be rewritten to category.php and infrastructure-details.php respectively.
I'm assuming your .htaccess file, and other files, are is inside the /project subdirectory.
RewriteRule ^([^/\.]+)/?$ category.php?slug=$1
RewriteRule ^([^/\.]+)/([^/\.]+)$ product-details.php?slug1=$1&slug=$2
RewriteRule ^([^/\.]+)/?$ infrastructure-details.php?slug=$1
Rule #1 and #3 conflict - they use exactly the same pattern (regex) to match against the requested URL. The first rule is always going to "win" and rewrite the request before rule#3 is able to process the request, so rule#3 never matches.
To write a generic rule like this there needs to be a discernible difference between the URL types that you can match with a pattern/regex. For example:
/category/pump
/infrastructure/paint
And then you can construct rules...
Options -MultiViews
RewriteRule ^category/([^/]+)$ category.php?slug=$1 [L]
RewriteRule ^infrastructure/([^/]+)$ infrastructure-details.php?slug=$1 [L]
Note that the order of these directives can be important. More specific rules need to be before more generalised rules.
Options -MultiViews
RewriteEngine on
RewriteRule ^infrastructure/([^/]+)$ infrastructure-details.php?slug=$1 [L]
RewriteRule ^([^/\.]+)/?$ category.php?slug=$1 [L]
RewriteRule ^([^/\.]+)/([^/\.]+)$ product-details.php?slug1=$1&slug=$2 [L]
This is work fine for me. (infrastructure-details.php?slug=$1 [L]) put on top.
The URLs are:
(Doesn't work) http://example.com/seller/samsung
(Works) http://example.com/seller/samsung/
The .htaccess rule I have for these types of URLs looks like:
RewriteRule ^seller/[^/]+/(.*)$ ./$1
What can I do to make both of these URLs to go to the same page?
You could just force a trailing slash to appear on the end of your URLs. You can do that by using the following in your .htaccess:
RewriteCond %{REQUEST_URI} !(/$|\.)
RewriteRule (.*) %{REQUEST_URI}/ [R=301,L]
Just make sure you clear your cache before you test this.
EDIT:
RewriteCond %{REQUEST_URI} /+[^\.]+$
RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]
What does the above do? So the condition grabs your directory, so for example /samsung and will check if it has a / on the end. If it does not, it will grab the directory at the end of URL (once again /samsung and add a / on to it. It will do this using a 301 redirect and would leave you with /samsung/.
As for the L flag (taken from official documentation):
The [L] flag causes mod_rewrite to stop processing the rule set. In
most contexts, this means that if the rule matches, no further rules
will be processed. This corresponds to the last command in Perl, or
the break command in C. Use this flag to indicate that the current
rule should be applied immediately without considering further rules.
How can I make mod_rewrite redirect to a certain page or probably just throw 404 if no other rules have been satisfied? Here's what I have in my .htaccess file:
RewriteEngine on
RewriteRule ^\. / [F,QSA,L]
RewriteRule ^3rdparty(/.*)$ / [F,QSA,L]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^((images|upload)/.+|style.css)$ $1 [L]
RewriteRule ^$ special [QSA]
RewriteRule ^(special|ready|building|feedback)/?$ $1.php [QSA,L]
RewriteRule ^(ready|building)/(\d+)/?$ show_property.php?type=$1&property_id=$2 [QSA,L]
RewriteRule . error.php?code=404 [QSA,L]
This is supposed, among other things, to send user to error.php if he tries to access anything that was not explicitly specified here (by the way, what is the proper way to throw 404?). However, instead it sends user from every page to error.php. If I remove the last rule, everything else works.
What am I doing wrong?
What is happening is that when you are doing a rewrite, you then send the user to the new URL, where these rewrite rules are then evaluated again. Eventually no other redirectoin rules will be triggered and it will get to the final rule and always redirect to the error.php page.
So you need to put some rewrite conditions in place to make this not happen.
The rewrite engine loops, so you need to pasthrough successful rewrites before finally rewriting to error.php. Maybe something like:
RewriteCond %{REQUEST_URI} !^/$
RewriteCond %{REQUEST_URI} !^/(special|ready|building|feedback|show_property)\.php
RewriteCond %{REQUEST_URI} !^/((images|upload)/.+|style.css)$
RewriteRule ^ error.php?code=404 [QSA,L,R=404]
Each condition makes sure the URI isn't one of the ones your other rules have rewritten to.
The R=404 will redirect to the error.php page as a "404 Not Found".
Unfortunatelly, it didn't work - it allows access to all files on the server (presumably because all conditions need to be satisfied). I tried an alternate solution:
Something else must be slipping through, eventhough when I tested your rules plus these at the end in a blank htaccess file, it seems to work. Something else you can try which is a little less nice but since you don't actually redirect the browser anywhere, it would be hidden from clients.
You have a QSA flag at the end of all your rules, you could add a unique param to the query string after you've applied a rule, then just check against that. Example:
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^((images|upload)/.+|style.css)$ $1?_ok [L,QSA]
then at the end:
RewriteCond %{QUERY_STRING} !_ok
RewriteRule ^ error.php?code=404&_ok [QSA,L,R=404]
In theory if none of the rules are matched (and the requested URL does not exist), it's already a 404. So I think the simplest solution is to use an ErrorDocument, then rewrite it:
RewriteEngine On
ErrorDocument 404 /404.php
RewriteRule ^404.php$ error.php?code=404 [L]
# All your other rules here...
You can do the same for any other HTTP error code.
The problem here is that after the mod_rewrite finishes rewriting the URL, it is resubmitted to the mod_rewrite for another pass. So, the [L] flag only makes the rule last for the current pass. As much better explained in this question, mod_rewrite starting from Apache version 2.3.9, now supports another flag - [END], that makes the current mod_rewrite pass the last one. For Apache 2.2 a number of solutions are offered, but since one of them was a bit clumsy and another didn't work, my current solution is to add another two rules that allow a specific set of files to be accessed while sending 404 for everything else:
RewriteRule ^((images|upload)/.+|style.css|(special|ready|building|feedback|property).php)$ - [QSA,L]
RewriteRule .* - [QSA,L,R=404]
I think your last rule should be
RewriteRule ^(.*)$ error.php?code=404&query=$1 [QSA,L]
You could leave out the parenthesis and the $1 parameter, but maybe it's useful to know, what the user tried to achieve.
Hope, this does the trick!
I've got a problem with rewriting a URL to a fastcgi dispatcher. If I leave only:
RewriteRule ^(.*)$ dispatch.fcgi/$1 [L,QSA]
I expected L (last rule) to cause only a single rewrite. Instead, it keeps prepending dispatch.fcgi until apache reports an error.
I know it can be fixed with:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.fcgi/$1 [L,QSA]
But what is the reason for multiple rewrites? Does L do something else than I think it does?
I know it's an old question, but to others searching for the REAL answer, here it is:
The [L] flag DOES work in .htaccess files. It tells the rewrite module to skip all of the following rules in that particular .htaccess file. It does its job, Apache rewrites the url and exits the .htaccess file.
However, at the end of the .htaccess file if the request url has been rewritten, the whole url matching process starts again with the new url.
This is what happens above, ^(.*)$ will always match the current url, it causes an infinite loop, only the maxredirect rewrite option (10 by default) stops it.
The !-f file attribute test (as mentioned by the questioner) would solve the problem, since the url will match a real filename:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.fcgi/$1 [L,QSA]
now, if we request http://example.com/toappend, .htaccess rewrites it to dispatch.fcgi/toappend and no rewrite loop will happen.
Hy , add this after RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule .* - [L]
.. and it should work stoping loops .
Apparently -- and I only read this here, I have no first hand knowledge -- the [L] directive does not work in .htaccess files, only if its in your .conf file.
See: Hidden features of mod_rewrite
within the .htaccess context, [L] will
not force mod_rewrite to stop. it will
continue to trigger internal
Faced the same problem, and it turns out that the best solution in Apache 2.3.9+ is to use END flag instead of L as it prevents mod_rewrite from looping over rules.
I have a strange problem with mod_rewrite, the rules that are relevant here are:
RewriteRule ^(.*)\/igre\-(.*)\.php\?Page=([0-9]+)$ game.php?GameUrl=$2&Page=$3 [L]
RewriteRule ^(.*)\/igre\-(.*)\.php$ game.php?GameUrl=$2&Page=1 [L]
And a corresponding URL might look something like this:
example.com/miselne-igre/igre-shirk.php?Page=2
example.com/miselne-igre/igre-shirk.php
The problem is that the first rule has no effect. If I use the first URL from the example I always get 1 into the Page variable, which shows that the second rule is used.
So what's wrong with the first one? And why is the second rule even matching a URL with ".php?Page=XYZ" at the end, if I said that the URL ends with ".php"?
ps: other rules in the .htaccess file are working fine...
The query string is not part of the URI path that is being processed by the RewriteRule directive. You have to use the RewriteCond directive to process the query string.
RewriteCond %{QUERY_STRING} ^Page=[0-9]+$
RewriteRule ^[^/]+/igre-([^/]+)\.php$ game.php?GameUrl=$1&%0 [L]
RewriteRule ^[^/]+/igre-([^/]+)\.php$ game.php?GameUrl=$1&Page=1 [L]
But you can still simplify this by using the QSA flag (query string append):
RewriteRule ^[^/]+/igre-([^/]+)\.php$ game.php?GameUrl=$1 [L,QSA]
mod_rewrite is not using the query in it's rewriting process. Therefor you first RewriteRule is ignored. You could combine it with a RewriteCond (haven't tested it though) like so:
RewriteCond %{QUERY_STRING} Page=([0-9]+)
RewriteRule ^(.*)\/igre\-(.*)\.php\?Page=([0-9]+)$ game.php?GameUrl=$2 [L, qsappend]
# qsappend appends the original query, in this case (Page=xx)
Ah, like Gumbo said; you can also use %1 to back reference to the page numer.
Is it just me or are your arguments back-to-front?
Do you mean:
RewriteRule ^(.*)\/(.*)\-igre\.php\?Page=([0-9]+)$ game.php?GameUrl=$2&Page=$3 [L]
RewriteRule ^(.*)\/(.*)\-igre\.php$ game.php?GameUrl=$2&Page=1 [L]
You wanted to match miselne-igre not igre-miselne.
Obviously this doesn't address the main issue, but thought I'd throw that in.
Dom