Redirect home page only to another link - apache

Say I want to redirect only http://example.com/ to http://example.com/main/, how do I do it?
Here's what I am doing right now:
RewriteEngine On
RewriteBase /
RewriteRule ^$ main/ [R=301,L]
The problem is, it's also redirecting query strings. For example: http://example.com/?channel=science is being redirected to http://example.com/main/?channel=science.
I don't want only the valid/specified non-empty (i.e. value is specified) query strings to be redirected. For example:
http://example.com/?channel
Should be redirected as well. How do I do this?

You can use (one or more) RewriteCond between your RewriteBase and RewriteRule to force rewrites only when querystring matches (or doesn't match with a !) what you want it to.
This will only redirect requests whose querystring matches cat or channel
RewriteCond %{QUERY_STRING} ^(.*)(channel|cat)(.*)$
You can also use multple RewriteCond combined with [OR] flags if you need one of the conditions, or without the [OR] flag if you need all conditions to be true at the same time. E.g.
RewriteCond %{QUERY_STRING} ^(.*)(channel)(.*)$ [OR]
RewriteCond %{QUERY_STRING} ^(.*)(cat)(.*)$
Also, if you want to remove the querystring from the redirected page, just add a ? to the end of your redirect url like this:
RewriteRule ^$ main/? [R=301,L]

Related

How to redirect a url that ends with html to https non-www version, while also retrieve the content from a specific php files?

i am still new to htaccess. I have a static website, that has a content inside several directories. I use this to redirect 301 all html pages to its https non-www version.
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
RewriteRule (.*) https://example.com/$1 [L,R=301]
I want the website to be dynamic. So after it redirects to https non-www version, i want it to grab the resources from a specific php files. But, i don't know how to do that, while also do the first 301 redirect.
I try to grab the resources by using something like:
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
RewriteRule (.*) https://example.com/$1
RewriteRule (.*)/(.*)/(.*)\.html$ https://note.mathpro.id/$2.php?name=$3 [L,R=302]
This URL http://example.com/category/uncategorized.html retrieves the content from https://example.com/category.php?name=uncategorized, but doesn't redirect it to https://example.com/category/uncategorized.html as it intially did.
Can anyone help?
... i don't know how to do that, while also do the first 301 redirect.
These are two entirely separate tasks that requires two different rules. You should not modify the first (canonical redirect) rule. (For some reason, you have removed the flags argument, ie. [L,R=301] - The L flag is required for the redirect to function as intended.)
RewriteRule (.*)/(.*)/(.*)\.html$ https://note.mathpro.id/$2.php?name=$3 [L,R=302]
This should not be an external redirect, it should be an internal rewrite. In order words, you want the (visible) URL to remain as /category/uncategorized.html. You don't want the end user to see /category.php?name=uncategorized.
For some reason you also have three capturing subpatterns in the RewriteRule pattern (.*)/(.*)/(.*)\.html$, whereas your example URL /category/uncategorized.html only has two?
Your regex should also be more restrictive. The "problem" with the very generic .* is that it is "greedy" and consumes everything, including slashes. So this regex will also match /foo/bar/baz/zip/bah/yop.html. (But which parts will it match/capture exactly?)
Try the following instead:
# 1. Canonical redirect (UNCHANGED)
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
RewriteRule (.*) https://example.com/$1 [L,R=301]
# 2. Rewrite to handler
RewriteRule ^([^/]+)/([^/]+)\.html$ $1.php?name=$2 [L]
This assumes the .htaccess file is located in the document root.
However, a minor problem with the above rewrite is that it rewrites the URL regardless of whether the "handler" (eg. category.php) exists or not. This isn't necessarily a big deal, but it means the 404 is triggered on category.php (the rewritten file-path), not /category/uncategorized.html (the originally requested URL from the user).
To resolve this, you can check whether the target file exists first. For example:
# 2. Rewrite to handler if it exists
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^/]+)/([^/]+)\.html$ $1.php?name=$2 [L]

Both URL With PHP and Non-PHP Access after RewriteRule In Htaccess

