Rewrite partial URL to specific page with .htaccess mod_rewrite - apache

Couldn't really figure out a title for this, so it's not the best, sorry.
I'm looking to rewrite URLs like this:
https://awesomechristianmusic.com/song-list?artist=dc-talk
To look like this:
https://awesomechristianmusic.com/dc-talk
Or for genres/topics:
https://awesomechristianmusic.com/song-list?genre=rock
https://awesomechristianmusic.com/song-list?topic=forgiveness
To look like this:
https://awesomechristianmusic.com/genre/rock
https://awesomechristianmusic.com/topic/forgiveness
Unfortunately, there seem to be some issues with my .htaccess file and I can't figure it out. Here's what I'm working with:
RewriteEngine on
RewriteBase /
# Force HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,QSA,R=301]
# Remove www.
RewriteCond %{HTTP_HOST} ^www\.(.*)$
RewriteRule ^(.*)$ https://%1/$1 [R=301,L,QSA]
# Remove trailing slashes
RewriteCond %{REQUEST_URI} ^.*/$
RewriteRule ^(.*)/$ https://%{HTTP_HOST}/$1 [R=301,L,QSA]
# This is where I'm currently working
RewriteRule ^/([^/]+)$ /song-list?artist=$1 [NC,L,QSA]
RewriteRule ^/genre/([^/]+)$ /song-list?genre=$1 [NC,L,QSA]
RewriteRule ^/topic/([^/]+)$ /song-list?topic=$1 [NC,L,QSA]
# Redirect everything through index.php
RewriteCond %{REQUEST_URI} !(/(api|edit)/?.*) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [NC,L,QSA]
# long list of 301 redirects
Currently, the three rewrites I'm working on don't do anything. If I remove the slashes at the beginning of their regexes, I get a 500 Internal Server Error. Any ideas what might be going wrong or how to fix it?

Swap out these three rules:
# This is where I'm currently working
RewriteRule ^/([^/]+)$ /song-list?artist=$1 [NC,L,QSA]
RewriteRule ^/genre/([^/]+)$ /song-list?genre=$1 [NC,L,QSA]
RewriteRule ^/topic/([^/]+)$ /song-list?topic=$1 [NC,L,QSA]
To these three rules:
# If not /genre/* and not /topic/*
# Convert /dc-talk to /song-list?artist=dc-talk
RewriteCond %{REQUEST_URI} !^/genre/(.*)$ [NC]
RewriteCond %{REQUEST_URI} !^/topic/(.*)$ [NC]
RewriteRule ^(.*)$ song-list?artist=$1 [NC,L,QSA]
# Convert /genre/rock to /song-list?genre=rock
RewriteRule ^genre/(.*)$ song-list?genre=$1 [NC,L,QSA]
# Convert /topic/forgivenessto /song-list?topic=forgiveness
RewriteRule ^topic/(.*)$ song-list?topic=$1 [NC,L,QSA]
You can view these rules in action here: https://htaccess.madewithlove.be/?share=763f7107-f056-5ebe-ae0a-7f53a17b225a

Related

.htaccess rewrite subfolders to remove /index

