Mod_Rewrite Difference between [L] and [R] - ajax

I am attempting to rewrite any URL with "_excaped_fragment_=/some/directory" to "/some/directory?ajax=1". The code below is working correctly but i would like to do it without the redirect. This is a Wordpress site.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
AddDefaultCharset UTF-8
RewriteCond %{QUERY_STRING} ^_escaped_fragment_=(.*)$
RewriteRule (.*) %1?ajax=1 [L,R=301]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
If I remove "R=301" and just leave the "L" it does not work. I have read about [L] not stopping when from .htaccess, but i actually do not want it to stop. I would like it to just change the URL then go through the regular Wordpress rewrite.
Any ideas? Let me know if you need more information.
Edit:
Wanted to add an answerable question. Why does a redirect work and no redirect not work? Does the URL get changed as it works its way down the file or only on the last rule?

The [L] will stop any further processing in .htaccess if the rule matched.
The way you have this written the [L] will do that, but then you add [R=301] which is a redirect. That will cause the request to be sent back to the "top of the stack" in Apache for processing as if it was a completely new request, since you are doing a redirect. HOWEVER, now on the 2nd time through you've got the modified URL because the rewrite was processed before doing the hand-off.
In other words [L] does the mangling, then says "OK, we are done here, drop out to normal web processing now".
[L,R=301] does the mangling, then says "we are done with THAT, now got tell whomever is next is line that we've done a redirect".
That last part of the [L,R=301] triggers a whole new set of logic to process the "hey, we just got a redirect" rules. In your case, causing the entire rewrite sequence to be processed from the top with the mangled URL this time around.

Related

Mod rewrite rule for mapping one or two parameters

I have the following .htaccess:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?([^/]+)/?$ /?page=$1 [L,QSA]
RewriteRule ^/?([^/]+)/([^/]+)/?$ /?page=$1&id=$2 [L,QSA]
This rules allow to enter urls like:
example.com/my-account-dashboard
example.com/my-account-dashboard/1
which are pretty urls for:
example.com?page=my-account-dashboard
example.com?page=my-account-dashboard&id=1
This works fine so far. But internaly the links are with those parameters. Is it possible to redirect (or something) to the pretty urls if possible? What are the rewrite rules for that?
First of all, a few remarks about your current code which contains some errors.
1) RewriteCond only applies on the very next RewriteRule. So your second RewriteRule can match without that condition (you can try it, you'll see). You need to put (again) that condition to the other RewriteRule (or use S skip flag to simulate if/else condition but it gets complicated for nothing).
2) I'm pretty sure you don't want to use QSA flag the way you do. By using it, you tell mod_rewrite to append any query string to the rewrite. Example: example.com/my-account-dashboard/?foo=bar will rewrite to /?page=my-account-dashboard&foo=bar. So unless you really want that, you don't need it. A lot of people think that they need QSA when adding some query string directly in the rewrite, just like you do. Again, this is not an error that will make everything crash, but still it's not totally correct.
3) Your rules create duplicate content which is bad for SEO (referencing). For instance, example.com/my-account-dashboard and example.com/my-account-dashboard/ (notice the trailing slash) both lead to the same page. But search engines won't consider them as the same. I invite you to search "duplicate content" on Google (or any other search engine you like) and have a look at it. A simple way to avoid this is to chose either with or without the trailing slash.
Now that the base is clear, let's answer to your question. You can't simply use a redirect R from old-url to new-url because you'd end up with an infinite loop. Something is there for this problem: THE_REQUEST. When mod_rewrite uses it, it is able to know that it comes from a direct client request, not a redirect/rewrite by itself.
All-in-one, here is how your code should look like:
RewriteEngine On
RewriteBase /
# Redirect old-url /?page=XXX to new-url equivalent /XXX
RewriteCond %{THE_REQUEST} \s/\?page=([^/&\s]+)\s [NC]
RewriteRule ^ /%1? [R=301,L]
# Redirect old-url /?page=XXX&id=YYY to new-url equivalent /XXX/YYY
RewriteCond %{THE_REQUEST} \s/\?page=([^/&\s]+)&id=([0-9]+)\s [NC]
RewriteRule ^ /%1/%2? [R=301,L]
# if /XXX is not a file/directory then rewrite to /?page=XXX
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?([^/]+)$ /?page=$1 [L]
# if /XXX/YYY is not a file/directory then rewrite to /?page=XXX&id=YYY
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?([^/]+)/([0-9]+)$ /?page=$1&id=$2 [L]
NB: i chose to use the "without trailing slash" option (e.g. example.com/my-account-dashboard and example.com/my-account-dashboard/1). Feel free to ask if you want with.

