RewriteRule not rewriting with matching regex - regex

I'm attempting to get apache to rewrite a request to mysite.com/blog/<number> to the file /blog.php?page=<number>. However, using a regex which does match that path, the URL is not rewritten and instead a 404 is returned as /blog/ is a nonexistent directory.
Here is the RewriteRule I'm using:
RewriteEngine On
RewriteRule ^blog/[0-9]+/? /blog.php?page=$1 [L]
I haven't used apache in quite a while, so I may have forgotten some extremely simple item which is required, but I cannot see anything wrong with the rule.
Edit:
RewriteRules from httpd.conf:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L]

You're not grouping the numbers after ^blog/ using round brackets, that's why $1 will be empty.
Try this rule in your DOCUMENT_ROOT/.htaccess file:
RewriteEngine On
RewriteRule ^blog/([0-9]+)/?$ /blog.php?page=$1 [L,NC,QSA]

Related

404 error with .htaccess url slug without a hyphen

I'm new to .htaccess and I've been working on a site where I have used URL slugs. Everything is working perfectly fine with slugs that have hyphens in them, but I get 404 error when I have a one word slug.
https://www.example.com/blog/example-blog works fine but https://www.example.com/blog/example throws a 404 error.
Below is the .htaccess code I'm currently using:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^([a-z]+)\/?$ $1.php [NC]
RewriteRule ^([a-zA-Z0-9-]+)\/?$ index.php?url=$1 [NC]
RewriteRule ^([a-zA-Z0-9-]+)\/season\/([0-9]+)\/?$ index.php?url=$1&season=$2 [NC]
</IfModule>
I've searched everywhere on Search Engine but got no luck. Any help is highly appreciated.
Summary:
I'm looking for ways for .htaccess to accept a slug without a hyphen as those with hyphens are working fine.
RewriteRule ^([a-z]+)\/?$ $1.php [NC]
This rule will catch the request /example and unconditionally rewrites it to example.php. Whereas /example-blog (with a hyphen) is ignored by this rule (because the regex ^([a-z]+)\/?$ does not match).
If this rule is required then add an additional condition that checks for the existence of the .php file before rewriting (otherwise this rule should be removed altogether). For example:
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([a-z]+)/?$ $1.php [NC,L]
Now, only requests that actually map to .php files are rewritten.
UPDATE:
I've added the L flag to the above rule, although it will still work without.
So, in summary, your complete set of rules should look like this:
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([a-z]+)/?$ $1.php [NC,L]
RewriteRule ^([a-zA-Z0-9-]+)/?$ index.php?url=$1 [L]
RewriteRule ^([a-zA-Z0-9-]+)/season/([0-9]+)/?$ index.php?url=$1&season=$2 [L]
There's no need to backslash-escape slashes in the regex, so I've removed the unnecessary backslashes. The NC flag is superfluous on the last two rules since you are already matching a-zA-Z in the RewriteRule pattern. And I've added the L flag, since you want processing to stop after the rewrite.
The <IfModule> container is also not required.

String repeats 20 times in RewriteRule if i try to use it with $1, $2 etc. back-references. Weird. Why?