I have some htaccess rules which rewrite friendly URLs. Everything is working apart from one thing.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R] # <- for test, for prod use [L,R=301]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.html [NC]
RewriteRule ^ %1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.*?)/?$ $1.html [NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . / [L,R=301]
This is a site with language subfolders, e.g.:
/fr/about.html
/en/about.html
With the above htaccess rules these urls come out like:
/fr/about
/en/about
However this also means my index pages URLs look like:
/fr/index
/en/index
What I would like, is for /index the URL looks like
/fr
/en
Which would mean they respect the trailing slash part of my above htaccess but remove index from the URL.
Any help much appreciated!
Try to add (before RewriteCond %{THE_REQUEST} ^...):
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s(.*?)/index(\.html)?[\s?] [NC]
RewriteRule ^ %1 [R=301,L]

htaccess mod_rewrite - Trailing Slash and loop of redirects

Here is my htaccess code:
RewriteEngine On
RewriteRule ^s/(.*)/(.*) /index.php?search=$1&category=$2 [L,QSA]
RewriteCond %{QUERY_STRING} ^search=([A-Za-z0-9\+]+)$
RewriteRule ^(.*)$ /s/%1/? [R=301,L]
RewriteCond %{QUERY_STRING} ^search=([A-Za-z0-9\+]+)&category=([A-Za-z0-9\+]+)$
RewriteRule ^(.*)$ /s/%1/%2/? [R=301,L]
I need to make a rewrite rule like this:
http://mywebsite.com/s/query+term => http://mywebsite.com/?search=query+term
OR if there is a category
http://mywebsite.com/s/query+term/Category => http://mywebsite.com/?search=query+term&category=Category
I need also to redirect all the old urls to the new one.
With this rules all that I can obtain is to have the search term and category name joined togheter. In a nutshell it is as if I had always:
http://mywebsite.com/?search=query+term/Category
If I remove all the conditions (RewriteCond), leaving only the rewrite rule with the addition of a trailing slash:
RewriteEngine On
RewriteRule ^s/(.*)/(.*)/ /index.php?search=$1&category=$2 [L,QSA]
Reaching the url of my interest in a direct way, the whole thing works. But I will not have the redirect..
So I have tried to set a rule like this:
RewriteEngine On
RewriteRule ^s/(.*)/(.*)/ /index.php?search=$1&category=$2 [L,QSA]
RewriteCond %{QUERY_STRING} ^search=([A-Za-z0-9\+]+)$
RewriteRule ^(.*)$ /s/%1/? [R=301,L]
RewriteCond %{QUERY_STRING} ^search=([A-Za-z0-9\+]+)&category=([A-Za-z0-9\+]+)$
RewriteRule ^(.*)$ /s/%1/%2/? [R=301,L]
But with this rule I get just a loop of redirects.
You can use the following rules :
RewriteEngine on
#1--Redirect from "?search=foobar&cat=cat" to "/s/foobar/cat" --#
RewriteCond %{THE_REQUEST} /\?search=([^&]+)&cat=([^\s]+) [NC]
RewriteRule ^ /s/%1/%/%2? [NC,L,R]
#2--Redirect from "/?search=foobar" to "/s/foobar" --#
RewriteCond %{THE_REQUEST} /\?search=([^/\s]+) [NC]
RewriteRule ^ /s/%1? [NC,L,R]
#1--Rewrite "s/foobar/cat" to "/?search=foobar&cat=cat"--#
RewriteRule ^s/([^/]+)/([^/]+)/?$ /?search=$1&$category=$2 [NC,L]
#2--Rewrite "s/foobar" to "/?search=foobar"--#
RewriteRule ^s/([^/]+)/?$ /?search=$1 [NC,L]

Apache .hatccess rewrites not working for legacy URLS

I'm trying to rewrite some legacy Joomla URLs on a site that's now using ExpressionEngine as its CMS but they're not working.
The ExpressionEngine URL rewrites, i.e. removing index.php from the URL work fine though.
This is what I've got:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !=on
# This is the one that's not working
RewriteRule /index.php?option=com_chronocontact&Itemid=54 /contact/ [R=301,L]
# Force www
RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
RewriteCond %{HTTP_HOST} (.+)$ [NC]
RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]
# Redirect index.php Requests
RewriteCond %{THE_REQUEST} ^[^/]*/index\.php [NC]
RewriteCond %{THE_REQUEST} ^GET
RewriteRule ^index\.php(.+) $1 [R=301,L]
# Standard ExpressionEngine Rewrite
RewriteCond %{REQUEST_URI} ^/
RewriteCond %{QUERY_STRING} ^(gclid=.*)
RewriteRule ^(.+) /index.php?/ [L,PT]
RewriteCond $1 !\.(css|js|gif|jpe?g|png) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^(assets|css|images|tinymce|js|min|cms|themes|index\.php|admin\.php|favicon\.ico|index\.php|path\.php|php\.ini) [NC]
RewriteRule ^(.+) /index.php?/ [L]
</IfModule>
Can anyone spot what I'm doing wrong?
The first thing is the stray RewriteCond %{HTTPS} !=on that you have at the top. It looks like it belongs to the rule under it, as in:
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
RewriteCond %{HTTP_HOST} (.+)$ [NC]
RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L]
As far as the rule that you have commented that doesn't work, the ? is a reserved character for regular expressions, and your pattern actually says that the second p in /index.php is "optional". Additionally, you can't match against the query string in a rewrite rule, you need to use a rewrite condition and match against the %{QUERY_STRING} variable:
RewriteCond %{QUERY_STRING} ^option=com_chronocontact&Itemid=54$
RewriteRule ^(index.php)?$ /contact/? [R=301,L]
is probably more along the lines of what you're looking for.