CodeIgniter and specific rewrite rule

On my CodeIgniter site, I would like to add a specific rewrite rule, so that this url
http://www.exemple.com/cache.manifest
would rewrite to
http://www.exemple.com/controller/manifest
(because Safari 7 seems to only accept .manifest files for ApplicationCache)
So I try to add this line to my htaccess
RewriteRule ^cache.manifest$ controller/manifest
I added it before the other rewrite rules :
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^cache.manifest$ controller/manifest
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
But it returns a 404. If I change the line to
RewriteRule ^cache.manifest$ test.html
it works. So the first part on my rule is correct.
If I try to access directly to www.example.com/controller/manifest, it works to, so my url is correct.
I tried also
RewriteRule ^cache.manifest$ index.php/controller/manifest [L]
But it doesn't work either…
Any clue ?
Thanks a lot
I tried some tests on my local server and I think the following might work:
RewriteRule ^cache.manifest$ /index.php/controller/manifest [R,L]
I am not entirely sure if you need the leading "/" or "/index.php", so you
may need to experiment.
You need the [R] flag to force a redirect. In this situation, you want Apache
to look for the string cache.manifest in the URL, and then go to the CI page
controller/manifest.
It appears that you need to explicitly set the redirect.
Please let me know if this works. Good luck!

.htaccess works in local but not on server (but no 404 error)

I have a .htaccess that is supposed to rewrite my URL. My host has told me that it supports URL rewriting, and I verified that by using phpinfo() and checking.
Anyways, this is my .htaccess:
RewriteEngine On
RewriteRule ^([_a-zA-Z0-9]+)$ index.php?page=$1 [R]
It works like a charm in local, but on my server, it doesn't do anything.
I checked this before on the internet and some people had it, but they all had a 404 error, while I don't have a 404 error. It simply doesn't redirect, it doesn't do anything, so I get all kind of error messages.
RewriteRule ^([_a-zA-Z0-9]+)$ index.php?page=$1 [R]
The regex in your rule doesn't match strings with slashes at any position. I am not sure that's acceptable and you don't give any request examples, but I don't think it is.
You may try this rule-set in one .htaccess file at root directory:
Options +FollowSymlinks -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !index\.php [NC]
RewriteRule ^([^/]+)/?$ index.php?page=$1 [L]
For permanent redirection replace [L] with [R=301,L].
You can make sure that the file (!-f) or directory (!-d) that you're matching doesn't exist before the rewrite. That way you don't end up with a 500 loop with something like /index.php?page=index. Additionally the ^ character is matching the beginning of the string, so if your original test was in a subdirectory it would not rewrite since you weren't allowing slashes.
This should work for any instance, however it will ONLY make the page variable the last string in the URI.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ([_a-zA-Z0-9]+)$ /index.php?page=$1 [R,L]

301 URL Forwarding with HTACCESS or PHP