I try to do a RewriteRule redirect in .htaccess where the output URL has some additional text beside the captured text from the capture groups.
Original url: https://example.com/places/europe/hungary/budapest/
My regex pattern: ^places/([a-zA-Z-_]+/)?([a-zA-Z-_]+/)?([a-zA-Z-_]+/)?
i want to add a 'text-' string in the destination url around some $1, $2..
The full line in .htaccess: RewriteRule ^places/([a-zA-Z-_]+/)?([a-zA-Z-_]+/)?([a-zA-Z-_]+/)? https://example.com/places/$1text-$2$3 [R=301,L]
but it outputs exactly this:
https://example.com/places/europe/text-text-text-text-text-text-text-text-text-text-text-text-text-text-text-text-text-text-text-text-hungary/budapest/
Instead of this: https://example.com/places/europe/text-hungary/budapest/
Yep, the additional 'text-' is repeating 20x times instead of 1.
If I don't put the 'text-' in the substitution string, all works as expected i.e:
https://example.com/places/$1$2$3 [R=301,L]
gives
https://example.com/places/europe/hungary/budapest/
What may cause this strange (to me) anomaly?
Is this should work without glitches or what is the correct syntax for this case?
All the other code in the .htaccess file (positioned after this RewriteRule part in question):
# BEGIN rlrssslReallySimpleSSL rsssl_version[3.3.5]
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
</IfModule>
# END rlrssslReallySimpleSSL
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Yes it's a wordpress install.
Thanks a lot for any help!
As suggested in comments by Amit that you're running into this issue because pattern [a-zA-Z_-]+/ matches original string hungary as well as the target string text-hungary, thus results in a redirect loop.
You may use this rule with a negative lookahead to prevent a redirect loop as you're experiencing in your current rule:
RewriteRule ^places/([a-zA-Z_-]+/)((?!text-)[a-zA-Z_-]+/)([a-zA-Z_-]+/?)$ /places/$1text-$2$3 [R=301,L]
(?!text-) is a negative lookahead condition that will fail the match when $2 starts with text-.
Also note that an unescaped - should be placed at the start or end of a character class [...].
Make sure to clear your browser cache before testing this change.

How to create .htaccess for multiple parameters in URL?

I need using this .htaccess file. It only changes the URL from www.mydomain.com/users/user?usernam=myname123&profile=myprofile123&data=mydata123 to www.example.com/users/myname123/myprofile123/mydata123 .
i use
RewriteEngine On
RewriteRule ^user\.php$ - [L]
RewriteRule ^([0-9a-zA-Z\-_.]*)/?$ /users/user.php?username=$1&profile=$2&data=$3[L,QSA]
htaccess in users folder
not work
With your shown samples, could you please try following rules. This will take anything in REQUEST_URI starting.
RewriteEngine ON
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{THE_REQUEST} /([^/]*)/([^/]*)/([^/]*)/([^/]*)/?\s
RewriteRule ^(.*) /%1?username=%2&profile=%3&data=%4 [NE,L,NC]
OR(either use above or following one) in case you want to match users in URI then run rules then try following.
RewriteEngine ON
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{THE_REQUEST} /users/([^/]*)/([^/]*)/([^/]*)/?\s
RewriteRule ^(.*) /users?username=%1&profile=%2&data=%3 [NE,L,NC]
Explanation: Adding detailed explanation for above.
RewriteEngine ON: Enabling RewriteEngine here to enable mod rule writing.
RewriteCond %{QUERY_STRING} ^$: Checking condition if query string is NULL then go further in rules.
RewriteCond %{THE_REQUEST} /users/([^/]*)/([^/]*)/([^/]*)/?\s: Matching regex in THE_REQUEST from /users to till spaces and capturing 3 groups values into back references to be used later.
RewriteRule ^(.*) /users?username=%1&profile=%2&data=%3 [NE,L,NC]: Using url rewrite to change URI to as per OP's request which has back references values in it.

Redirects to path with "/" at the end

I got redirects from /something to /something/ with that setting at my .htaccess file:
RewriteCond %{REQUEST_URI} !\.
RewriteRule ^(.*[^/])$ http://%{HTTP_HOST}/$1/ [L,R=301,QSA]
I want to add the same thing for pages which ends on 123.html
RewriteCond %{REQUEST_URI} [0-9]+\.html$
RewriteRule ^(.*[0-9]+\.html[^/])$ http://%{HTTP_HOST}/$1/ [L,R=301,QSA]
It does't work... BUT!
RewriteCond %{REQUEST_URI} [0-9]+\.html$
RewriteRule ^(.*[0-9]+\.htm.*[^/])$ http://%{HTTP_HOST}/$1/ [L,R=301,QSA]
That variant works perfect! Why apache does't like "l"? Who knows?
Apache version: 2.4.9
Your attempted not working rule is:
RewriteRule ^(.*[0-9]+\.html[^/])$ http://%{HTTP_HOST}/$1/ [L,R=301,QSA]
Which doesn't work because your regex is incorrect as your Request URI is ending with .html and there is nothing after .html. Hence \.html[^/] doesn't match the URI but \.htm.*[^/] does match as last [^/] matches letter l.
Correct rule would be:
RewriteRule ^(.*[0-9]+\.html)$ http://%{HTTP_HOST}/$1/ [L,R=301]
PS: You also don't need to use RewriteCond

