mod_rewrite to serve html pages through php script - .htaccess

First of all, I've set my rewrite rule to allow the removal of .html from the URL.
I've also created a php script that I want to serve all of my HTML pages. This way, I can create and link to a simple html page, but it will be handled by my php script.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ /folder/webpage.php?view=webpage_handler&file=$1.html [L]
So instead of linking to www.mysite.com/page.html I link to www.mysite.com/page which allows me to access the page.html through webpage.php
I would also like to be able link to the page.html in some other cases (without removing the .html extension) and still have my webpage.php handle the page view.
I've tried:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ /folder/webpage.php?view=webpage_handler&file=$1.html [L]
RewriteRule ^(.*\.(html))$ /folder/webpage.php?view=webpage_handler&file=$1 [L]
but this does not work like expected. I'm not sure if the second rule is working at all, and I do believe they're conflicting each other... but I don't know how to fix it.
Is there a safe way to allow me to link to both "/page.html" and "/page" and get my expected outcome?

After more trial and error, I've learned that what I had was actually correct. For some reason my "view" variable was getting erased which was causing my script to not function properly.
My $_GET['view'] variable was blank in webpage.php but the $_GET['file'] variable was set like it should.
I changed from
view=webpage_handler
to
view=handle_webpage
That's it. It works fine now. Obviously it was something I did, but I have no clue what.

Related

Mod Rewrite tweak to ignore asset directories

