Redirection of URLs with non-latin characters - .htaccess

I'm having trouble with what seems like a simple redirects, but the separate online tests I've done show interesting results.
URL 1 to redirect:
https://example.com/bg/%D0%B0%D0%B2%D1%82%D0%BE%D1%80/author-name
Note: %D0%B0%D0%B2%D1%82%D0%BE%D1%80 is author (автор) in Bulgarian language.
Rewrite rule:
RewriteRule ^bg/%D0%B0%D0%B2%D1%82%D0%BE%D1%80/(.*)$ https://example.com/bg/author/$1 [L,R=301]
Redirects to:
https://example.com/bg/автор/author-name
Instead, I want it to redirect to:
https://example.com/bg/author/author-name
Test online:
https://htaccess.madewithlove.com?share=98002622-055d-4656-9100-32bc297a42c8
URL 2 to redirect:
https://example.com/bg/%25D0%25B0%25D0%25B2%25D1%2582%25D0%25BE%25D1%2580/author-name
Note: %D0%B0%D0%B2%D1%82%D0%BE%D1%80 is probably also author (автор) in Bulgarian language.
Rewrite rule:
RewriteRule ^bg/%25D0%25B0%25D0%25B2%25D1%2582%25D0%25BE%25D1%2580/(.*)$ https://example.com/bg/author/$1 [L,R=301]
Redirects to:
https://example.com/bg/%D0%B0%D0%B2%D1%82%D0%BE%D1%80/author-name
I want it to redirect to:
https://example.com/bg/author/author-name
Test online:
https://htaccess.madewithlove.com?share=66fdb0d9-f5bb-45a7-a60c-24accb924410
I tried to separate URL 1/URL 2 and their rewrite rules in two online tests to be easier to understand, (I will need both URLs to redirect on production site).
All I can see is that part of URL in rewrite rule from first example appears in output URL in second example, even if used in separate tests, like I did.
It looks like there is some redirection I am not aware of (higher power) witch redirects between:
%D0%B0%D0%B2%D1%82%D0%BE%D1%80
автор
%25D0%25B0%25D0%25B2%25D1%2582%25D0%25BE%25D1%2580
Can anyone fix my redirect rules, if there is anything wrong with them?

Problem is in URL decoding.
When /%25D0%25B0%25D0%25B2%25D1%2582%25D0%25BE%25D1%2580/ is decoded it becomes /%D0%B0%D0%B2%D1%82%D0%BE%D1%80/, which is also decoded and finally becomes /автор/.
URL redirection rule is needed for each case (to achieve successful redirection without redirect chains):
RewriteRule ^bg/%25D0%25B0%25D0%25B2%25D1%2582%25D0%25BE%25D1%2580/(.*)$ https://example.com/bg/author/$1 [L,R=301]
RewriteRule ^bg/%D0%B0%D0%B2%D1%82%D0%BE%D1%80/(.*)$ https://example.com/bg/author/$1 [L,R=301]
RewriteRule ^bg/автор/(.*)$ https://example.com/bg/author/$1 [L,R=301]

Related

.htaccess rewrite conflicting rules

I'm having an issue with some htaccess rules which I thought would be simple. I have some nice SEO friendly URL rewriting in place as below
RewriteEngine On
RewriteCond %{REQUEST_URI} !^(index\.php|/images|/templates|/views|/ajax|/uploads|/robots\.txt|/sitemap\.xml|/favicon\.ico|/scripts|/cron|/combine.php|/js|/css)
RewriteRule ^(.*)$ index.php?ref=$1&%{QUERY_STRING} [L]
This all works well and I want to keep this. I also wish to rewrite some old pages which Google WMT is reporting as 404's to the new equivalent and for that I'd like to use:
Redirect 301 /about_us http://example.com/about-us
The problem I have is that the URL that the browser is directed to is:
http://example.com/about-us?ref=about_us
The about_us is the old link and about-us is the correct link. If the htaccess redirected to example.com/about-us then the other SEO friendly rewrite rule will pick it up and show the page but eh extra ?ref= parameter is confusing it. I am guessing the two rules are conflicting to a degree but is there a way to get the two rules to work together e.g. redirect without the extra ?ref= parameter? My knowledge of htaccess is basic to say the least so I am a little stuck on this one.
Thanks in advance
Redirect and RedirectMatch are part of mod_alias, while the rewrite rules are part of mod_rewrite. The problem you're running into is when you mix the two, both modules affect the same request, thus two things happen when you only want one. In this case, you need to stick with just mod_rewrite and use this instead:
RewriteEngine On
RewriteRule ^about_us /about-us [L,R=301]
RewriteCond %{REQUEST_URI} !^(index\.php|/images|/templates|/views|/ajax|/uploads|/robots\.txt|/sitemap\.xml|/favicon\.ico|/scripts|/cron|/combine.php|/js|/css)
RewriteRule ^(.*)$ index.php?ref=$1&%{QUERY_STRING} [L]
Note that the rule that redirects comes before the rule that routes to index.php.

prefix a friendly url using mod rewrite in htaccess