Rewrite URL's .htaccess

I believe it might be a possible duplicate. But I tried my best to search for such a thing that will suit my needs and I found, none.
So here's basically what I have so far, and I will explain what I need modified.
# Forbidden Access
ErrorDocument 403 /403.php
# Not Found
ErrorDocument 404 /404.php
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine On
RewriteBase /
</IfModule>
<IfModule mod_rewrite.c>
# Strip off .php extension if it exists
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
RewriteRule ^ %1 [R,L,NC]
# Unless directory, remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/$ /403.php$1 [R=301,L]
# Resolve .php file for extensionless php urls
RewriteRule ^([^/.]+)$ $1.php [L]
</IfModule>
Now this seems to be working flawlessly. But it has one error. Let me explain first.
1) It does automatically strip-off .php extension if it exists. Not sure if it strip off .php if it is url of an external request. Forgot to check, but maybe you already know so you can tell me ?
2) When I type this... "http://website.dev/img/" it does give me an "403 Forbidden Access". So that's all good.
3) When I try this... "http://website.dev/index" it does load the page even if there is .php extension manually added it will strip it off. So All good in here too...
4) When I try random path like this... "http://website.dev/asdasd" it does give me an "404 Not Found". So we're good in here as well.
But the main problem is here...
5) When I try following... "http://website.dev/dashboard/index" it give me an 404 Not Found even tho it should be loading without issues. It appears for all pages within dashboard directory.
Can you help me to modify that htaccess above please ? I am really tired of searching and I don't know regex at all.
That is because of the faulty regex used in your very last rule to silently add .php extension. Change last rule to:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI}\.php -f [NC]
RewriteRule ^(.+?)/?$ /$1.php [L]
Here's my translation of you rules:
# Strip off .php extension if it exists
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
Bad comment. You regexp means: strip off all files that have 3 uppercase first and and dot php in it. Maybe you've forgotten the ending $?
# Unless directory, remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/$ /403.php$1 [R=301,L]
Why is that? Just do a redirect, and Apache will handle the 301 it for you:
RewriteRule .* - [L,R=403]
And then last question: why you strip off .php extension, if you re-add it later on? (°_o)
So here's what you should do, with some examples, and adapt them you fit your needs:
First test if the file has no special treatment. If so, stop immediately, like this:
RewriteRule ^/(robots\.txt|404\.php|403\.php)$ -
Then test if someone is trying to hack. If so, redirect to whatever you want:
RewriteRule (.*)test.php - [QSA,L]
RewriteRule (.*)setup.php http://noobs.land.com/ [NC,R,L]
RewriteRule (.*)admin(.*) http://noobs.land.com/ [NC,R,L]
RewriteRule (.*)trackback(.*) http://noobs.land.com/ [NC,R,L]
Then, only after this, forbid the php extension:
RewriteRule (.*)php$ - [L,R=404]
Then, accept all static "known" file extension, and stop if it matches:
RewriteRule (.*)(\.(css|js|htc|pdf|jpg|jpeg|gif|png|ico|mpg|mp3|ogg|wav|otf|eot|svg|ttf|woff)){1}$ $1$2 [QSA,L]
Now you can do some testing. If the URI ends with a 'aabb/', test if you have a file named aabb.php, and if so, go for it:
RewriteCond %{REQUEST_URI} (\/([^\/]+))\/$
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule (.*) %{DOCUMENT_ROOT}/%1.php [QSA,L]
If nothing is handled, and you get here, it's a problem, so stop it:
RewriteRule .* - [L,R=404]
FYI, all those sample rules are deeply tested on a production server.
And now with that, you have all what you need to do something good & working.