I'm configuring Expression Engine on Windows using IIS and have ISAPI v3 Rewrite installed.
It's partly working. The main site and subpages work but needs to be modified because some web page assets are stored in similarly named directories.
The recommended Rewrite provided by Ellislabs is this and I've modified it a little to work with our Win 2012 IIS 8 server:
RewriteEngine On
RewriteBase /
# Removes index.php from ExpressionEngine URLs
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteCond %{REQUEST_URI} !/system/.* [NC]
RewriteRule (.*?)index\.php/*(.*) abc/$1$2 [R=301,NE,L]
# Directs all EE web requests through the site index file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ abc/index.php?/$1 [L]
For example, the URL http://oursite.example.com/abc works.
Subpages are mostly working and I suspect this applies to any page really but I'm noticing it on subpages. It removes index.php and mostly loads, such as http://oursite.example.com/abc/subdept/page/
However our developer has some assets kept in a server directory named /uploads/abc/ so if a page refers to this directory, it fails to load those assets because it contains the same name, "abc".
Thus, what is the best way to handle this?
I'm guessing I can either tell it to ignore "uploads/cls" or correct the current Rewrite so that it only looks at the first "abc". I'd like for the solution to cover most similar issues that would arise so I don't have to keep modifying it. We have 12 sites and I'll have to apply the solution to each one.
Everything I've tried hasn't worked.
Also, I thought !-f and !-d would tell it to ignore it if the file or directory existed and that doesn't seem to be working as I'd expect here because these images in /uploads/abc/ do exists.
Thanks!
--
Additionally just trying to get it to work at all, I tried adding a htaccess file with "RewriteEngine Off" in the /uploads/abc/ directory and that failed to fix it.
I also tried to add this after each comment and it fails to fix it:
RewriteCond %{REQUEST_URI} !^/excluded-folder/.*$
Seeing how both of the above attempts fail to fix it, I'm wondering if there could be something else going on. Any ideas?
My rewrite was fine. The problem turned out to be code within an Expression Engine template that the in house developer created. They updated the code and the images are loading fine now.

What is the proper way to make your url "nicer"?

recently i have tried to build some MVC application without any framework to understand MVC pattern better. Till now i have resolved every problem i have had BUT....
Pretty common thing is to make your URL looks "nicer"
For example www.somesite.com/controller/method
instead of www.somesite.com/index.php?c=1&m=2.
i achieved this simply with htacces by aiming it to a variable.
in htaccess...RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
This works perfectly fine until someone tries to rewrite variable "url".
Basically if someone types www.somesite.com/controller/method?url=1
my Application will pop up an error page because i am parsing everything after / and calling specific controllers and methods by its name (or popping up an error page if that doesnt exists).
So i would like to know if there is a better way to do this or way to avoid this behaviourThanks :)
EDIT
In last few hours i tried to find a better solutions. I thought i could put my url into Enviromental variable instead of into get variable.
So i experimented with commands like
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)$ index.php [E=URL:$1,QSA]
unfortunately $_SERVER["URL"] is blank......
i would be really happy if someone could help me with this piece of code :) Thanks
EDIT 2
Okay to make it clear i'll add few examples.
My current htacces looks like this
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)$ index.php?url=$1 [QSA]
So if someone goes to www.somesite.com/foo/bar
i will check $_GET["url"] and then explode it explode("/", filter_var(rtrim($_GET["url"], "/"), FILTER_SANITIZE_URL))
Now i have array which looks like [0=>foo 1=>bar]
That means in my code that i will try to call controller called foo and then method in this class called bar
In case that the user will try to acces www.somesite.com/foo/bar/fee/faa, fee and faa will pass as a parameters to method bar in class foo.
So this was just example how does this work. My problem is as i said when someone tries to acces lets say www.somesite.com/foo?url=0. Then my script will try to handle $_GET["url"] and the result wont be foo but 0 because of ?url=0 rewrites the value of url which was originaly set in my .htacces. So my scripts will try to call controller called 0 and if that doesnt exists itt will popup error404. I have already tried to ignore this specific variable via QUERY_STRING in htacces but this seems to me like a stupid solution. For now i would like to stick with setting evniromental variable instead of get variable or if there is some better way to achieve this :) Thanks
Your current set-up relies on $_GET to obtain core information but, as you've faced, that variable is populated from user input so anyone can mess with your routing, even inadvertently.
A typical Apache configuration for a custom router looks like this (this snippet is from CakePHP/2.x):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
As you can see is doesn't add GET variables of its own, it merely lets existing ones to pass through. Original URL is right there inside $_SERVER, you don't need to instruct Apache to copy it into the redirected URL.
I understand you want $_SERVER['REQUEST_URI'] but you can peek inside the array with the usual methods: print_r($_SERVER), var_dump($_SERVER), phpinfo()...

how to rename a module in the url with mod_rewrite

I'm using MVC with /<module>/<controller>/<action>/ have a module at example.com/module/whatever, and I need to 'rename' it to example.com/module-a/whatever. The whole application is already written, so I can't go through and change it everywhere in my code, so I'm hoping to do it with mod_rewrite. I've tried the following
RewriteCond %{THE_REQUEST} ^GET\ /module/
RewriteRule ^module/(.*) /module-a/$1 [L,R=301]
which did what I wanted as far as redirecting all urls like example.com/module/whatever to example.com/module-a/whatever, but now I need all requests at 'module-a' to be internally rewritten as 'module'. It also needs to work for the module root (i.e. example.com/module with no trailing slash). Is this possible? I added
RewriteRule ^module-a/(.*)$ module/$1
directly beneath the above condition and rule, but when the page is accessed, it still says the module 'module-a' is not found.
Edit:
I have a few more rules below those, I wouldn't think they would affect this, but here they are anyway:
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
Solution
I ended up using
RewriteCond %{THE_REQUEST} ^GET\ /module/
RewriteRule ^module$ /module-a [L,R=301]
RewriteRule ^module/(.*) /module-a/$1 [L,R=301]
to redirect all links from module to module-a. I had to do it with 2 rules because I don't know regex well enough to combine them, handling the special case of the url example.com/module.
To rewrite internally, the original rule I had would normally work, but Zend seems to do some stuff that overrides that, so I had to handle it with routes. See rename a zend module with routes
If I understand correctly then you've gone about this from the wrong direction. I am also not clear on the purpose of your RewriteCond
You want all module-a/* requests to be processed internally as module/*, so all you need is a simple rewrite::
RewriteRule ^module-a/?(.*) /module/$1 [L]
I suspect the problem you are having is the internal links on the site all reference /module/ rather than /module-a/, but putting a 301 there will cause no end of problems (not least with search engines), and with the subsequent rewrite you may fall into circular references. You are much better off changing the link code in your app (if you have a link abstraction class), or at worst using output buffering to swap all links out before rendering the page.
Note: The second rule below the above is not being processed if the first matched, as [L] causes mod_rewrite to cease processing if that rule is matched.

ignore specific directories in htaccess using mod_rewrite

I've got the following code in my .htaccess to strip out index.php from the urls in my CMS-based site.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
This code works great and it routes requests exactly how I want. For example, with URL: http://example.com/contact/ the directory contact doesn't actually exist if you look in the FTP; instead index.php handles the request and shows my contact info. Perfect. Well, almost perfect.
I want to modify this code to specify a couple directories in FTP that should be ignored. For example, if I've got a folder called assets, when I go to http://example.com/assets/ the default DirectoryIndex page is displayed. Instead, I want this directory to be ignored -- I want index.php to handle /assets/.
TL;DR: How can I modify the above code to explicitly ignore certain existing directories (so that index.php handles them instead of the DirectoryIndex)?
Why not adding this below or before your code?
RewriteRule ^(assets/.*)$ /index.php/$1 [L]

How do I redirect all but one url to a script

I'm trying to get www.example.com and www.example.com/index.html to go to index.html, but I want all other urls e.g. www.example.com/this/is/another/link to still show www.example.com/this/is/another/link but be processed by a generic script. I've tried
RewriteEngine on
RewriteCond %{REQUEST_URI} !^index\.html$
RewriteCond %{REQUEST_URI} !^$
RewriteRule ^(.*)$ mygenericscript.php [L]
but it wont work, can someone please help?
Instead of testing what %{REQUEST_URI} is, you can instead just test if the resource exists:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* mygenericscript.php
This prevents your static resources (images, stylesheets, etc.) from being redirected if they're handled through the same directory your .htaccess is in as well.
What's probably happening now is that you're seeing an internal server error, caused by an infinite internal redirection loop when you try to access anything that isn't / or /index.html. This is because .* matches every request, and after you rewrite to mygenericscript.php the first time, the rule set is reprocessed (because of how mod_rewrite works in the context that you're using it in).
The easiest to do this is to install a 404-handler which gets executed when the server does not find a file to display.
ErrorDocument 404 /mygenericscript.php
or
ErrorDocument 404 /cgi-bin/handler.cgi
or similar should do the trick.
It is not that RewriteRule's can not be used for this, it is just that they are tricky to set up and requires in depth knowledge on how apache handles requests. It is a bit of a black art.
It appears as if you're using PHP, and you can use auto_x_file (x is either append or prepend:
http://php.net/manual/en/ini.core.php

Resources