Redirect not working for complex rewrite rules (.htaccess)

I'm trying to make a redirect from a non-www version of the link to the www one. Its working fine for something like http://mywebsite.com but it fails for a request like http://mywebsite.com/artists/metallica/ or even a complex one. The whole .htaccess file is bellow. Any clues?
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*).html
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://mywebsite.com/$1/ [L,R=301]
RewriteRule ^artists/([^/-]+)-p([^/]+)/$ /artists.php?l=$1&p=$2 [QSA,L]
RewriteRule ^artists/([^/]+)/$ /artists.php?l=$1 [QSA,L]
RewriteRule ^submit/$ /submit.php [QSA,L]
RewriteRule ^users/$ /users.php [QSA,L]
RewriteCond %{THE_REQUEST} ^.*/index.php
RewriteRule ^(.*)index.php$ http://www.mywebsite.com/$1 [R=301,L]
Try this rule:
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
But make sure that you put this rule in front of those rules that just do an internal rewrite. Otherwise an already internally rewritten rule might get redirected externally.

.htaccess rewrite without www AND redirect to subdirectory

I'd like to redirect
www.example.com/* to example.com/*
And at the same time redirect
example.com/* to example.com/forum/*
But I also have /wiki/ and /blog/ and /style/, so I don't want to redirect
example.com/style/* to example.com/forum/style/*
This is what I have at the moment, which is not working quite correctly:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^example\.com$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/forum/
RewriteRule ^(.*)$ forum/$1 [R=301,L]
Clarification: my question can be asked in a simpler way.
I'd like to redirect an empty REQUEST_URI or /, or a non-existent file only if it is in the root directory to /forum/.
Try this:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com
RewriteRule ^(.*)$ http://example.com/$1 [R=301,QSA,L]
RewriteCond %{REQUEST_URI} !^/(wiki|blog|style|forum)
RewriteRule ^(.*)$ http://www.example.com/forum/$1 [R=301,QSA,L]
I would use these rules:
# redirect www.example.com to example.com
RewriteCond %{HTTP_HOST} ^www\.example\.com$
RewriteRule ^ http://example.com%{REQUEST_URI} [L,R=301]
# prefix everything but /forum/, /wiki/, /blog/, /style/ with /forum/ and rediret to it
RewriteRule !^(forum|wiki|blog|style)/ /forum%{REQUEST_URI} [L,R=301]
The second rule could additionally be replaced by this one to check the existence of the first path segment for every request.
# check if first segment of requested URI path is either missing
RewriteCond $0 ^$ [OR]
# or cannot be mapped to an existing directory
RewriteCond %{DOCUMENT_ROOT}$0/ !-d
RewriteRule ^[^/]* /forum%{REQUEST_URI} [L,R=301]
I'd say this should work.
RewriteEngine on
RewriteRule ^forum/(.*)$ forum/$1 [L]
RewriteRule ^wiki/(.*)$ wiki/$1 [L]
RewriteRule ^blog/(.*)$ blog/$1 [L]
RewriteRule ^style/(.*)$ style/$1 [L]
RewriteRule ^(.*)$ forum/$1 [L]
RewriteCond %{HTTP_HOST} ^www.example\.com$
RewriteRule ^(.*)$ http://example.com/$1
I don't have the answer for everything but for your www/no www problem you could try this :
# Enforce www
# If you have subdomains, you can add them to
# the list using the "|" (OR) regex operator
RewriteCond %{HTTP_HOST} !^(www|subdomain) [NC]
RewriteRule ^(.*)$ /exemple/$1 [L,R=301]
# Enforce NO www
RewriteCond %{HTTP_HOST} ^www [NC]
RewriteRule ^(.*)$ http://exemple.com/$1 [L,R=301]