Remove extension but preserve parameter - .htaccess

I have been wondering, how to remove the extension but preserve the parameters of an url? For example: search.php?q=test becomes /search?q=test.
I have tried the following, but it removes the entire search.php from the url:
RewriteCond %{THE_REQUEST} /([^.]+)\.php [NC]
RewriteCond %{REQUEST_FILENAME} search
RewriteRule ^ %1/ [NC,L,R]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} search
RewriteRule ^([^/]+)/?$ $1.php [NC,L]
Thank you in advance!

To remove an extension, you typically check if the requested filename (with extension) exists, and then rewrite
RewriteCond %{REQUEST_FILENAME}.ext -f
RewriteRule ^ %{REQUEST_FILENAME}.ext [L]
The rule above is a generic approach, working for any file ending in .ext.
If you want to rewrite just one fixed file, you can do so by naming the relevant file explicitly, e.g.
RewriteRule ^search$ /search.php [L]
mod_rewrite preserves a query string by default, as long as you don't add your own
Modifying the Query String
By default, the query string is passed through unchanged. You can, however, create URLs in the substitution string containing a query string part. Simply use a question mark inside the substitution string to indicate that the following text should be re-injected into the query string. When you want to erase an existing query string, end the substitution string with just a question mark. To combine new and old query strings, use the [QSA] flag.

Related

Problem with .htaccess accessing variable in method in PHP with forward slash

I'm having a problem accessing a variable.
My method is requested this way:
http://example.com/method/parameter
I have a specific .htaccess file that manages that:
<ifmodule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ index.php?categoryId=$1 [QSA,L]
</ifmodule>
This enables the $categoryId variable to be passed by a forward slash.
Here is the deal, I'm trying to pass another variable adding another forward slash. The complete request would be something like this:
http://example.com/method/parameter/orderby
I've tried changing the .htaccess file to:
<ifmodule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ index.php?categoryId=$1?orderBy=$2 [QSA,L]
</ifmodule>
There was no change. Am I missing something?
What you need to do to capture multiple query string parameters in the $_GET array in index.php is change your RewriteRule to the following:
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ index.php?method=$1&param=$2&orderby=$3 [L,QSA]
I've used method, param and orderby as you indicated in the question.
Just repeat the pattern ([^/]+)/ for each query string parameter you want to add, and reference them respectively with $1, $2, $3 etc.
Note: in your original RewriteRule you did not format the query string properly, you need to use & between the parameters, not ?(the question mark is used as a separator, and is not part of the query string.).
The above solution requires three parameters, if however you wanted to make the parameters optional, you can use ? in the pattern, as follows:
RewriteRule ^([^/]+)?/?([^/]+)?/?([^/]+)?/?$ index.php?categoryId=$1&orderBy=$2&something=$3 [L,QSA]
A question mark makes a preceding token in the regular expression optional.

RewriteRule returns not found if url/word is lowercase

I Rewrite a url via htaccess but if I write it with lowercase or not exactly us it is inside the RewriteRule won't work, returns that the file or object not found. Example if I write go to url ACTIVATE/TheTokenKey returns not found. Is there anything that will read the url to lowercase, So if we write AcTivAtE will read it as activate.
RewriteBase /
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^Activation/(.*)$ ?tab=activation&token=$1 [L]
Use the [NC] flag on your rule
RewriteRule ^Activation/(.*)$ ?tab=activation&token=$1 [NC,L]
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

Reference capture groups of multiple RewriteCond in RewriteRule

