regex mod_rewrite ?-mark sign causing bug - regex

I'm trying to redirect old-style links from an old website to new style links in php.
I'm using:
RewriteEngine on
RewriteBase /
RewriteRule s\.cfm?id=5$ http://mysite.com/article5.php [B,L,R=301]
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
However, if I use just s.cfm? everything works fine and redirects to article5.php. But if I try to redirect the id=5 part, I get page not found.
I tried just s.cfm?id and it causes the htaccess bug. So anything you put after question mark ?... causes a problem, I don't know why.

You can't match against the query string inside a RewriteRule, only the URI path is sent through the rule itself. If you need to match against the query string, then use the %{QUERY_STRING} var inside a RewriteCond:
RewriteCond %{QUERY_STRING} ^id=5$
RewriteRule ^/?s\.cfm$ http://mysite.com/article5.php [L,R=301]
Everything else is fine.

Related

htaccess removing .php extension and pretty urls

Im trying to both remove .php extensions. So for example "http://localhost/timetable/login" instead of "http://localhost/timetable/login.php"
But also have
"http://localhost/timetable/38/" instead of
"http://localhost/timetable/index.php?week=38"
Im able to get one or the other working but not both at the same time. Im assuming its because there is a conflict between them but Im not advanced enough to find it.
Here is my .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
RewriteRule ^([0-9]+)$ index.php?week=$2
RewriteRule ^([0-9]+)/$ index.php?week=$2
If in the address bar I type "http://localhost/timetable/38" it brings me to "http://localhost/38/" and an Object not Found error.
Does anyone know what the problem is ?
UPDATE: I can now go to the page but
echo $_GET['week'];
Is returning empty result, so its ignroing the 40 in "http://localhost/timetable/40"
Instead of using separate rewrite rule for each input, you should consider routing all of them as a single string to some php file.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?page=$1 [L,QSA]
In you php file, you can then separate the string as input and use them as required.
<?php
$inputs = explode('/', $_GET['page']);
You only have one capture group when you try to get the week. So it should be $1 instead of $2.
According to this test tool, the following should work:
RewriteRule ([0-9]+)/?$ index.php?week=$1
I would do something like this:
# rewrite if url ends with a number and possibly a slash
RewriteRule ([0-9]+)/?$ index.php?week=$1 [QSA,L]
# do not append .php if it already ends with .php, other add .php
RewriteCond %{REQUEST_URI} !\.php$
RewriteRule ^(.*)$ $1.php [QSA,L]

.htaccess rewriterule with backslashes in regex

I want to 'catch' an URL with .htaccess rewriterule. How can I add backslashes to the rewriterule?
For example:
http://www.example.com/page1 -> index.php?page=page1
http://www.example.com/page1/subpage1 -> index.php?page=page1/subpage1
As you can see, I want the backslash between 'page1' and 'subpage1' IN the rewriterule, because the path can be variable (more subpages).
I tried this:
RewriteRule ^(.*)$ /index.php?page=$1 [NC,L,QSA]
But then I get an Internal Server Error.
Thanks in advance!
You get an Internal Server Error because your rule introduces an infinite redirect loop.
Here is what you want
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.php?page=$1 [NC,L,QSA]
It checks if the url is not a physical folder/file before rewriting it internally

Htaccess rewrite GET request to another GET request and another with 2 GET variables

I have two url's I'm trying to rewrite, for the past... 4-5 hours (headache now).
I am trying to rewrite
/arts/tag/?tag=keyword
to
/search/art?keywords=keyword
Looking at other questions I formulated my rewrite like this
RewriteRule /arts/tag/?tag=([^&]+) search/art?keywords=$1 [L,R=301,NC]
and
RewriteRule ^arts/tag/?tag=$ /search/art\?keywords=%1? [L,R=301,NC]
I tried with backslashes and without, no luck.
Also tried
RewriteCond %{QUERY_STRING} /arts/tag/?tag=([^&]+) [NC]
RewriteRule .* /search/art\?keywords=%1? [L,R=301,NC]
The second one is similar,
/arts/category?id=1&sortby=views&featured=1
to
/art/moved?id=1&rearrange=view
The reason I change the get variable name is for my own learning purpose as I haven't found any tutorials for my purpose. I also changed category to moved since the categories have changed and I have to internally redirect some ID #'s.
RewriteCond %{QUERY_STRING} id=([^&]+) [NC] // I need the path in there though, not just query string, since I'll be redirecting /blogs/category and /art/category to different places.
RewriteRule .* /art/moved/id=%1? [L,R=301,NC]
Any help will be appreciated. Thank you.
Assuming the queries in the original URLs have nothing in common with those in the substitution URLs, maybe this will do what you want, using the first keyin the query as a condition and to identify the incoming URL:
RewriteEngine On
RewriteBase /
# First case
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} \btag\b
RewriteRule .* http://example.com/search/art?keywords=keyword? [L]
Will map this:
http://example.com/arts/tag/?tag=keyword
To this:
http://example.com/search/art?keywords=keyword
# Second case
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{QUERY_STRING} \bid\b
RewriteRule .* http://example.com/art/moved?id=1&rearrange=view? [L]
Will map this:
http://example.com/arts/category?id=1&sortby=views&featured=1
To this:
http://example.com/art/moved?id=1&rearrange=view
Both are mapped silently. If the new URL is to be shown in the browser's address bar modify the flags like this [R,L]. Replace R with R=301 for a permanent redirect.

