Rewrite rule for specific name/value to take precedence over others - regex

I have two rewrite rules:
RewriteRule ^([^/]+)/([^/]+)/?$ /?action=viewCategoryName&categoryName=$1&page_identifier=$2 [L,QSA,B]
and
RewriteRule ^([^/]+)/?$ /?action=viewHomepageName&page_identifier=$1 [L,QSA,B]
I would like to create a new rule to rewrite:
/?action=archive&categoryId=$1
to
/archive/news
Where 'news' is the category Id, or $1.
With the two rules mentioned above, is this possible? I would imagine I need to place it above the other rules, and specify specifically if example.com/archive/ rewrite and then stop the rewrite.

You can have your rules like this in root .htaccess
RewriteEngine On
# don't process further rules for real files and directories
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
RewriteRule ^(archive)/([^/]+)/?$ /?action=$1&categoryId=$2 [L,QSA,NC]
RewriteRule ^([^/]+)/([^/]+)/?$ /?action=viewCategoryName&categoryName=$1&page_identifier=$2 [L,QSA,B]
RewriteRule ^([^/]+)/?$ /?action=viewHomepageName&page_identifier=$1 [L,QSA,B]

Related

.htaccess case-insensitive directories

I access to the file.php writing mydomain.com/file. I need to be able to access also writing mydomain.com/FILE.
In .htaccess I use the following rules to remove extension:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.+?)/?$ /$1.php [L]
# redirect to .php-less link if requested directly
RewriteCond %{THE_REQUEST} ^[A-Z]+\s.+\.php\sHTTP/.+
RewriteRule ^(.+)\.php $1 [R=301,L]
If this rules should be changed- it's up to you.
Define this RewriteMap in Apache or vhost config:
RewriteMap lc int:tolower
Then inside your .htaccess have an additional rule to lowercase all uppercase URIs:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301,NE]
# redirect to .php-less link if requested directly
RewriteCond %{THE_REQUEST} ^[A-Z]+\s.+\.php\sHTTP [NC]
RewriteRule ^(.+)\.php$ /$1 [R=301,L,NC,NE]
# convert each REQUEST_URI to lowercase
RewriteRule ^(.*?[A-Z]+.*)$ /${lc:$1} [R=301,L,NE]
# internally add .php
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
Use [NC] flag in your rules
Use of the [NC] flag causes the RewriteRule to be matched in a
case-insensitive manner. That is, it doesn't care whether letters
appear as upper-case or lower-case in the matched URI.
https://httpd.apache.org/docs/current/rewrite/flags.html
You need to take care of two aspects: first the case insensitive matching and second the case conversion to lowercase.
Apache's rewriting module provides the NC flag for the first aspect and a somewhat more complex approach to the second one:
RewriteEngine On
# remove trailing slash (/) if no such folder exists
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /${lc:$1} [NC,L,R=301]
# internally rewrite to a php script if it exists and convert to lower case
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ /${lc:$1}.php [NC,L]
# redirect to .php-less link if requested directly
RewriteRule ^(.+)\.php$ ${lc:$1} [NC,L,R=301]
I have the impression though that your original set of rewriting rules does not really achieve what you attempt to, that is it syntactically invalid even. That is why I changed a few aspects.

mod-rewrite when index.php is in the URL

I wish to rewrite http://example.com/admin/pages/index.php to http://example.com/index.php?admin=admin&cid=pages.
It works for http://example.com/admin/pages (which I also want), but not for http://example.com/admin/pages/index.php.
How is this accomplished?
RewriteEngine On
RewriteBase /
# If the request is for a valid directory, file, or link, don't do anything
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^ - [L]
#remove the trailing slash
RewriteRule (.+)/$ $1
# If you add this first rule to support views, be sure to remove the QSA flag from the second rule (maybe not required since the first rule has the L flag)
#replace admin/cid with index.php?admin=admin&cid=cid
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?admin=$1&cid=$2 [L,QSA]
#replace mypage with index.php?admin=mypage
RewriteRule ^([^/]+)/?$ index.php?admin=$1 [L,QSA]
EDIT
Random changes shows that this might be correct.
RewriteRule ^([^/]+)/([^/]+)/index.php/?$ index.php?admin=$1&cid=$2 [L,QSA]
RewriteRule ^([^/]+)/([^/]+)/?$ index.php?admin=$1&cid=$2 [L,QSA]
#replace mypage with index.php?admin=mypage
RewriteRule ^([^/]+)/index.php/?$ index.php?admin=$1 [L,QSA]
RewriteRule ^([^/]+)/?$ index.php?admin=$1 [L,QSA]
Problem is your first rule that is skipping all files & directories from rules.
Replace your rules with this:
RewriteEngine On
RewriteRule ^index\.php$ - [L,NC]
#remove the trailing slash
RewriteRule (.+)/$ $1 [L,R=302]
# If you add this first rule to support views, be sure to remove the QSA flag from the second rule (maybe not required since the first rule has the L flag)
#replace admin/cid with index.php?admin=admin&cid=cid
RewriteRule ^([^/]+)/([^/]+)(?:/?|/index\.php)$ index.php?admin=$1&cid=$2 [L,QSA]
#replace mypage with index.php?admin=mypage
RewriteRule ^([^/.]+)/?$ index.php?admin=$1 [L,QSA]

htaccess redirect based on directories and subdirectories

