Apache rewrite rules doesn't work only with particular prefix - php

I've some problem with a script I'm writing.
I have those kind of URLs:
forum.php?f=topic&g=$1&id=$2&alias=$3
forum.php?f=group&g=$1
forum.php
I need to rewrite those for have:
/forum/group/id-alias_topic > forum.php?f=topic&g=[GROUP]&id=[ID]&alias=[ALIAS_TOPIC]
/forum/group > forum.php?f=group&g=[GROUP]
/forum > forum.php
I tried with:
RewriteRule ^forum/([\w'-]+)/([0-9]+)-([\w'-]+) forum.php?f=topic&g=$1&id=$2&alias=$3
RewriteRule ^forum/([\w'-]+) forum.php?f=group&g=$1
RewriteRule ^forum/ forum.php
But it doesn't work. It shows me only forum.php
Every URL starting with /forum shows me the default page provided by /forum.php
For example, forum.php will show the text "MAIN PAGE".
forum.php?f=topic&g=[GROUP]&id=[ID]&alias=[ALIAS_TOPIC] should show me "GROUP + ID + ALIAS_TOPIC"
But if I visit /forum/android/1-first_topic it shows me "MAIN PAGE"
If I replace ^forum with, for example ^foru, it works.
I've cleaned my browser cache and restarted apache, but it still doesn't work.
Also with other browsers the problem is the same.
In my /var/www there are those files and directories:
administrator.php assets cache forum_functions.php forum.php functions.php global.php index.php media notfound.php OLD pwdgen.php robots.txt rss.php simple_html_dom.php store.php template v.php
Do you have some advice?
Rewrite.log: http://pastebin.com/MeapYeBA

Because you have not used the [L] (last) flag and not anchored the end of the expressions with $ each one matches the last rule after dropping through the first two.
For example, this URL will match both the first and last rules: example.com/forum/group/123-thing because the last rule matches forum/ and anything that follows it if not terminated by $.
Add [L] flags to prevent fall-through, and terminate the regex with $
# Don't apply these if the file actually exists (like forum.php)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# This one doesn't really need to terminate in $
RewriteRule ^forum/([^/]+)/([0-9]+)-(.+) forum.php?f=topic&g=$1&id=$2&alias=$3 [L]
# This one must terminate with $
RewriteRule ^forum/([^/]+)$ forum.php?f=group&g=$1 [L]
# As must this one..
RewriteRule ^forum/?$ forum.php [L]
I have also replaced your [\w'-]+ with a simpler [^/]+ to match everything up to the next /. In the last rule, I added /? to allow for an optional trailing /. It will work just as well with [\w'-]+, but since you intend to match everything between /, [^/]+ is a more common pattern.
Each of the above rules is tested and working over at http://htaccess.madewithlove.be/

You Must put skip flag for stop other rules With tihs [S] at end of RewriteRule like
RewriteRule ^forum/([\w'-]+)/([0-9]+)-([\w'-]+)$ forum.php?f=topic&g=$1&id=$2&alias=$3 [S=2]
RewriteRule ^forum/([\w'-]+)$ forum.php?f=group&g=$1 [S=1]
RewriteRule ^forum/$ forum.php

Found a solution thanks to #Michael Berkowski
sudo nano /etc/apache2/sites-enabled/000-default
and remove all occurrences of MultiViews, then restart apache.

Related

.htaccess redirect /subpage/ to /subpage?/wp-login

Trying to use .htaccess rule to do the wp-login JS check on first visit by appending ?/wp-login to the url since it's interferring with Sucuri firewall when using password protection.
I've created a test subdomain to try to get the htaccess redirect to work before using it on the live site:
RewriteCond %{QUERY_STRING} ^protectedpage$
RewriteRule ^(.*)$ https://testing.no11.ee/protectedpage?/wp-login [R=302,L]
view here: testing.no11.ee/protectedpage
Unfortunately this does not add the query arg to the url. What am I doing wrong here?
Expected result when visiting page should be https://testing.no11.ee/protectedpage?/wp-login as the browser url.
Full htaccess:
# BEGIN WordPress
# The directives (lines) between "BEGIN WordPress" and "END WordPress" are
# dynamically generated, and should only be modified via WordPress filters.
# Any changes to the directives between these markers will be overwritten.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
RewriteCond %{QUERY_STRING} ^protectedpage$
RewriteRule ^(.*)$ https://testing.no11.ee/protectedpage?/wp-login [R=302,L]
</IfModule>
# END WordPress
RewriteCond %{QUERY_STRING} ^protectedpage$
RewriteRule ^(.*)$ https://testing.no11.ee/protectedpage?/wp-login [R=302,L]
This checks that the QUERY_STRING is set to protectedpage, but in your example it's the URL-path that is /protectedpage, not the query string.
You also need to first check that the query string is not already set to /wp-login, otherwise you'll get a redirect loop.
However, you've also put the code in the wrong place. Note the WordPress comment that precedes the code block - you should not manually edit this code. This directive also needs to go before the WordPress front-controller, otherwise, it's simply never going to get processed.
Try the following instead before the # BEGIN WordPress comment marker:
RewriteCond %{QUERY_STRING} !^/wp-login$
RewriteRule ^(protectedpage)/?$ /$1/?/wp-login [R=302,L]
This matches an optional trailing slash on the requested URL, but it redirects to include the trailing slash in the target URL.
(You do not need to repeat the RewriteEngine on directive.)
No need to include the scheme + hostname if you are redirecting to the same. The $1 backreference simply saves repetition and refers to the matched URL-path, ie. protectedpage (without the trailing slash) in this example.
However, this always redirects and appends /wp-login to this URL - not just the "first visit" - is that really what you require? Otherwise, you need to somehow differentiate between "first" and "subsequent" visits (by detecting a cookie perhaps?)
UPDATE: Minor addition: how would one improve this to add ?/wp-login to all urls that have the page /subpage/ as parent i.e /subpage/page-1 and /subpage/page-2 would result in /subpage/page-1?/wp-login etc? I tried using (.*) but this delets the subpage from the url...
You could do something like the following:
RewriteCond %{QUERY_STRING} !^/wp-login$
RewriteRule ^(subpage/[^/]+)/?$ /$1/?/wp-login [R=302,L]
The [^/]+ subpattern matches any character except / - so only the second path segment, excluding the optional trailing slash. This is similar to .*, but this would capture everything, including any trailing slash, so would result in a double slash in the redirected URL.

Set .htaccess rules to specify different folders

I want to set a rule in .htaccess if I enter in the url www.mydomain.com/compare.php set 'public_html' as root otherwise anything come in the url set root as 'public' folder.
RewriteRule ^(?!compare-source.php).*)$ public/$1 [L]
I want to achieve following result.
if url is www.mydomain.com/compare.php hit following file.
public_html/compare.php
if urls are www.mydomain.com/ OR www.mydomain.com/home etc hit following file.
public_html/public/index.php
I am weak in regex and in these apache rules always :-( can someone give me the solution with good description?
Your answers are welcome, please can you describe how this crazy things work in detail. Thanks.
Try:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/public
RewriteRule ^((?!compare\.php).*)$ /public/$1 [L]
The RewriteEngine directive enables or disables the runtime rewriting engine.
The RewriteCond directive defines a rule condition. The following Rule is only used if this condition is met; In our case, if REQUEST_URI (the path component of the requested URL) does not (because of !) begin (because of ^) with /public. We need this condition because we don't want to rewrite already rewritten URL - that would cause loop and Internal error 500.
Finally, the RewriteRule will match regex Pattern (^((?!compare\.php).*)$) against part of the URL after the hostname and port, and without the leading slash. If the pattern is matched, the Substitution (public/$1) will replace the original URL-path.
In plain language, if URL path does not begin with compare.php (because of ?!), pick everything (.*) between beginning (^) and end ($) and place it in variable $1. Then replace the original URL path with /public/$1.
#Anubhava's answer is also correct, he just placed both conditions in RewriteRule, and also it could be written even more readable as:
RewriteCond %{REQUEST_URI} !^/public
RewriteCond %{REQUEST_URI} !^/compare\.php
RewriteRule ^(.*)$ /public/$1 [L]
You can use this .htaccess in site root:
RewriteEngine On
# route /home/ or /home to /
RewriteRule ^home/?$ / [L,NC]
# if not compare-source.php or public/* then route to /public/*
RewriteRule ^(?!public/|compare-source\.php$).*)$ public/$1 [L,NC]

Apaches mod_rewrite issues

I'm having issues with apaches mod_rewrite. I'm wanting to make clean urls with my php application but it doesn't seem to give the results i'm expecting.
I'm using this code in my .htaccess file:
RewriteEngine on
RewriteRule ^project/([0-9]{4})/([0-9]{2})$ /project/index.php?q=$1&r=$2 [L]
RewriteRule ^project/([0-9]{4})$ /project/index.php?q=$1 [L]
To make it so when I view, http://localhost/user/project/system, it would be the equivelant of viewing http://localhost/user/project/index.php?q=system
Instead of getting any results I just get a typical 404 error.
I've also just checked to see if mod_rewrite works by replace my .htaccess code with this:
Options +FollowSymLinks
RewriteEngine On
RewriteRule (.*) http://www.stackoverflow.com
And it properly redirects me here, so mod_rewrite is definitely working.
The root path to my project is /home/user/public_html/project
The the url used to view my project is http://localhost/user/project
If anymore information is required let me know.
Thanks
If your .htaccess file is indeed located in the project/ subdirectory already, then don't mention it in the RewriteRule again. Remove it:
RewriteRule ^([0-9]{4})/([0-9]{2})$ /project/index.php?q=$1&r=$2 [L]
# no "project/" here
Rules always pertain to the current local filename mapping.
Else experiment with a RewriteBase.
You have [0-9]{4} in your regex which will only match numbers of 4 digits. "system", however, is not a number of 4 digits, and therefore does not match.
You can use something like [^/]+ instead.
RewriteRule ([^/]+)/([0-9]{2})$ /index.php?q=$1&r=$2 [L]
RewriteRule ([^/]+)$ /index.php?q=$1 [L]
Don't know if the second parameter should be a number with 2 digits or not.
Edit: I also added "user" at the beginning now.
Edit2: Okay, I thought you were in the root htdocs with your htaccess. So remove "project" and "user" if you are in "project" with the .htaccess.
You probably mean
RewriteRule ^/project/([0-9]{4})/([0-9]{2})$ /project/index.php?q=$1&r=$2 [L]
RewriteRule ^/project/([0-9]{4})$ /project/index.php?q=$1 [L]
The '^project' means "start of line is 'project'" but the start is a '/project', so you need to include the starting slash (i.e. '^/project...').
Sorry, missed the system bit (and the user bit). Was concentrating on the slash.
RewriteRule ^/user/project/([a-zA-Z0-9]*)/([a-zA-Z0-9]*)$ /user/project/index.php?q=$1&r=$2 [L]
RewriteRule ^/user/project/([a-zA-Z0-9]*)$ /user/project/index.php?q=$1 [L]
Should have you right.

rewrite a folder so all files display under new rewrite rule

Is there a way that I can rewrite a folder so that all the files under that folder follow the same rule? For example:
if i have a folder with say 5 php files (a.php, b.php, c.php, d.php, index.php) in it and i use the following rule:
RewriteRule ^products/storage/?$ /content/products/storage/index.php [QSA,L]
is there a way that I can get all the files to show to be accessed like: site.com/products/apples/a.php, site.com/products/apples/b.php, etc. without having to write a rule for each one?
I tried the following but it didnt work.
RewriteRule ^products/storage/?$ /content/products/storage/ [QSA,L]
I also need it to NOT overwrite my other rules such as:
RewriteRule ^products/storage/?$ /content/products/storage/product-name1/ [QSA,L]
RewriteRule ^products/storage/?$ /content/products/storage/product-name2/ [QSA,L]
any ideas?
Your problem is the trailing $ on the end of the regex. This will only allow a match if the full URI matches products/storage (with optional trailing slash) exactly. Instead, try the following and note the absence of the trailing $ character:
RewriteRule ^products/storage/? /content/products/storage/ [QSA,L]
This will match anything that starts with products/storage (with optional trailing slash). Alternatively, if you wanted to capture and re-use everything in the URI that followed products/storage/ you could try:
RewriteRule ^products/storage(/?.+)?$ /content/products/storage$1 [QSA,L]
UPDATE
Should you need to preserve other RewriteRules as your updated question suggests, you should look to add a RewriteCond condition like so:
RewriteCond !^products/storage/?$
RewriteRule ^products/storage(/?.+)?$ /content/products/storage$1 [QSA,L]
The RewriteCond tells the RewriteRule to only process if the condition is not met.

PHP all GET parameters with mod_rewrite

I am designing my application. And I should make the next things. All GET parameters (?var=value) with help of mod_rewrite should be transform to the /var/value. How can I do this? I have only 1 .php file (index.php), because I am usign the FrontController pattern. Can you help me with this mod_rewrite rules?Sorry for my english. Thank you in advance.
I do something like this on sites that use 'seo-friendly' URLs.
In .htaccess:
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* /index.php [L]
Then on index.php:
if ($_SERVER['REQUEST_URI']=="/home") {
include ("home.php");
}
The .htaccess rule tells it to load index.php if the file or directory asked for was not found. Then you just parse the request URI to decide what index.php should do.
The following code in your .htaccess will rewrite your URL from eg. /api?other=parameters&added=true to /?api=true&other=parameters&added=true
RewriteRule ^api/ /index.php?api=true&%{QUERY_STRING} [L]
.htaccess
RewriteEngine On
# generic: ?var=value
# you can retrieve /something by looking at $_GET['something']
RewriteRule ^(.+)$ /?var=$1
# but depending on your current links, you might
# need to map everything out. Examples:
# /users/1
# to: ?p=users&userId=1
RewriteRule ^users/([0-9]+)$ /?p=users&userId=$1
# /articles/123/asc
# to: ?p=articles&show=123&sort=asc
RewriteRule ^articles/([0-9]+)/(asc|desc)$ /?p=articles&show=$1&sort=$2
# you can add /? at the end to make a trailing slash work as well:
# /something or /something/
# to: ?var=something
RewriteRule ^(.+)/?$ /?var=$1
The first part is the URL that is received. The second part the rewritten URL which you can read out using $_GET. Everything between ( and ) is seen as a variable. The first will be $1, the second $2. That way you can determine exactly where the variables should go in the rewritten URL, and thereby know how to retrieve them.
You can keep it very general and allow "everything" by using (.+). This simply means: one or more (the +) of any character (the .). Or be more specific and e.g. only allow digits: [0-9]+ (one or more characters in the range 0 through 9). You can find a lot more information on regular expressions on http://www.regular-expressions.info/. And this is a good site to test them: http://gskinner.com/RegExr/.
AFAIK mod_rewrite doesn't deal with parameters after the question mark — regexp end-of-line for rewrite rules matches the end of path before the '?'. So, you're pretty much limited to passing the parameters through, or dropping them altogether upon rewriting.

Categories