Just curious if anyone can help me on this HTACCESS issue.
I have these OLD URLS that need to get forwarded properly.
Previous structure
domain.com/Canada/Accounting
domain.com/Canada/Trades
domain.com/Canada/Sales
Proper structure
CATEGORY - /jobs/accounting-jobs
LOCATION - /jobs/jobs-kelowna
TOGETHER - /jobs/accounting-jobs-kelowna
Domain Structure
domain.com/jobs/[category]-jobs-[location]
Is this possible, either by HTACCES or PHP...just don't want these 404'ed pages.
I have 86+ to do, if there is a good way to forward these.
This is what I have, but i'm unable to successfully forward the bad-urls properly.
OLD
/browse
/Toronto/
/Canada/Administrative
/Vancouver/
/Canada/Trades
/Calgary/
/Canada/Hospitality
This is my HTACCESS right now.
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
#
# Trailing slash check
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule ^(.*)$ $1/ [L,R=301]
#
# PAGES
RewriteRule ^add-job/?$ /add-job.php [L]
RewriteRule ^jobs/?$ /results.php [L]
RewriteRule ^sitemap/?$ /sitemap.php [L]
#
# SEARCH
# CATEGORY - accounting-jobs
# LOCATION - jobs-kelowna
# TOGETHER - accounting-jobs-kelowna
RewriteRule ^jobs/([a-zA-Z0-9_-]+)/([0-9]+)?$ results.php?whatwhere=$1&page=$2
RewriteRule ^jobs/([a-zA-Z0-9_-]+)/([0-9]+)/?$ results.php?whatwhere=$1&page=$2
To 301 redirect your pages you can do something like:
RewriteEngine On
RewriteBase /
RewriteRule ^(\w+)/(\w+)$ /jobs/$2-jobs-$1 [R=301,L]
This only addresses the urls from your previous structure (the combinations, you have not shown any previous urls with just location or category) but note that Canada will stay Canada, it does not become canada. You can change everything to lower case using rewrite as well.
You also have to take care that you don't rewrite any of the current urls but without more information, this should do it.
Edit: For the location-only urls you could use a rule like:
RewriteRule ^(\w+)/$ /jobs/jobs-$1 [R=301,L]
Again, you need to look out that your rewrite rule does not interfere with your current urls. If that is the case, you would need to redirect every old url manually.
For lower-case new urls, you should search SO, there are some questions with good answers about converting a mized-case variable to lower-case.
If you have mod_rewrite, you can add these lines to your .htaccess file:
RewriteEngine on
RewriteRule ^Canada/Accounting$ /jobs/accounting-jobs [R,L]
However, it's not clear from your question exactly what you want mapped. Are the 3 previous URLs supposed to redirect to the 3 new ones? They don't seem to be equivalent.

mod rewrite and static pages

is possible to exclude a url being parsed by mod rewrite?
my .htaccess has rewrite rules like
RewriteRule ^contact contact_us.php
and a couple more static pages.
currently my site don't have troubles cause uses http://domain.com/user.php?user=username
but now i need rewrite to:
http://domain.com/username
I've tried with:
RewriteRule ^(.*)$ user.php?user=$1 [L]
but all my site stops working...
is possible to avoid parse my static pages like contact/feed/etc being treated like usernames?
edit to match david req:
this is my actual .htaccess file:
RewriteEngine On
Options +Followsymlinks
RewriteRule ^contact contact_us.php [L]
RewriteRule ^terms terms_of_use.php [L]
RewriteRule ^register register.php [L]
RewriteRule ^login login.php [L]
RewriteRule ^logout logout.php [L]
RewriteRule ^posts/(.*)/(.*) viewupdates.php?username=$1&page=$2
RewriteRule ^post(.*)/([0-9]*)$ viewupdate.php?title=$1&id=$2
RewriteRule ^(.*)$ profile.php?username=$1 [L]
also i've enabled modrewrite log my first file:http://pastie.org/1044881
Put the rewrite rules for the static pages first, and add the [L] flag to them:
RewriteRule ^contact contact_us.php [L]
...
then after those, use your rewrite rule for the username:
RewriteRule ^(.*)$ user.php?user=$1 [L]
(hopefully nobody has a username of contact).
EDIT: Based on the log output you posted (which I'm assuming corresponds to an unsuccessful attempt to access the contact page... right?), try changing the contact rewrite rule to either
RewriteRule ^contact$ contact_us.php [L]
or
RewriteRule ^contact contact_us.php [L,NS]
That is, either add $ to make the pattern match only the literal URL contact, or add the NS flag to keep it from applying to subrequests. According to the log output, what seems to have happened is that Apache rewrites contact to contact_us.php and then does an internal subrequest for that new URL. So far so good. The weird thing is that the ^contact pattern again matches contact_us.php, "transforming" it to contact_us.php, i.e. the same thing, which Apache interprets as a signal that it should ignore the rule entirely. Now, I would think Apache would have the sense to ignore the rule only on the subrequest, but I'm not sure if it's ignoring the entire rewriting process and leaving the original URL, /contact, as is. If that's the case, making one of the changes I suggested should fix it.
EDIT 2: your rewrite log excerpt reminded me of something: I'd suggest making the rewrite rule
RewriteRule ^([^/]+)$ user.php?user=$1 [L]
since slashes shouldn't be occurring in any usernames. (Right?) Or you could do
RewriteRule ^(\w+)$ user.php?user=$1 [L]
if usernames can only include word characters (letters, numbers, and underscore). Basically, make a regular expression that matches only any sequence of characters that could be a valid username, but doesn't match URLs of images or CSS/JS files.
The -f and -d options to RewriteCond check if the current match is a file or directory on disk.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ....

Resources