Is it possible to prefix a htaccess rewrite rule
for example can a variable be used as a prefix to a url
website.com/$variable-for-sale/
/cupcakes-for-sale/
/pies-for-sale/
/flans-for-sale/
The idea is to then use that variable to display all the cupcakes/pies/flans for sale
How would this be written as a rewrite rule? Is it even possible?
Thanks
The first rule will take care of redirecting your ugly URL to Friendly like one.
The second rule will internally redirect it back so the browser URL remains the friendly URL while service the content of your page.
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
# Redirect /?cake=anything to /anything-for-sale/
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+\?cake=([^&\s]+) [NC]
RewriteRule ^ /%1-for-sale/? [R=302,L]
# Internally forward /anything-for-sale/ to /?cake=anything
RewriteRule ^([^-]+)-for-sale/?$ /?cake=$1 [NC,L]
Keep in mind I am using R=302 its always better to use 302 which means temporary redirect while testing a new rule before making it permanent as the permanent will cache the information to your browser. Once the rule is confirmed to be working as expected change R=302 to R=301.
To extract variable, you need to use regex parentheses in the correct pattern, then you can use $1 to fetch the group:
RewriteRule ^([^-]+)-for-sale/$ /target.php?variable=$1 [L]
The "target" part is the script you use to display the "variable". Since your question doesn't mention what that is, you have to figure it out.

I changed the structure of my site to reach index cards

Excuse me for my english.
I make a brands directory web site.
Before to acces to the brands pages I use requests like this :
mydomain.com/fiche.php?id=115
where id is the id of the brand in my directory
I change the structure of the brands pages and now use this request:
mydomain.com/annuaire.php?type=fiche&id_marq=115
where id has become id_marq
I try to use a rewritebrule like this:
RewriteRule ^fiche.php$ http://www.annuaire-sites-officiels.com/annuaire.php?detail=fiche&id_marq=$1 [L,QSA,R=301]
to redirect the old links to the new pages but result dont pass the id_marq value and the url is:
http://www.annuaire-sites-officiels.com/annuaire.php?detail=fiche&id_marq=&id=115
&id= is too.
What am I doing wrong?
Your rule is not evaluating query string and that's why its not capturing id query parameter.
Change your code to:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} ^id=([^&]+) [NC]
RewriteRule ^fiche\.php$ /annuaire.php?detail=fiche&id_marq=%1 [R=302,L,QSA,NC]
Once you verify it is working fine, replace R=302 to R=301. Avoid using R=301 (Permanent Redirect) while testing your mod_rewrite rules.
Check out Regex Back Reference Availability:
You have to capture the query string. [QSA] passes it forward unaltered, so unless you're using id for anything you don't need that bit of code. Your 301 redirect is correct since this is a permanent redirect. Remember if you add a failed redirect your browser may cache that redirect so it might not look like it's working.
In this string match I'm only catching numbers to prevent someone from passing something like an asterisk * and XSS exploiting your site.
I've not included and [NC] matches in my code because when you allow multiple cases they can seem like different URLs to search engines (bad for SEO).
RewriteCond %{QUERY_STRING} id=([0-9]+)
RewriteRule ^fiche.php$ http://%{HTTP_HOST}/annuaire.php?detail=fiche&id_marq=%1 [R=301,L]

trouble with simple mod_rewrite redirect rule

I have mod_rewrite working in a development environment.
This testing domain is using these rules in an .htaccess file:
Options +FollowSymLinks
Options +Indexes
RewriteEngine on
# deal with potential pre-rewrite spidered / bookmarked urls
RewriteRule ^clothes/index.php?pg=([0-9]+)$ /clothes/index$1.php [R=301,L]
# deal with actual urls
RewriteRule ^clothes/[0-9a-z-]+-pr([0-9]+).php$ /clothes/product.php?pid=$1 [L]
The 2nd Rule works fine. Entering http ://testdomain.dev/clothes/shirt-pr32.php is silently delivered content from http ://testdomain.dev/clothes/product.php?pid=32 ...which is as desired and expected!
However, assuming this was applied to a live site, one that had originally used paths such as: http ://testdomain.dev/clothes/product.php?pid=32, I'd like to redirect any incoming requests following the old pattern to the new urls ...which is what the 1st Rule was intended to do.
My problem is my testing server seems to ignore the 1st Rule and serves the page as requested (page loads but address bar remains at http ://testdomain.dev/clothes/product.php?pid=32)
Any assistance or enlightenment would be most graciously accepted!
You need to match the query string within a RewriteCond, then backreference that RewriteCond from the rule. The RewriteRule only matches against the path, not the query string.
Here's a related post I previously answered with a similar request: Mod_rewrite rewrite example.com/page.php?v1=abc&v2=def to example.com/abc/def
You can't match against the query string in a rewrite rule, you need to use the `%{QUERY_STRING} variable in a condition and use the % to backrefernce groupings. So instead of:
RewriteRule ^clothes/index.php?pg=([0-9]+)$ /clothes/index$1.php [R=301,L]
You'll need:
RewriteCond %{QUERY_STRING} ^pg=([0-9]+)
RewriteRule ^clothes/index.php$ /clothes/index%1.php? [R=301,L]

htaccess redirect with dynamic variables conflict

I'm working in an old CMS that uses htaccess to rewrite URIs with GET variables into something more user friendly.
RewriteEngine on
RewriteRule ^animals/(.*)/ secondary.php?page=$1
RewriteRule ^animals/(.*) secondary.php?page=$1
which results (correctly) in
http://www.example.com/animals/duck
The problem is I now need to redirect some of those pages to new pages. I've tried:
Redirect 301 /animals/goose http://www.example.com/animals/fowl
The redirect almost works, but it adds "?page=goose" to the end of the rewritten URI:
http://www.example.com/animals/fowl?page=goose
I've tried using RewriteRule as well as RewriteCond, but unfortunatley I'm having no luck. Any help would be immensely appreciated.
Try placing this before the other rules instead of the Redirect statement. R=301 is for the redirect and L signals that the rule in question is the last rule to be processed.
RewriteRule ^animals/goose /animals/fowl [R=301,L]
Also you can easily make the slash (just like any other character) optional with a question mark, instead of having two rules.
RewriteRule ^animals/(.*)/?$ secondary.php?page=$1

Resources