How to redirect url to the url with htaccess - apache

I didn't know how to question this but my problem is like this
I have written a rule for a url
RewriteRule ^mysite.com.pk/([a-zA-Z0-9]+) index.php?store=$1
RewriteRule ^mysite.com.pk/([a-zA-Z0-9]+)/products index.php?store=$1&view=products
RewriteRule ^mysite.com.pk/([a-zA-Z0-9]+)/products/([0-9]+) index.php?store=$1&view=products&category=$2
RewriteRule ^mysite.com.pk/([a-zA-Z0-9]+)/single/([0-9]+) index.php?store=$1&view=single&product=$2
I am new to htaccess so I don't know much about it. Is there a way that even if a old url comes like index.php?store=abc&view=single&product=123
this will be redirected to a new one like mysite.com.pk/abc/single/123

You have to make some small modifications to your proposed rules to get them to work. And you have to add additional rewriting rules to achieve what you actually ask: redirecting "old" URLs to your new syntax.
This is probably what you are looking for:
RewriteEngine on
RewriteRule ^/?([a-zA-Z0-9]+)$ index.php?store=$1 [END]
RewriteRule ^/?([a-zA-Z0-9]+)/products$ index.php?store=$1&view=products [END]
RewriteRule ^/?([a-zA-Z0-9]+)/products/([0-9]+)$ index.php?store=$1&view=products&category=$2 [END]
RewriteRule ^/?([a-zA-Z0-9]+)/single/([0-9]+)$ index.php?store=$1&view=single&product=$2 [END]
# index.php?store=xyz&view=single&product=123
RewriteCond %{QUERY_STRING} store=([^&]+)&?
RewriteCond %{QUERY_STRING} view=single&?
RewriteCond %{QUERY_STRING} product=([^&]+)&?
RewriteRule /?index.php$ /%1/single/%3 [END,R=301]
# index.php?store=xyz&view=products&product=123
RewriteCond %{QUERY_STRING} store=([^&]+)&?
RewriteCond %{QUERY_STRING} view=products&?
RewriteCond %{QUERY_STRING} category=([^&]+)&?
RewriteRule /?index.php$ /%1/products/%3 [END,R=301]
# index.php?store=xyz&view=products
RewriteCond %{QUERY_STRING} store=([^&]+)&?
RewriteCond %{QUERY_STRING} view=products&?
RewriteRule /?index.php$ /%1/products [END,R=301]
# index.php?store=xyz
RewriteCond %{QUERY_STRING} store=([^&]+)&?
RewriteRule /?index.php$ /%1 [END,R=301]
Those rules should work the same in a .htaccess style file and in the real http host configuration. Please see the note below about that.
If you are using an old version of the apache http server then you may have to replace the END flag by the L flag. Try that if you receive an "internal server error" (http status 500) and the server complains about the END flag in the error log file. You may have to add some additional conditions to prevent an endless rewriting loop in that case.
Please note that I did not test that rule set. I hope it does not contain any silly mistakes and you certainly will have to test it.
All of the above assumes that mysite.com.pk is meant to match your host name ("domain"). But that will not work, since the RewriteRules work on the request path, not the full URL. If you want to limit the application of the rules to a specific host, then you can add a leading condition to stop the rewriting process:
RewriteCond %{HTTP_HOST} !^mysite\.com\.pk`
RewriteRule .* - [END]
And a general hint: you should always prefer to place such rules inside the http servers host configuration instead of using .htaccess style files. Those files are notoriously error prone, hard to debug and they really slow down the server. They are only provided as a last option for situations where you do not have control over the host configuration (read: really cheap hosting service providers) or if you have an application that relies on writing its own rewrite rules (which is an obvious security nightmare).

Related

.htaccess RewriteRule from long url to show short url

Im trying to rewrite url from long to short but cant wrap my head around this.
My survey rewrite works wonderfully but after completing my survet php redirects to www.example.com/survey_thank_you.php?survey_id=1
but I would like to show url like www.example.com/thank_you
Im not even sure if this is possible.
Im new with .htaccess and i have tried almost everthing
.htaccess
Options +FollowSymLinks
Options -MultiViews
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^survey_thank_you.php?survey_name=([0-9a-zA-Z]+)/?$ Thank_you [L,NC,QSA]
RewriteRule ^([0-9a-zA-Z]+)/?$ survey_form.php?survey_name=$1 [L,NC,QSA] #works like charm.
Any help or directions will be highly appreciated.
Solution:
Options +FollowSymLinks
Options -MultiViews
RewriteEngine on
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^survey_id=([0-9a-zA-Z]+)/?$
RewriteRule ^survey_thank_you\.php$ /%1/thank_you [R,L,QSD]
RewriteRule ^([0-9a-zA-Z]+)/thank_you$ survey_thank_you.php?survey_id=$1 [L,NC,QSA]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([0-9a-zA-Z]+)/?$ survey_form.php?survey_name=$1 [L,NC,QSA]
but after completing my survet php redirects to www.example.com/survey_thank_you.php?survey_id=1
You need to "correct" the URL that PHP is redirecting you to after the survey. If the desired URL is /thank_you (or /Thank_you?) then PHP should be redirecting to that URL.
You then use mod_rewrite in .htaccess to internally rewrite /thank_you back into the URL that your application understands. ie. /survey_thank_you.php?survey_id=1. However, therein lies another problem, where does the 1 (survey_id) come from in the query string? Presumably you don't want to hardcode this? So this would need to passed in the requested URL. eg. /1/thank_you or perhaps /thank_you/1?
However, is this really necessary? The resulting "thank you" page is not a page that should be indexed or a page that is normally navigated to by the user, so implementing a user-friendly URL here doesn't seem to be a worthwhile exercise?
RewriteRule ^survey_thank_you.php?survey_name=([0-9a-zA-Z]+)/?$ Thank_you [L,NC,QSA]
RewriteRule ^([0-9a-zA-Z]+)/?$ survey_form.php?survey_name=$1 [L,NC,QSA] #works like charm.
You are using a survey_name URL parameter (referencing an alphanumeric value) in your directives, but a survey_id ("numeric"?) URL parameter in your earlier example? So, which is it? Or are these rules unrelated?
You state that the second rule "works like charm", but how? What URL are you requesting? That would seem to rewrite /Thank_you to survey_form.php?survey_name=Thank_you - but that does not look correct?
As mentioned in comments, the RewriteRule pattern matches against the URL-path only. To match against the query string you need an additional condition that matches against the QUERY_STRING server variable. This would also need to be an external 3xx redirect, not an internal rewrite (in order to change the URL that the user sees). Therein lies another problem... if you don't change the URL that your PHP script is redirecting to then users will experience two redirects after submitting the form.
You also need to be careful to avoid a redirect loop, since you are internally rewriting the request in the opposite direction. You need to prevent the redirect being triggered after the request is rewritten. ie. Only redirect direct requests from the user should be redirected.
So, to answer your specific question, it should be rewritten something like this instead:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^survey_name=[0-9a-zA-Z]+/?$
RewriteRule ^survey_thank_you\.php$ /Thank_you [QSD,R,L]
The check against the REDIRECT_STATUS environment variable ensures that only direct requests are processed, not internally rewritten requests by the later rewrite. REDIRECT_STATUS is empty on the initial request and set to the string 200 (as in 200 OK status) after the first successful rewrite.
The QSD flag (Apache 2.4) is necessary to discard the original query string from the redirect response.
So the above would redirect /survey_thank_you.php?survey_name=<something> to /Thank_you.
But this is losing the "survey_name" (or survey_id?), so should perhaps be more like the following, in order to preserve the "survey_name":
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^survey_name=([0-9a-zA-Z]+)/?$
RewriteRule ^survey_thank_you\.php$ /%1/Thank_you [QSD,R,L]
Where %1 is a backreference to the value of the survey_name URL parameter captured in the preceding CondPattern.
However, you would then need to modify your rewrite that turns this back into an understandable URL.
(But you should probably not be doing this in the first place without first changing the actual URLs in the application.)

.htaccess redirection not working in ubuntu

To remove multiple slashes I wrote this condition that is working in windows system but not in Ubuntu 18.04 I don't know why..?
RewriteCond %{HTTP_HOST} !=""
RewriteCond %{THE_REQUEST} ^[A-Z]+\s//+(.*)\sHTTP/[0-9.]+$
RewriteRule .* %{HTTP_HOST}/%1 [R=301,L]
I am getting this error in ubuntu system..
Forbidden
You don't have permission to access this resource.
And my URL changed this
http://in.decashop.localhost/p/8489882_500-boys-gym-short-sleeved-t-shirt-grey.html
to this
http://in.decashop.localhost/var/www/html/decashopglobal/www/in.decashop.localhost/p/8489882_500-boys-gym-short-sleeved-t-shirt-grey.html
if I put multiple slashes like
http://in.decashop.localhost///p/8489882_500-boys-gym-short-sleeved-t-shirt-grey.html
At first, you can check apache's log. try to access your website using URL or IP and check your Webserver's log information.
In ubuntu you can try:
sudo tail -f /var/log/apache2/error.log
In most cases wrong permission is the main cause of this problem.
RewriteCond %{HTTP_HOST} !=""
RewriteCond %{THE_REQUEST} ^[A-Z]+\s//+(.*)\sHTTP/[0-9.]+$
RewriteRule .* %{HTTP_HOST}/%1 [R=301,L]
The output you are seeing is consistent with the directives you have posted, as you are missing the scheme (ie. http) on the substitution string in the RewriteRule directive (which presumably should be an absolute URL) - so I don't see how this would have "worked" on the Windows server? Unless you had a very different config (but even then it couldn't have worked the same way).
With the RewriteRule directive as written, the substitution string (ie. %{HTTP_HOST}/%1) would be seen as a relative URL and Apache would then add back the directory-prefix ie. /var/www/html/decashopglobal/www/ prior to issueing the redirect - which naturally results in the malformed redirect you are seeing. If you had set a RewriteBase directive elsewhere in the config file, then this would have overridden this behaviour (although still wouldn't have produced the output you seem to be expecting).
Also note that these directives are intended to remove multiple slashes from the start of the URL-path only, not elsewhere in the URL-path.
So, you would need to change the RewriteRule directive to read:
RewriteRule ^ http://%{HTTP_HOST}/%1 [R=301,L]
OR, remove the HTTP_HOST server variable altogether (to make the substitution string root-relative):
RewriteRule ^ /%1 [R=301,L]
You will need to clear your browser cache before testing, as the erroneosu 301 (permanent) redirects will be cached persistently by the browser. (Test with 302s to avoid caching issues in the future.)
This Rule worked for me..
RewriteBase /
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+(.*?)/+(/[^\s]+) [NC]
RewriteRule ^ %1%2 [R=302,L,NE]
Thanks To All.

RewriteRule unexpectedly return 301

I'm lost, I spent hours into this simple issue and can't figure what I'm doing wrong here.
This works as expected:
RewriteEngine on
RewriteRule ^([A-Za-z0-9-_.]+)/([A-Za-z0-9-_.]+/)$ index.php?eins=$1&%{QUERY_STRING}&zwei=$2&%{QUERY_STRING} [L]
and rewrites this request: https://domain.tld/asdf/asdf/ internally
to https://domain.tld/index.php?eins=asdf&zwei=asdf
so far so good everything as expected.
But if I add this additional 2nd rule
RewriteEngine on
RewriteRule ^([A-Za-z0-9-_.]+)/([A-Za-z0-9-_.]+/)$ index.php?eins=$1&%{QUERY_STRING}&zwei=$2&%{QUERY_STRING} [L]
RewriteRule ^(.+[^/])$ /$1/ [R=301,L]
Apache responds to the same request https://domain.tld/asdf/asdf/ with 301 to redirect to https://domain.tld/index.php/?eins=asdf&&zwei=asdghi/
I expected The first RewriteRule should be the L = Last one, but why is it redirecting? Actually I would like to achieve a 301 redirect only if a trailing slash is missing.
Check the RewriteRule Flags L|last,
If you are using RewriteRule in either .htaccess files or in
sections, it is important to have some understanding of
how the rules are processed. The simplified form of this is that once
the rules have been processed, the rewritten request is handed back to
the URL parsing engine to do what it may with it. It is possible that
as the rewritten request is handled, the .htaccess file or
section may be encountered again, and thus the ruleset may be run
again from the start. Most commonly this will happen if one of the
rules causes a redirect - either internal or external - causing the
request process to start over.
If you just want to add the trailing slash only for directory, you could try these rules:
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} !(.+)/$
RewriteRule ^(.*) $1/ [L,R=301]

Moving from IIS ISAPI rewrite to Apache mod_rewrite

I've seen few people have asked this on here already, but none of the solutions provided worked for me so far.
We have always been developing for the IIS ISAPI rewrite (on Windows) and suddenly one of the clients decided to place the project on the Linux server running Apache. As a result some of the rules are no longer working.
Example of an ISAPI rewrite rule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^login/?([^/]*)([^/]*)$ /login.cfm?msg=$1&$2 [L,QSA]
RewriteRule ^login.cfm$ /login/ [R=301,L,NC]
login.cfm is an actual existing page and not dynamically generated based on template.
Could someone help me how to translate this for the Apache mod_rewrite please? Currently the rule creates an infinitive loop and the output is:
login/?msg=&&msg=&&msg=&&msg=&&msg=&&msg... (till the limit of the url length)
Safe to say the page is not found either so it doesn't even check whether the file with such name exists.
The page could be /login or /login/wrong so the rule should recognize both cases.
You can use these rules in your site root .htaccess:
RewriteEngine On
# external redirect from actual URL to pretty one
RewriteCond %{THE_REQUEST} /login\.cfm\?msg=([^\s&]*)\s [NC]
RewriteRule ^ /login/%1? [R=301,L,NE]
# internal forward from pretty URL to actual one
RewriteRule ^login(?:/([\w-]+))?/?$ login.cfm?msg=$1 [L,QSA,NC]

apache RewriteRule not working

I have this url http://www.example.com/Courses/get/38789/my-course, i added this rule to the .htaccess file
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/Courses/get
RewriteRule ^Courses/get/(.*)/(.*)$ course-$1-$2 [R=301,L]
but when i go to http://www.example.com/Courses/get/38789/my-course nothing happens, i stay on the same page, there is no redirect.
p.s the link is just an example not the actual link
A more efficient method would be to use the following:
RewriteRule ^Courses/get/(\d+)/([^/]+)/?$ /course-$1-$2 [R=301,L]
Now, keep in mind that this rule should come before any rules that may rewrite the request to, say, an index.php file. This would be naturally true if the code you posted in your question was all of your code. If not, please post your entire .htaccess file so we can be sure it is being placed in the right location.
Be sure the mod_rewrite is turned on, and the you have set AllowOverride All in your virtual host/Apache site configuration. If you're running on a shared production server, this would not apply to you.
Side note: Whilst it does work, you need not use RewriteEngine on twice - only once at the beginning of your file will suffice. You also do not need RewriteCond %{REQUEST_URI} ^/Courses/get - it is essentially redundant as you are already using an expression to test against the request.