I'm now using this .htaccess file. It only changes the URL from www.example.com/?page=home to www.example.com/home.
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
RewriteRule ^([\w-]+)?$ index.php?page=$1 [L]
RewriteRule ^([\w-]+)/?$ index.php?page=$1 [L]
I want to add more $_GET parameter, for example www.example.com/home/parameter1/value1/.
and preferably that you can do those parameters indefinitely.
You can't do this "indefinitely" using .htaccess alone. You would need to decide on the maximum number (N) of parameters and write a directive for each in order: N, N-1, N-2, ... 1. However, you are also limited by the number of backreferences that are supported. ie. With just $1 to $9, you are limited to 4 parameters, using your method of including the parameter name in the URL path as well.
For example:
# 3 additional parameters
RewriteRule ^([\w-]+)/([\w-]+)/([\w-]+)/([\w-]+)/([\w-]+)/([\w-]+)/([\w-]+)/?$ index.php?page=$1&$2=$3&$4=$5&$6=$7 [L]
# 2 additional parameters
RewriteRule ^([\w-]+)/([\w-]+)/([\w-]+)/([\w-]+)/([\w-]+)/?$ index.php?page=$1&$2=$3&$4=$5 [L]
# 1 additional parameter
RewriteRule ^([\w-]+)/([\w-]+)/([\w-]+)/?$ index.php?page=$1&$2=$3 [L]
# No parameters (just the page)
RewriteRule ^([\w-]+)/?$ index.php?page=$1 [L]
These all allow an optional trailing slash (as in your current example). However, you are better off deciding whether a trailing slash is required or not and choosing one or the other. Having the trailing slash optional simply promotes duplicate content.
This URL pattern is also a bit too "generalised" in my opinion. It is more usual to be specific and avoid including the parameter name in the URL. For example: example.com/home/value1/value2/value2 - the parameter names (param1, param2, etc.) would be hardcoded in the RewriteRule substitution. This would also allow you to have twice as many parameters.
RewriteRule ^([\w-]+)?$ index.php?page=$1 [L]
RewriteRule ^([\w-]+)/?$ index.php?page=$1 [L]
You shouldn't need two directives here. (Providing the DirectoryIndex is set correctly.)
Related
I'm aware this has already been asked, but I've tried countless solutions but I'm still not getting the desired result.
I've a page which shows a list of names and the variables data are the starting letter (variable l which can also be a number) and the page number (page_no) and the page number is optional as it should not be displayed in the page 1.
The original URL is the following
https://www.example.com/allnames.php?l=A&page_no=1
I've the following rule
RewriteCond %{QUERY_STRING} ^l=([\w]+)$
RewriteRule ^allnames.php$ /allnames/%1? [R=301,L]
which works fine for page 1, but it doesn't include the page_no variable, so I tried this one but I'm unable to understand what's wrong.
RewriteCond %{QUERY_STRING} ^l=([\w]+)?page_no=([0-9]+)$
RewriteRule ^allmovies.php$ /allmovies/%1/%2? [R=301,L]
the result expected would be, for example
allnames/A or allnames/A/1 for letter A, page 1
allnames/S/8 for letter S, page 8
And the following is the content of the htaccess file
RewriteEngine On
Options +FollowSymLinks -MultiViews
# to prevent loops
RewriteCond %{ENV:REDIRECT_STATUS} !200
#remove index.php
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
# Sets the HTTP_AUTHORIZATION header removed by apache
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .? - [L]
RewriteRule .? %{ENV:BASE}/index.php [L]
# allnames.php
RewriteCond %{QUERY_STRING} ^l=([\w]+)$
RewriteRule ^allnames.php$ /allnames/%1? [R=301,L]
RewriteRule allnames/ /allnames.php?l=$1&page_no=$2 [L]
RewriteCond %{QUERY_STRING} ^l=([\w]+)?page_no=([0-9]+)$
The regex in the condition (CondPattern) does not allow for the & delimiter between URL parameters. You are also allowing the l parameter value to be entirely omitted (which would result in an ambiguous URL) or contain multiple characters (which you've stated should be a single "letter").
You would seem to need something like the following instead:
RewriteCond %{QUERY_STRING} ^l=([\w])&page_no=([0-9]+)$
But note that this will fail if the l parameter value contains more than one character (or is omitted entirely).
the result expected would be, for example
allnames/A or allnames/A/1 for letter A, page 1
Note that you would still need your first rule (without the page_no URL param) to get allnames/A. You could instead make page_no optional in the second rule, but you would still get a trailing slash (ie. allnames/A/) if that is an issue?
How come that none of these solutions work on my Apache servers:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/{2,} [NC]
RewriteRule ^(.*) $1 [R=302,L]
or
RewriteCond %{REQUEST_URI} ^(.*)/{2,}(.*)$
RewriteRule . %1/%2 [R=302,L]
or
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=302,L]
among others that I tried.
I tried ALL solutions from this page: Issue In Removing Double Or More Slashes From URL By .htaccess
and other pages as well.
The problem is that the rule in the htaccess does not match the double slashes within these above patterns.
I tried also "literal" patterns, with exact urls without regex patterns. Still nothing. But with a single slash - all work.
It seems like Apache has a problem when it finds: "//" - the url is clearly not recognized and the rule is ommited.
The idea is simple: to get rid of double slashes and replace them with one slash:
http://demo.codesamplez.com/html5//audio -> http://demo.codesamplez.com/html5/audio
Do you know how can I redirect URL with double slash "//" to a single onen "/"?
Here's htaccess (removed the longest comments in the file):
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/test//slash
RewriteRule ^(.*)$ /test/slash [R=302,L]
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
# Sets the HTTP_AUTHORIZATION header removed by Apache
RewriteCond %{HTTP:Authorization} .
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^app\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]
# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# Rewrite all other queries to the front controller.
RewriteRule ^ %{ENV:BASE}/app.php [L]
</IfModule>
Try the following instead, near the top of the root .htaccess file, before any existing rewrites:
# Remove multiple slashes anywhere in the URL-path
RewriteCond %{THE_REQUEST} \s[^?]*//
RewriteRule (.*) /$1 [R=302,L]
This uses the fact that multiple slashes have already been reduced in the URL-path matched by the RewriteRule pattern. And the check against THE_REQUEST (which contains the first line of the request headers and does not change throughout the request) ensures that multiple slashes were initially present somewhere in the URL-path (excluding the query string).
Another potential issue is if you have a proxy server (or load balancer) in front of your application (Apache) server and this is perhaps normalizing the request (reducing multiple slashes, removing trailing space, etc) as it forwards the request to your application (Apache) server. The application server then never sees the original request (with multiple slashes) that you see in the browser.
Looking at your attempts...
RewriteCond %{REQUEST_URI} ^/test//slash
RewriteRule ^(.*)$ /test/slash [R=302,L]
This "should" work, with the limited example as posted. However, the REQUEST_URI server variable is modified throughout the request, so if the URL has already been modified (perhaps in the server config) then this may not match.
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/{2,} [NC]
RewriteRule ^(.*) $1 [R=302,L]
This only matches multiple slashes at the start of the URL-path, not anywhere in the URL-path. This would also result in a malformed redirect if used in .htaccess (unless you also had a RewriteBase directive set). Without the slash prefix on the substitution string this rule is probably intended for a server or virtualhost context, not .htaccess.
RewriteCond %{REQUEST_URI} ^(.*)/{2,}(.*)$
RewriteRule . %1/%2 [R=302,L]
The same issue with the use of REQUEST_URI as mentioned above. Otherwise, this should work. However, it results in multiple redirects if there are more than 1 group of multiple slashes. eg. //foo//bar.
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=302,L]
The same as above, except this only matches double slashes, rather than groups of two or more slashes. So if there are more than two slashes in a group it will result in multiple redirects.
I have a problem with my .htaccess, a short explanation I would like to set http://example.com/newest on my website. However, it always redirects to http://example.com/postname. Where I just need the exact "newest" page. Here is my code:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteBase /
RewriteRule ^[^/]+$ %{REQUEST_URI}/ [L,R=301]
RewriteRule ^/category/(.*)$ page.php?f=$1
RewriteRule ^/search/(.*)$ search.php?f=$1
RewriteRule ^(.*)/$ post.php?f=$1 <- If this is removed, my post htaccess will not work
RewriteRule ^newest/$ index.php?f=newest <- I want to execute this code
I really don't know what this is called, I have been looking for the whole stackoverflow but I did not get any answer. Please remain me if this is a duplicate question.
As Mohammed implied in comments, your directives are in the wrong order. The line above your "newest" rewrite is a catch-all and rewrites all requests, so the last line will never match.
http://example.com/newest
Note that your rules imply that your URLs should end in a trailing slash. So, you should be linking to http://example.com/newest/ (with a trailing slash), not http://example.com/newest, otherwise your users will get a lot of unnecessary redirects.
However, you appear to be under the belief that the RewriteCond directive applies to all the directives that follow. This is not the case. It only applies to the first RewriteCond directive. You also need some L flags to prevent further processing.
You also have a slash prefix on the "category" and "search" rewrite patterns, so these would never match in a .htaccess context.
Try something like the following instead:
RewriteEngine On
RewriteBase /
# Don't process the request further if it maps to an existing file
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# Append trailing if omitted
# Although strictly speaking this only redirects if there are no slashes at all in the URL
RewriteRule ^[^/]+$ %{REQUEST_URI}/ [L,R=301]
RewriteRule ^category/(.*)$ page.php?f=$1 [L]
RewriteRule ^search/(.*)$ search.php?f=$1 [L]
RewriteRule ^newest/$ index.php?f=newest [L]
RewriteRule ^(.*)/$ post.php?f=$1 [L]
Is there a way to replace all question mark, '&' , and equal sign by slash ???
currently I am only replacing php extensions by .html
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule ^(.*)\.html$ $1.php [nc]
now, if the websites url is this
http://www.mydomain.com/session/image-display.php?image=1&id=59
the user should get
http://www.mydomain.com/session/image-display.html/image/1/id/59
--edited---
I just need a example so that i could write them for other pages as well.
also how to rewrite 2 or more rewrite rules ??
Based on the example you gave, you can use this:
RewriteRule ^session/image-display.html/image/(.*)/id/(.*)
/session/image-display.php?image=$1&id=$2 [L]
The [L] at the end is optional, it tells Apache to stop looking for other rules if this one is applied
You need to change your links so that they look like:
http://www.mydomain.com/session/image-display.html/image/1/id/59
Then add this in the htaccess file in your document root, before any rules that you may already have:
RewriteCond %{THE_REQUEST} \ /session/image-display\.php\?image=([^&]+)&id=([^&\ ]+)
RewriteRule ^ /session/image-display.html/image/%1/id/%2? [L,R=301]
RewriteRule ^session/image-display\.html/image/([^/]+)/id/([^/]+) /session/image-display.php?image=$1&id=$2 [L]
Try this in .htaccess:
RewriteRule ^(.*)\.html/image/([^/]+)/id/([^/]+)$ $1.php?image=$2&id=$3 [NC]
These 2 rules will internally rewrite /session/image-display.html/n1/v1/n2/v2/n3/v3 to /session/image-display.php?n3=v3&n2=v2&n1=v1
There can be any number of /name/value pairs as this rule is pretty generic.
# this rule will be applied as many times as there are /name/value pairs in URI
# after /session/image-display.html
RewriteRule ^(session/image-display\.html)/([^/]*)/([^/]*)(.*)$ /$1/$4?$2=$3 [L,QSA,NC]
# this rule be applied in the last then all /name/value pairs have been converted
# into query string
RewriteRule ^(session/image-display)\.html/?$ /$1.php [L,NC]
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.