URL rewriting with Apache .htaccess with two matches - regex

Sorry about this question - I know this is asked a lot, but this case is a little more distinct (for me at least).
I have the following content in my current .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ index.php?mode=$1 [QSA,L]
This rewrites all URLs that are from index.php and have the mode parameter to a simply URL where the mode's content becomes the main part of the URL, like this:
http://someurl.com/index.php?mode=mymode
Becomes:
http://someurl.com/mymode
This is exactly what I need. But I also need to extend this and be able to achieve the same effect with another file of mine named user.php. The case is almost the same:
http://someurl.com/user.php?action=hello
Becomes:
http://someurl.com/hello
I have no idea how to achieve the second part without conflincting with the first one.
I'm kinda stuck on this one.

Keep your rules like this:
# new rules for /user.php?action=hello
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^user/([^/]+)/?$ user.php?action=$1 [QSA,L]
# existing rule for /index.php?mode=mymode
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ index.php?mode=$1 [QSA,L]
PS: Also better to use absolute path in your css, js, images files rather than arelative one. Which means you have to make sure path of these files start either with http:// or a slash /.

Related

Mod rewrite rule for optional language in URL

I have a shop URL like this
https://domain.eu/cz/lp/9200
And I'm trying to rewrite it in .htaccess to https://domain.eu/lp/index.php?id=$2&lang=$1
I came really close with
RewriteRule ^/?(hr|sk|pl|cz|ro|it)/lp/(\d+)?$ /lp/index.php?id=$2&lang=$1
which works ok but I can't seem to find a way to handle the situation when there is no lang in URL.
So this is also valid: https://domain.eu/lp/9200 but in that case I want $1 to just be empty (or have a default value when it's not present)
I know "?" means "one or zero" times that's why I tried
RewriteRule ^/?[(hr|sk|pl|cz|ro|it)?]/lp/(\d+)?$ /lp/index.php?id=$2&lang=$1
But it doesn't work as expected. Any point in the right direction would be appreciated.
With your shown samples, attempts; please have your htaccess Rules file in following manner. Make sure to clear your browser cache before testing your URLs.
RewriteEngine ON
##Rewrite rule for uris which have only 1 parameter.
RewriteRule ^lp/(\d+)/?$ /lp/index.php?id=$1 [NC,L]
##Rewrite rule for uris which 2 parameters.
RewriteRule ^(hr|sk|pl|cz|ro|it)/lp/(\d+)/?$ /lp/index.php?id=$2&lang=$1 [NC,L]
OR use following solutions, in case uris you are trying to access are non-existent ones. Make sure either use 1st solution OR this one, once at a time only.
RewriteEngine ON
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^lp/(\d+)/?$ /lp/index.php?id=$1 [NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(hr|sk|pl|cz|ro|it)/lp/(\d+)/?$ /lp/index.php?id=$2&lang=$1 [NC,L]

Smarter way to write recursive redirect?

I am sure theres a better way to do this, but cant really figure it out.
Can somebody tell me if theres a better way to write to following Apache .htaccess rewrite rules?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)$ /index.php?param1=$1 [L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/([^/]*)$ /index.php?param1=$1&param2=$2 [L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/([^/]*)/([^/]*)$ /index.php?param1=$1&param2=$2&param3=$3 [L,QSA]
If you just have 3 path segments your current code does not seem that bad. Your current rules are easy to understand, and I don't think the duplicated conditions !-f and !-d will have a huge performance impact.
You can rewrite your current rules to a sequence like this. First you rewrite the url val1/val2/val3/val4/val5 to index.php/val1/val2/val3/val4/val5. Then we have a bunch of similar rules that all take the first path segment and turn it into a parameter. Once no more path segments remain the rest of the rules are ignored.
#Only on requests with at least 1 character (e.g. not to http://localhost)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php%{REQUEST_URI} [QSA]
#Since we don't have the L flag, this will do param1 - paramx in one go
RewriteRule ^index\.php/([^/]+)(/.*)?$ index.php$2?param1=$1 [QSA]
RewriteRule ^index\.php/([^/]+)(/.*)?$ index.php$2?param2=$1 [QSA]
RewriteRule ^index\.php/([^/]+)(/.*)?$ index.php$2?param3=$1 [QSA]
RewriteRule ^index\.php/([^/]+)(/.*)?$ index.php$2?param4=$1 [QSA]
RewriteRule ^index\.php/([^/]+)(/.*)?$ index.php$2?param5=$1 [QSA]
Before using this, you should test both the performance of these rules and your current rules to see which one performs better. Please note that this approach yields strange results if more than, in this case, 5 path segments are in the url, as the 6-th until nth path segment will overwrite param1 - param5. You could 'fix' this by adding another rule RewriteRule ^index\.php index.php [END] on recent versions of Apache.

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).

.htaccess URL Rewrite: Point directory name to filename

Sorry if this question already asked here. But I could not found the solution yet.
I have the following .htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ index.php?page=$1 [L]
I want to rewrite the URL from domain.com/index.php?page=contact -To- domain.com/contact
Yes, it worked well. But the problem is when I add a forward slash / like this domain.com/contact/
It displayed Not Found page instead. I think the browser recognized contact/ as a directory but not a file.
I really want the visitor can access to that page by that two ways with forward slash / at the end and without it. How to make this work?
Make trailing slash optional in your regex in as ^([^/]+)/?$:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ index.php?page=$1 [L,QSA]

.htaccess issue, existing .php files and search.php

I'm new to playing with .htaccess for nicely formatted urls and I'm just not sure I'm doing it right.
My current .htaccess file looks like this:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^search/(.*) search.php?query=$1 [L]
RewriteRule !\.(gif|jpg|ico|css|js|txt|xml|png|swf)$ index.php
What I want is for mysite.com/home/56/page-title to go to index.php where I filter out the number and load the correct index page, which works fine.
Before that, I want to check if the url is pointing at search.php, and if so redirect to mysite.com/search/the-search-term, this also works fine.
What isn't working is if I try to visit a specific .php file say mysite.com/control_panel.php - it just takes me to index.php, but I thought that the following line stopped that from happening?
RewriteCond %{REQUEST_FILENAME} !-f
If someone could explain it to me that would be great :)
Thanks!
1. Order of rules matters
2. RewriteCond directives will only be applied to the ONE RewriteRule that follows it. If you need to apply the same conditions to multiple rules you have to write them multiple times or change the rewrite processing logic (multiple approaches available).
Try this one:
RewriteEngine On
RewriteRule ^search/(.*) search.php?query=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(gif|jpg|ico|css|js|txt|xml|png|swf)$ index.php [L]