i have a special situation and i can't find a good solution. I've already seen dozens of questions/answers here but none of them seems to solve my problem!
I have an url like this:
https://subdomain.domain.com/{user-name}/{app-name}/
"user-name" and "app-name" can change everytime and i need to redirect it to
index.php?u={user-name}&a={app-name}
But if the url is only https://subdomain.domain.com/{user-name}/ i need to redirect it to
store-list.php?u={user-name} (to show a list of all available apps for that user).
My .htaccess is currently like this:
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ /store-list.php?u=$1 [L]
RewriteRule ^([^/]+)/([^/]+)/?$ /index.php?u=$1&a=$2 [L]
It redirects perfectly on both situations but every call to a "real" file doesn't work (for example a call to a js or css file inside my html).
What am i doing wrong??
Making one RewriteCond Set Apply to Several Rules
Yes, we're really close... but a RewriteCond only applies to one rule. That's what is throwing us off. Let's use some tricky logic and put the conditions in reverse:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L,S=2]
RewriteRule ^([^/]+)/?$ /store-list.php?u=$1 [L]
RewriteRule ^([^/]+)/([^/]+)/?$ /index.php?u=$1&a=$2 [L]
The conditions say that if the files do exist, leave them unchanged, and to skip the two next rules (S=2).

Conditionally redirecting directory structure URL to html file

My goal is to redirect any url such as http://mydomain.com/somename to http://mydomain.com/somename.html except for http://mydomain.com/name1 and http://mydomain.com/name2 For these two, I wish to redirect them to http://mydomain.com/main.php?g1=name1 (or name2, etc). If these later two have two or three more directories in the URL (i.e. http://mydomain.com/name1/val2/val3), I wish to add them as individual GET values such as http://mydomain.com/main.php?g1=name1&g2=val2&g3=val3. I would like the browser to keep showing the directory path, and not something like http://mydomain.com/somename.html.
Below is my unsuccessful attempt. How can I accomplish this? Thank you
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
## If the request is for a valid directory, file, or link, don't do anything
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^ - [L]
RewriteCond %{REQUEST_URI} !^/name1 [OR] RewriteCond %{REQUEST_URI} !^/name2
RewriteRule ^(.*)$ $1.html [L]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ ?p=$1&c=$2&v=$3 [L,QSA]
RewriteRule ^([^/]+)/([^/]+)/?$ p=$1&c=$2 [L,QSA]
RewriteRule ^([^/]+)/?$ ?p=$1 [L,QSA]
</IfModule>
You have the right idea in most places, but you need to change the order of your rules to match more specific stuff before less specific stuff. Generally, I'm allowing a trailing / in the rules below via /?. Remove that from the end if you won't permit a trailing / to be matched.
RewriteEngine on
RewriteBase /
# This should be fine as you have it....
## If the request is for a valid directory, file, or link, don't do anything
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^ - [L]
# Reverse your rule order here.
# First match name1|name2 with an optional trailing /
# but nothing else following...
RewriteRule ^(name1|name2)/?$ main.php?g1=$1 [L,QSA]
# Two additional dirs
RewriteRule ^(name1|name2)/([^/]+)/([^/]+)/?$ main.php?g1=$1&g2=$2&g3=$3 [L,QSA]
# Three additional dirs
RewriteRule ^(name1|name2)/([^/]+)/([^/]+)/([^/]+)/?$ main.php?g1=$1&g2=$2&g3=$3&g4=$4 [L,QSA]
# Last, do the generic rule to rewrite to .html
# using [^.]+ to match anything not including a .
# You could be more specific with something like [a-z]+ if that
# corresponds to your expected input
RewriteRule ^([^.]+)$ $1.html [L,QSA]
If you wanted to check that the URI is not name1, name2 in a condition, use an [AND] which is implicit:
RewriteCond %{REQUEST_URI} !/name1
RewriteCond %{REQUEST_URI} !/name2
RewriteRule ^([^.]+)$ $1.html [L,QSA]

Rewrite URL with 1 or more parameters?

I'm strugglening with my .htaccess file in orther to achieve this:
a.com/male-items (OR)
a.com/male-items/popularity -> a.com/index.php?g=m&sort-popularity
a.com/female-items (OR)
a.com/female-items/popularity -> a.com/index.php?g=f&sort=popularity
a.com/male-items/alphabet -> a.com/index.php?g=m&sort=alphabet
a.com/male-items/alphabet/a -> a.com/index.php?g=m&sort=alphabet&l=a
(and same for female)
I know it should be something like
RewriteRule ^a$ a.com/index.php?q=$1
But actually looking into the different mod-rewrite / regex explanations and cheat-sheets doesn't help a lot with getting it to work. The hard part is to understand how do you define the different parametes in the address and then use them in the rewritten url.
(any explanations with your solution would be appretiated)
Use these rules in your DOCUMENT_ROOT/.htaccess file:
RewriteEngine On
RewriteRule ^male-items/?$ /index.php?g=m&sort=popularity [L,QSA]
RewriteRule ^male-items/([^/]+)/?$ /index.php?g=m&sort=$2 [L,QSA]
RewriteRule ^male-items/([^/]+)/([^/]+)/?$ /index.php?g=m&sort=$2&l=$3 [L,QSA]
RewriteRule ^female-items/?$ /index.php?g=f&sort=popularity [L,QSA]
RewriteRule ^female-items/([^/]+)/?$ /index.php?g=f&sort=$2 [L,QSA]
RewriteRule ^female-items/([^/]+)/([^/]+)/?$ /index.php?g=f&sort=$2&l=$3 [L,QSA]
These htaccess lines redirect all nonexisting files/folders to index.php:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
inside index.php you can use: $_SERVER['REQUEST_URI'] to parse your parameters.