Access Both URL With PHP and Non-PHP in PHP project after applying Htacces Rules
RewriteRule ^c/([a-zA-Z0-9-/]+)$ category.php?id=$1 [L]
RewriteRule ^p/([a-zA-Z0-9-/]+)$ detail.php?post=$1 [L]
Here I access both URLs like www.example.com/c/category-name and www.example.com/category.php?id=12 but I want only www.example.com/c/category-name URL. I don't Want Duplicate URLs both this page.
With your shown samples, attempts please try following htaccess rules. Make sure to clear your browser cache before testing your URLs.
RewriteEngine ON
##Internal rewrite rules.
RewriteCond %{HTTP_HOST} ^(?:www\.)?example.com$ [NC]
RewriteRule ^c/([\w-]+)/?$ category.php?id=$1 [QSA,NC,L]
##External redirect rules.
RewriteCond %{HTTP_HOST} ^(?:www\.)?example.com$ [NC]
RewriteCond %{THE_REQUEST} \s/category\.php?id=(\S+)\s [NC]
RewriteRule ^ /c/%1? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^[^/]*/(.*)/?$ category.php?id=$1 [QSA,NC,L]
Unless you have changed an existing URL structure and category.php and/or detail.php have been indexed by search engines then you could simply force a 404 when either of these URLs are accessed directly.
For example, the following should go before your existing rewrites:
# Block direct access to "category.php" or "detail.php"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(category|detail)\.php$ - [R=404]
The check against the REDIRECT_STATUS env var ensures that we are only checking direct requests and not rewritten requests by the later rewrite.
Otherwise, if these "old" URLs have previously been indexed by search engines or linked to by third parties then you should redirect to the "new" (canonical) URLs instead. For example:
# Redirect "category.php" or "detail.php" to canonical URL
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^(?:id|post)=([a-zA-Z0-9/-]+)$
RewriteRule ^(?:(c)ategory\.php|detail\.(p)hp)$ /$1/%1 [R=301,L]
I've moved the hyphen to the end of the character class (ie. from [a-zA-Z0-9-/] to [a-zA-Z0-9/-]) to avoid a potential ambiguity since hyphens are naturally special characters inside a character class.
The $1 backreference contains either c or p, depending on the request, to form the first path segment. %1 is the value captured from the URL-parameter. Importantly, this is the same regex you are using the later rewrite to match the value.
NB: Test first with a 302 (temporary) redirect to avoid potential caching issues.

Redirect whole site from http to https except one route with query parameters

I have read some question about redirect the whole site from http to https changing .htaccess like this:
# Rewrite http://www.example.com to https://www.example.com
#
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
It works good, but I need to exclude one route from this redirect, and I have found examples for a static url, but I haven't found a rule (RewriteCond) when the url has query parameters. I want that a custom route was accessed only with http. This route requires some query parameters that must be present, and other are optionals. For exmple:
http://<mydomain>/dataregister?device=id1234&val1=20&val2=30&hash=12345689
I think I should add another RewriteCond to exclude this route, but I'm not sure how to do it. I have tried with this, but It doesn't work:
RewriteCond %{THE_REQUEST} != /dataregister [NC]
Have it like this:
RewriteCond %{THE_REQUEST} !/dataregister/?\? [NC]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
Pattern /dataregister/?\? will match original URL that contains either /dataregister/? or /dataregister\?.
Make sure to clear your browser cache before testing change.

Restrict some url pattern in a apache redirect

I am writing a redirect to match any url of the patter /message/* here.
RewriteRule ^/message/(.+)$ http://abet.in/message/$1 [NC,R=301,L]
Now I want to modify it by not allowing some string pattern in url.
RewriteCond to check /message/index.html in the url.
1. Check if the request url contains /message/index.html.
2. If the condition is not met then do a redirect.
I tried the following methods. But I am not sure whether they are correct or not.
RewriteCond %{THE_REQUEST} !^/message/index
RewriteCond %{REQUEST_URI} !^/message/index [NC]
Could some one tell how to do this.
%{THE_REQUEST} contains a string that looks like this for a regular page request:
GET /message/index.html HTTP/1.1
And %{REQUEST_URI} looks like this:
/message/index.html
So your 2nd option is almost correct. You don't need a / at the start of the Pattern for RewriteRules.
Additionally, these two rules will prevent all requests that start /message/index from being redirected):
RewriteCond %{REQUEST_URI} !^/message/index [NC]
RewriteRule ^message/(.+)$ http://abet.in/message/$1 [NC,R=301,L]
If you only want to prevent /message/index.html and not /message/index.php or /message/index-of-something-else then do:
RewriteCond %{REQUEST_URI} !^/message/index\.html [NC]
RewriteRule ^message/(.+)$ http://abet.in/message/$1 [NC,R=301,L]

redirect url with query string to path, and url without query string must be internally rewritten

I've been trying and trying.
If one goes to:
www.domain.nl/vereniging
internally a page is requested from:
www.domain.nl/?p=vereniging
For that I use this:
RewriteCond %{QUERY_STRING} !(p=.*)$
RewriteRule ^(.+)$ ?p=$1 [NC]
If a users visits:
www.domain.nl/?p=vereniging
I want the users to be redirected to:
www.domain.nl/vereniging
For that I use:
RewriteCond %{QUERY_STRING} ^p=(.*)$ [NC]
RewriteRule ^$ http://www.domain.nl/%1? [NC,R=301]
(If I put RewriteCond %{REQUEST_FILENAME} !-d before this, it doesn't redirect anymore. That's strange because a query is not a directory right?)
Separately, these 2 chunks of code work.
However, if I put them together in 1 .htaccess it bitches about looping.I don't understand this, because the conditions should prevent looping.
Try applying the END flag to either the first or second RewriteRule.
Look at the END flag here: http://httpd.apache.org/docs/current/rewrite/flags.html
You need to check against the actual request:
RewriteCond %{THE_REQUEST} \?p=([^&\ ]+)
RewriteRule ^ /%1? [L,R=301]