Explain this mod_rewrite rule - regex

Can anyone explain what this mod_rewrite rule is doing?
I'm trying to comment the file, but the code seems to state the opposite of what I think it's doing
# Enable rewriting of URLs
RewriteEngine on
# Allow specified file types to be accessed
# Thing to test = URL
# Condition = not starting with
RewriteCond $1 !^(index\.php|images|css|js|robots\.txt)
# RewriteRule will only be performed if the preceeding RewriteCond is fulfilled
# Remove index.php from all URLs
# Pattern = anything (0 or more of any character)
# Substitution = index.php + the rest of the URL
RewriteRule ^(.*)$ /index.php/$1 [L]

The browser sends a request to the server (Apache, since you're using mod_rewrite):
GET profile/edit
Apache accepts this request and sees in its configuration files that you've configured it to pass all requests through mod_rewrite. So, it sends the string 'profile/edit' to mod_rewrite. Mod_rewrite then applies the rules you specified to it, which then transforms the request (in the way I explained in my previous post) to 'index.php/profile/edit'. After mod_rewrite is done, Apache continues processing the request, and sees 'oh, this guy is requesting the file index.php'. So it calls the php interpreter which then parses and executes index.php - and gets '/profile/edit' as arguments. The php code (CI in your case) parses these arguments and knows how to call the right module in your application.
So basically, it's a way to always call index.php, even when the url doesn't specify index.php. In that way, index.php works as the front controller: it routes all requests to the right location in your application.

^ = begin of line
( = begin group
.* = any character, any number of times
) = end group
The $1 in the second part is replaced by the group in the first part.
Is this a Symfony rule? The idea is to pass the whole query string to the index.php (the front controller) as a parameter, so that the front controller can parse and route it.

If the URL does not start with index.php or images or css or js or robots.txt, the string "/index.php/" is prefixed.
As index.php is probably an executable php app, the index.php then can read the rest of the URL from its cgi environment. (it is stored in ${PATH_INFO})

Related

htaccess redirect starting URL expression to blog page

I want to redirect certain URLs starting with an expression. For ex
I want to redirect:
www.example.com/%2FE (www.example.com/%2FExxxxxxxx) to my blog page in my .htaccess file.
I can redirect www.example.com/2FExxxxx but I am not able to target the %.
The xxxx... I have used in the URL is to represent any expression after %2FE.
This is my code:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule %2FE /blog [R=301,L]
<IfModule>
Can anyone here help me?
By default Apache rejects (with a server generated 404) any URL that contains an encoded slash (%2F) in the URL-path part of the URL. This occurs before the request is processed by .htaccess. (This is considered a security feature.)
To specifically permit encoded slashes, there is the AllowEncodedSlashes directive (default value is Off). But this can only be set in a server or virtualhost context. It cannot be set in .htaccess. To permit encoded slashes, AllowEncodedSlashes can be set to either On or NoDecode (preferable).
For example:
# In a server / virtualhost context (not .htaccess)
AllowEncodedSlashes NoDecode
Then, once the above has been implemented in the server config and the webserver restarted, you can proceed to match the slash using mod_rewrite in .htaccess...
RewriteRule %2FE /blog [R=301,L]
Ordinarily, the RewriteRule pattern matches against the %-decoded URL-path. However, if the NoDecode option has been set then the encoded slash (%2F) is not decoded. So the above "should" work (except that the pattern is not anchored, so potentially matches too much).
But note that multiple (decoded) slashes are reduced in the URL-path that is matched by the RewriteRule pattern. So matching multiple-contiguous slashes here is not possible.
I would instead match against the THE_REQUEST server variable, which is as per the original request and always remains %-encoded (if that is how the request has been made). And multiple slashes are preserved. Note that THE_REQUEST contains the first line of the HTTP request headers, not just the URL-path.
For example:
RewriteEngine On
RewriteCond %{THE_REQUEST} \s/%2FE [NC]
RewriteRule . /blog [R=301,L]
You should not use the <IfModule> wrapper here.

Redirect Query String via .htaccess

I'm trying to redirect the user via the .htaccess file to create friendly URL example:
UI URL: https://example.com/courses/1
htaccess role
RewriteEngine On
RewriteRule ^courses/([0-9]{1})$ /courses.php?page=$1
Output URL: https://example.com/courses.php?page=1
And everything is working fine, Now I need to add other query params to the URL like this http://smart-courses.com/courses/1?p1=1&p2=2 so, I need htaccess to redirect me to https://example.com/courses.php?page=1&p1=1&p2=2
I tried to create a new role to check if p1 and p2 are exists and rewrite the URL
RewriteRule ^courses/([0-9]{1,5})?lid=([0-9]{1,})&did=([0-9]{1,})$ /courses.php?page=$1&p1=$2&p1=$3
Also, I tried to take any chars after ([0-9]{1,5}) (page number) and put it after ?page=1 but it did not worked
RewriteRule ^courses/([0-9]{1})\?(.*)$ /courses.php?page=$1&$2
The query string is not part of the path section of the URL that the rule pattern is matched against. If you'd have to capture something from the query string you need to use a RewritetCond, that is documented. In this case however you don't even need to capture anything:
RewriteEngine On
RewriteRule ^/?courses/(\d)$ /courses.php?page=$1 [QSA]
The QSA flag adds a potential query string to the (rewritten) target URL. The rewriting module takes care to use the correct concatenation here (the & character). Again, this behavior is documented: https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
Take a look yourself: htaccess.madewithlove.com

Redirect the URL from one query string to another

I have spent a great many hours trying to find a solution to this and tried many different approaches but nothing I have tried has worked so far.
I would like to redirect a URL with a query string to another URL that contains the value of that query string.
I want to redirect:
https://example.com/component/search/?searchword=XXXXXXXXX&searchwordsugg=&option=com_search
to
https://example.com/advanced-search?search=XXXXXXXXX
You can do something like the following using mod_rewrite at the top of your root .htaccess file:
RewriteEngine On
RewriteCond %{QUERY_STRING} (?:^|&)searchword=([^&]*)
RewriteRule ^component/search/?$ /advanced-search?search=%1 [NE,R=302,L]
The RewriteRule pattern matches against the URL-path only, which notably excludes the query string. To match against the query string we need a separate condition that checks against the QUERY_STRING server variable.
%1 is a backreference to the first capturing group in the preceding CondPattern, ie. the value of the searchworld URL parameter.
The regex (?:^|&)searchword=([^&]*) matches the searchworld URL parameter anywhere in the query string, not just at the start (as in your example). This also permits an empty value for the URL parameter.
The NE flag is required to prevent the captured URL parameter value being doubly encoded in the response. (Since the QUERY_STRING server variable is not %-decoded.)
The L flag prevents further processing during this pass of the rewrite engine.
Reference:
Apache docs: RewriteRule Directive
Apache docs: RewriteCond Directive

How to set up rewrite rule for a list of keywords in the URL?

What I wish to do
I have a number of URLs I need to redirect, along with a 301 permanent redirect header being sent to browser. I've determined doing this at the htaccess level is most efficient (as opposed to doing it with a function in the Wordpress site this relates to).
The URLs to redirect are:
https://www.mydomain.com.au/search-result/?location=victoria
https://www.mydomain.com.au/search-result/?location=new-south-wales
https://www.mydomain.com.au/search-result/?location=queensland
https://www.mydomain.com.au/search-result/?location=south-australia
https://www.mydomain.com.au/search-result/?location=tasmania
https://www.mydomain.com.au/search-result/?location=northern-territory
Where to redirect to
I want to redirect them to the home page: https://mydomain.com.au/ (I might later choose to redirect them all elsewhere, but I can do that part).
NOTE: The query string should be dropped from the redirect.
I am not sure whether it's best to test for all six of those location= variables, or to simply test for the one location= variable that is not to redirect.
The one location= variable that is not to redirect is ?location=western-australia. E.g.,
https://www.mydomain.com.au/search-result/?location=western-australia
Additional considerations
Note that there are other .../search-result/ URLs that have different variables in the query strings, such as ?weather=... or ?water=.... For example, https://www.mydomain.com.au/search-result/?location=victoria&weather=part-shade&water=&pasture=
As seen in that example, it's also possible multiple variables will be in the query string, such as ?location=tasmania&weather=&water=moderate&pasture=.
So I need to test for the presence of the above listed location= irrespective of whether or not it has other variables after it. The location= variable is always the first in the overall query string.
I am thinking it may be as simple as testing for the presence of /search-result/ AND that followed by victoria | tasmania | northern-territory | etc. in the URL. I can't be 100% sure those words (victoria, etc.) won't show up in any other URLs, hence my reason for only redirecting if those words follow either location= or /search-result/. I suspect location= would be a suitable condition.
I've played around with modifying many rewrite rule examples I've found online, and couldn't get anything to work. I'd either get a 501 error (site crash), or nothing would happen at all.
Thank you.
Not sure if you've tried these, but they worked well for me:
To allow any location values, except western-australia:
# The request path is /search-result/ or maybe /search-result
RewriteCond %{REQUEST_URI} ^/search-result/?$
# ..and the query string 'location' is not empty
RewriteCond %{QUERY_STRING} (^|&)location=.+($|&)
# ..and the value is not 'western-australia'.
RewriteCond %{QUERY_STRING} !(^|&)location=western-australia($|&)
# Redirect to the home page.
RewriteRule . / [R=301,NC,L]
To allow only certain location values:
RewriteCond %{REQUEST_URI} ^/search-result/?$
// Allow only certain location values - (<value>|<value>|...).
RewriteCond %{QUERY_STRING} (^|&)location=(victoria|new-south-wales)($|&)
RewriteRule . / [R=301,NC,L]
And note that, in WordPress, you need to put the above before the WordPress rules:
# This is a sample .htaccess file used on a WordPress site.
# PLACE YOUR CUSTOM RULES HERE.
# BEGIN WordPress
<IfModule mod_rewrite.c>
# ...
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
I.e. Place your rules above the # BEGIN WordPress line, to avoid getting 404 errors.
And btw, I'm no htaccess expert, but hopefully this answer helps you. :)

Using Apache Rewrite Module to do complex Rewriting

I want to use apache rewrite module to do complex rewriting.
For example
If the url is http://www.site.com/wall and http://www.site.com/profile and http://www.site.com/info I want to rewrite into http://www.site.com/gotopage.php?page=wall ,or http://www.site.com/gotopage.php?page=profile and so forth
But if the url is other than that I want to pass it the other way
For example. if the url is http://www.site.com/newthing then it should rewrite as http://www.site.com/index.php?params=newthing
Please Help. I tried to see other questions but did not get it!
RewriteEngine On
# Special rule for 3 unique cases
RewriteRule /(wall|profile|info)$ /gotopage.php?page=$1 [L]
# Only rewrite if the URL has not yet been rewritten
RewriteCond %{HTTP_URL} (?!gotopage\.php|index\.php)
RewriteRule /([^/]+) /index.php?params=$1 [L]
Here's an explanation, line by line:
Any URL that matches one of the 3 specified words gets rewritten to go to gotopage.php.
This line is a condition for the next line. Only if the URL matches this regex will the next line even be considered. The regex checks to ascertain that the request is not already going to gotopage.php or index.php. If it is, we don't want to rewrite anything (we would just end up in an infinite loop).
If the requested URL has no subsequent slashes, rewrite it to go to index.php.