Removing index.php from url using .htaccess even if the user requests it

I never want index.php to show up in my URL, even if the user inputs it. Is this possible?
This is variation whatever after several tries. I've come close a few times but this is where it's at for now.
RewriteEngine On
RewriteBase /sub-dir/
RewriteCond %{REQUEST_URI} index\.php$ //If URL ends in index.php
RewriteRule (.*)index\.php $1 //Somehow remove index.php from the url
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
Currently I have permalink set up where if the user enters domain.com/sub-dir/my-perma-lin/ it generates a string on the page based on my-perma-link to look like My Perma Link. What I'd like is if the user submits any URL ending in index.php it just removes that from the URL but leaves everything else as is.
domain.com/sub-dir/index.php --> domain.com/sub-dir/
domain.com/sub-dir/my-perma-link/index.php --> domain.com/sub-dir/my-perma-link
I've written quite a few rules in http://htaccess.madewithlove.be/ that work perfectly but when I upload it (to Dreamhost) nothing works.
This for example should work according to the the tester
RewriteEngine On
RewriteBase /sub-dir/
RewriteCond %{REQUEST_URI} \.php //Not needed but thought it would/should help
RewriteRule (.*)(index\.php)+ $1 [L,R=301,NC]
But it just removes everything after /sub-dir/
I'm either missing something super obvious or it's not possible ...
You need to add some flags to your rule:
RewriteEngine On
RewriteBase /sub-dir/
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.php(\?|\ )
RewriteRule ^ /%1 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
You can ditch the RewriteCond %{REQUEST_URI} index\.php$ condition, as that's being checked by the regex in the RewriteRule. You need to include a $ at the end of the regex, and include the flags L to stop rewriting and R=301 to redirect.

My previously working HTAccess no longer works

My HTAccess was working before. But I wanted to add an FTP section to the site. It is decided that all FTP will go in /ftp and all requests to /ftp/... will be internally redirected to /ftp.php?dir=... that handles authentication and such before using readfile(...). Being a n00b at regex, I assumed this would work: (only the ftp section was added and the |ftp added)
RewriteEngine On
# http://httpd.apache.org/docs/2.4/rewrite/flags.html
# Match page
RewriteCond %{REQUEST_URI} !^/?(cydia|firmware|scripts|site|ftp)
RewriteCond %{REQUEST_URI} !^/?(robots.txt|ftp.php)
RewriteRule ^/?(.*)$ /site/index.php?title=$1 [PT,L,QSA]
# Match FTP
RewriteCond %{REQUEST_URI} ^/?ftp
RewriteRule ^/?(.*)$ /ftp.php?dir=$1 [PT,L,QSA]
RewriteRule ^/*$ /site/index.php [L,QSA]
Basically, what I did was (I think) match /ftp as a true instead a false like above. However, this gives me a 500 Server Error throughout the site (indicating a problem in the HTAccess). I'm sure this is a simple error, but I'm hoping you can help me with this.
Your issue is that those too line will redirect everything starting with ftp (including ftp.php and this will create an infinite loop)
RewriteCond %{REQUEST_URI} ^/?ftp
RewriteRule ^?(.*)$ /ftp.php?dir=$1 [PT,L,QSA]
Try replacing them with this :
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^/?ftp
RewriteRule ^/?(.*)$ /ftp.php?dir=$1 [PT,L,QSA]