When I have multiple RewriteCond chained together, only the capture groups of the last RewriteCond can be referenced with %0-%9.
In the following problem the parameters in the query string of the url can be in any order. To parse them into a fancy url I would need to match each parameter in the query string individually:
RewriteCond %{QUERY_STRING} param1=([^&]+)
RewriteCond %{QUERY_STRING} param2=([^&]+)
RewriteCond %{QUERY_STRING} param3=([^&]+)
RewriteRule ^foo$ bar/%1/%2/%3/ [R]
Like I pointed out... this doesn't work. To fix this, I could reference the capture group of the previous RewriteCond in the next RewriteCond and 'propagate' each parameter to the actual RewriteRule:
RewriteCond %{QUERY_STRING} param1=([^&]+)
RewriteCond %1&%{QUERY_STRING} ^([^&]*)&.*param2=([^&]+)
RewriteCond %1&%2&%{QUERY_STRING} ^([^&]*)&([^&]*)&.*param3=([^&]+)
RewriteRule ^foo$ bar/%1/%2/%3/ [R]
This should work, but for each additional parameter it get's messier. An other solution could possibly be parsing one parameter and redirecting the client after each parameter (resulting in a lengthy chain of redirects, which I would like to avoid).
Is there an cleaner way of accessing the capture groups of all RewriteCond's in the RewriteRule (e.g. is it possible to name them or assign them to a variable so I can reference them somewhere else?)
You could try constructing the target URL inside the rewrite conditions:
RewriteCond ##%{QUERY_STRING} (.*)##(|.*&)param1=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param2=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param3=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param4=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param5=([^&]+)
RewriteCond %1/%3##%{QUERY_STRING} (.*)##(|.*&)param6=([^&]+)
RewriteRule ^foo$ /bar%1/%3? [L,R]
When I try to request:
/foo?param1=a&param2=b&param6=3&param3=4&param5=5&param4=6
I get redirected to:
/bar/a/b/4/6/5/3
Adding any additional required query string parameters won't make it look any more messy than it already is.
After experimenting some more, it would be possible to parse all parameters as environment variables and use them like that. I doubt it is very efficient though and I think any use-case that would need such a construction would be better of using a php page router. For fancy url's Jon Lin's solution would probably work better. It does however sort-of mimic what I had in mind.
I'll, however, put the code in here for demonstration:
#Parse all query key-value pairs to an environment variable with the q- prefix
RewriteCond %{QUERY_STRING} ^([^=]*)=([^&]*)(&(.*)|$)$
RewriteRule ^(.*)$ $1?%4 [E=q-%1:%2,N]
#If 'param1' existed in the query string...
RewriteCond %{ENV:q-param1} !^$
RewriteRule ^foo$ bar/%{ENV:q-param1} [END]
or even...
#Keep the original query string
RewriteCond %{ENV:qstring} ^$
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule .* - [E=qstring:#%1]
#parse the query parameters to environment variables
RewriteCond %{ENV:qstring} ^#([^=]*)=([^&]*)(&(.*)|$)$
RewriteRule ^(.*)$ - [E=q-%1:%2,E=qstring:#%4,N]
#See that the original query string is still intact
RewriteCond %{ENV:q-param1} !^$
RewriteRule ^foo$ bar/%{ENV:q-param1} [QSA]

mod_reweite htaccess not work with a point in var

I creating a mod_rewrite rule like this
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME}\.php !-f
RewriteRule ^(.*)$ ./page.php?key=$1
it works! But I want to do this:
www.site.com/var1.var2.var3
(variables are separated by point) separated by - or _ no problems, but if I put the point does not work why?
I assume that you are trying a rule like this
RewriteRule ^(.*).(.*).(.*)$ ./page.php?key=$1&key2=$2&key3=$3
but you should remember to escape the dots which you want to interpret as periods. There are many ways to right this but here is a simple way if you are new to .htaccess files:
RewriteEngine On
RewriteBase /
# Skip existing files or directories
RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule ^ - [L]
# Add default PHP extension when appropriate
RewriteCond %{SCRIPT_FILENAME}.php -f
RewriteRule ^.* $0.php [L]
# Pick up 1,2 and 3 parameter versions
RewriteRule ^(.*?)\.^(.*?)\.(.*)$ page.php?key=$1&key2=$2&key3=$3 [QSA,L]
RewriteRule ^(.*?)\.(.*?)$ page.php?key=$11&key2=$2 [QSA,L]
RewriteRule ^(.*?)\.$ page.php?key=$1 [QSA,L]
Note:
the first rule uses "^" as a pattern which always matches and the "-" means don't replace it.
the second uses $0 which means the entire match pattern
rule 3-5 match the 3,2,1 parameter options
the [L] (last) flag means skip the rest of the rules
you will need the QSA flag is you use other parameters.
The reason for splitting the existance check in to is that you need to handle files such as CSS and image (PNG/GIF/PNG) files as well as your application syntax.

.htaccess rewrite rule to map a specific query string to a controller

Trying to crack this following;
/any/segment/?zone=116&n-value=a128c471
.. to map into a controller /controller/ads.php, but to make sure ads.php REQUEST_URI and QUERY_STRING remains the same (no redirects).
Given from following of course;
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !((.*)\.(.*))$
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ /$1/?%{QUERY_STRING} [NC,L,R=301]
I would appreciate any advice.
The URL will fail your third condition. mod_rewrite ignores the query string; it will see a slash at the end of the URL.
It's unnecessary to manually add the (verbatim) query string to the end.
You need to change the replacement string used by your rewrite rule and remove the R=301 flag. Depending on what URLs are in use in your site, you might need a more specific regex on the left hand side (or another condition) to exclude the URLs you do not want to rewrite.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !((.*)\.(.*))$
RewriteRule ^(.*)$ /controller/ads.php [NC,L]

Resources