I am updating a php app, which currently does not use url rewriting. The aim is to hide file extensions. The general structure of the website is as follows
root/
index.php
login.php
page1.php
page2.php
page3.php
page4.php
page5.php
page6.php
page7.php
page8.php
subfolder/
index.php
validpage.php
images/
css/
The subfolder folder in the above structure is unique in that it is the only subfolder containing php files.All of the other files are in the root folder.
I have been through these questions Mod Rewrite and PHP and Mod-Rewrite or PHP router? and mod_rewrite, php and the .htaccess file
Updated htaccess. thanks to #thomasmalt
RewriteEngine on
RewriteBase /
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -l
RewriteRule ^.*$ - [NC,L]
# only rewrite if the requested file doesn't exist
RewriteCond %{REQUEST_FILENAME} !-s
# add .php to the url
RewriteRule ^(.*)$ $1.php
Problem now is I get a 500 instead of a 404 error, when I try to access a non existent page like localhost/inex.php. The Apache error log gives me the following errors. (I accessed localhost/index which loaded the contents of index.php , followed by which I loaded localhost/inex which gave me a 500 error.)
[Sat Sep 25 14:44:26 2010] [error] [client 127.0.0.1] File does not exist: C:/wamp/www/index
[Sat Sep 25 14:44:36 2010] [error] [client 127.0.0.1] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.
Update: found the answer to my question here. The question is resolved.
Apache has an option: Options +MultiViews
If you enable this, you don't need to place the file-extention in the url.
I'm not totally sure what you're trying to achieve, and i suspect, no disrespect intended, that you need to understand both mod_rewrite, and the way the webserver and php parses and executes files. I'm not sure how to answer without shooting over or under your level of understanding, but I'll try.
I can tell you what you're current .htaccess is doing: (pseudocode)
if REQUEST_FILENAME does not exist then
rewrite request to /index.php/<the request>
Since index.php is your php script that is executed and everything put in $1 is ignored.
That's why index.php is executed whatever you do.
What you could try to put in your .htaccess is this:
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^(.*)$ $1.php
That should take the request and try to append .php to the end of it. I haven't tested it unfortunately, but you should give it a try. The result should be something like this:
if request is "/news/article"
translate it to "/news/article.php"
And you should read the mod_rewrite documentation twice a day for a month, and buy the O'Reilly book about Regular Expressions.
And if you have administrator access to the development server you should look into
RewriteLogLevel
RewriteLog
From experience, it's harder than it sounds to retro-fit mod_rewrite into an existing site.
This isn't because mod_rewrite is hard -- actually it's relatively easy to set it up and get your new URLs working. The reason it's hard is because your existing site will have all the old URLs hard-coded into it, so you'll have to go through your code changing them all to point to the new URL format - this can be especially tricky if your code builds up URL strings dynamically. You'll need to do lots of testing to make sure you've picked up every possible variation and that they all still work.
Also worth mentioning that search engines and external sites will have historic links in to your site using the old URLs, so you can't get rid of them completely.
I know that doesn't answer your question, but I believe these are important things to consider before you start the project, because for an existing site it isn't the quick-fix that some people make it out to be.
It send you to root because you have RewriteBase / what defining default base ...
If you want to stay in subfolder just make another .htaccess in subfolder with RewriteBase /subfolder/
or remove it
you can make condition like you want
RewriteRule ^(([0-9]+)-)?page(-([0-9]+))?/?$ index.php?page=$2&id=$4 [L]
this will take you from www.abcd.com/2-page-3 to www.abcd.com/index.php?page=2&id=3
Code in index.php doesn't need to contain anything.
Related
I'm trying to change the URL of my website to show only the ID but It seems to not work...
I don't know why.. other commands of RewriteRule work well..
Actually the .htaccess file looks like belove
RewriteEngine On
RewriteRule ^/?([0-9a-zA-Z-]+)/$ article.php?articleId=$1 [L]
I want that it works like this:
Old_URL(to modify):
mywebsite.it/article.php?articleId=15
I want something like this:mywebsite.it/article/15
But the URL remains the same actually: always display this: mywebsite.it/article.php?articleId=15
Thanks in advance to every help :)
An internal rewrite will never change the URL visible in the browser. You are probably looking for an external redirection. Or better the combination of both:
RewriteEngine On
# externally redirect old URL
RewriteCond %{QUERY_STRING} (?:^|&)articleId=(\d+)(?:&|$)
RewriteRule ^/?article/?$ /article/%1 [R=301,L]
# internally rewrite new URL
RewriteRule ^/?article/(\d+)/?$ /article.php?articleId=$1 [END]
Those rules are meant to be implemented on top level. Best in the actual http server's host configuration. If you do not have access to that then a distributed configuration file will work (".htaccess") when located in the host's DOCUMENT_ROOT, but support for that needs to be enabled.
It is a good idea to start out using a R=302 temporary redirection and only change that to a R=301 permanent redirection once you are happy with how things work. That prevents caching issues on the client side.
I have a basic MVC system that is sending POST data to URLs such as
admin/product/add/
But this is giving me an error
Forbidden
You don't have permission to access
/admin/product/add/ on this server.
Additionally, a 404 Not Found error was encountered while trying to
use an ErrorDocument to handle the request.
The RewriteRule is simply
RewriteRule ^(.*)/$ index.php?uri=$1
Last time I saw this on a server changing file/directory permissions to 755 seemed to fix it but not this time. I have never really understood the reason for the error so was hoping someone may be able to provide some more information?
You have 2 errors:
You don't have permission to access /admin/product/add/ on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
The 2nd one is quite certainly a consequence of the same bug. You may have something in your apache configuration which remove 404 errors from default http server handling and push it to your php application, if this php application was working we would have a nice 404, but...
The first one tells you your php application is not running at all.
So. This first error tell us that apache did try to directly access the directory /path/to/documentroot/admin/product/add/ on your server and to produce a listing of it (well a listing of the directory content would be done only if apache were authorized to do so). But of course this is not a real directory on your server. It is a virtual path in your application. So apache ends up with a 404 (which leads to error 2).
The application handles a virtual path, apache does not manage it. The RewriteRule job is to catch the requested path before apache is trying to serve it and give it to one single php file (index.php) as a query string argument.
So... this rewrite rule was not applied. Things that could prevent this rule to be applied are numerous:
mod_rewrite not activated: is the module present and enabled (RewriteEngine on)?
syntax error: mod rewrite syntax is quite hard to read, sometimes really complex. But here it seems quite simple.
The RewriteRule resulting file is maybe not a valid target for apache. If the index.php file is not present in the DocumentRoot, or not readable by the apache user, then apache will fail. Warning: having a file readable by the apache user means having read rights on the file but also execution rights on all parents directories for the apache user. This is where your classical chmod/chown solutions are fixing the problems.
The rule must be in a valid configuration file. Is this rule in a an apache configuration file, inside a Location or Directory section? Or maybe in the global scope -- this may alter the rewrite Rule syntax--. Or is it in a .htaccess file? If it's a .htacces does apache reads the .htacces files and are mod-rewrite instructions allowed there (AllowOverride None). Isn't there others .htaccess files taking precedence?
So to fix the problem:
If you have an apache version greater than 2.2.16 you can replace the RewriteRule by FallbackRessource /index.php to check that this does not come from a mod-rewrite problem.
try to directly request index.php, so that at least a direct request to this file does work
try to directly access a valid ressource on the documentRoot (a txt file, an image, something that should not be handled by the rewrite but directly served)
check that if any of your virtual paths could map real physical paths Apache is not trying to serve the physical one (like when you write a RewriteCond %{REQUEST_FILENAME}-d) but really push the path to index.php
check apache error logs.
debug mod_rewrite with RewriteLog and RewriteLogLevel
collect facts, settings and tests, and then push that to SO or Servfault.
So the problem is quite simple: the php application is not receiving the request. But there are a very big number of ways to end in this state. The message in itself is not very important. The only way to find the error is to check all parameters (or to have years of bug fixing experience and developing a pre-cognitive intuition organ for lamp bugs -- usually a beard --, like admins). And the only way for us to help you is to find strange facts in a big list of configuration details, this is why good questions contains a lot of informations, even if all theses informations looks simply "classical" for you.
EDIT
To clarify the problem you should edit your answer, track the POST requests with tools such as Chrome developpers tools or firebug (keep the network tracking in record mode to catch several POSTS) or try to replay the post with Live HTTP headers reply. You should try to isolate the problematic POST and give us details. Debug is not magical.
Now I know one magical random POST failure. It's the empty GET url bug. It could be that (or not). If you have one empty GET url hidden somewhere (<IMG SRC="">, url() in css, or an empty LINK in headers for example. As theses hidden POST are defined in HTTP as "replay-the-request-which-launched-the-source-page, and some browsers even replay the POST that gives you the page if they found one. This could lead to broken hidden POSTS.
It could be also that the POST is not sent to the right server. Hard to say. So please collect informations from your comments, add some more network analysis and edit the question which is now really containing not enough facts.
Try this:
RewriteCond %{REQUEST_METHOD} =POST
RewriteRule ^(.*)/$ index.php?uri=$1
Use this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?uri=$1 [L]
Also use only www or non-www domain but not both at the same time. Redirect users with htaccess where you would like like to...
NonWWW to WWW:
RewriteCond %{HTTP_HOST} !^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
WWW to NonWWW:
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^www\.(.*)$ http://%1/$1 [R=301,L]
This one is a little confusing to me.
I'm running a LAMP server with Zend Framework. I've spent a lot of time going over my error logs to try and clean-up any programming errors/bugs.
Most of my specific site errors are done but I looked into my general Apache error log:
/var/log/apache2/error.log
And I'm seeing a lot, almost constant, errors for "File does not exist" like the following (simplified for brevity):
[date] [error] [client #:#:#:#] File does not exist: /var/www/sites/[website folder]/public/explore
[date] [error] [client #:#:#:#] File does not exist: /var/www/sites/[website folder]/public/where-to-buy
[date] [error] [client #:#:#:#] File does not exist: /var/www/sites/[website folder]/public/products
And so on. These folders do not exist because all requests are suppose to be redirected into the index.php file and handled by Zend Framework. The actual controllers and actions exist, such that anyone going to:
http://www.example.com/explore
or
http://www.example.com/where-to-buy/
will get the correct page via Zend Framework.
But I'm not understanding why all these errors are occuring?
If figure it might have something to do with the .htaccess file that redirects most requests (excluding style sheets, documents, images, etc) to the index.php script. This is what mine looks like:
RewriteEngine On
# make sure all requests go to 'www' sub-domain
RewriteCond %{HTTP_HOST} ^example.com
RewriteRule (.*) http://www.example.com/$1 [R=301,L]
# Zend Framework, redirect requests to index.php
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
Is Apache trying to resolve the request via an actual directory first and then passing the request to index.php? Which causes the error request?
I'm also not sure why this is getting dumped into the default error log, instead of the error log or the specific site. In other words, I have error logs for each domain such as "example.com_error.log". That might be another indication to the issue. It might be a sequence thing as "error.log" is tired to a "default" site.
Thanks for any insight!
Fozzy
From Regilero:
the fact this is going to the default log is effectively a good hint
on the problem, check the related access.log. Maybe some requests made
on a DNS name not handled in your virtualhost or by web clients not
using HTTP 1/1 (so with no host header) – regilero Oct 19 '11 at 22:52
I was able to compare the access.log with the error.log to investigate my issues.
It was awhile ago but I believe the issue was due to some script going directly to the server via an IP address and trying to use the directory structure from one of the virtually hosted domains.
There is a way I was thought to do things but I want to get a little bit advanced. To pass variables and stuff through links, i do this
http://www.fayimora.com/games.php?catID=8
That works fine but am working on a more professional site now and I think that won't be nice enough. I would prefer links like
http://www.fayimora.com/games/
I know that to achieve this I just need to create subfolders under the main folder and then rename games to index aswel.
Now the only problem is how do i pass variables? Like above i passed a variable catID with value 8. Now if i want to do this giving that i dont want to show the user the variabes been passed in the link, ow do i go about this?...
I know it might be a little bit complicated but i really need it..
I was told to look at this site >However I got stuck with this
Thu May 19 15:00:28 2011] [warn] module rewrite_module is already loaded, skipping
httpd: Syntax error on line 127 of /Applications/XAMPP/xamppfiles/etc/httpd.conf:
Thanks for the help in advance and please tell me if something somewhere isin't clear
Thanks
Here is how I have done this in the past. This uses a .htaccess file and Apache's mod_rewrite module:
<IfModule mod_rewrite.c>
DirectoryIndex index.php
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?path=/$1 [L,QSA]
</IfModule>
These rules essentially state that, for any path to my server that is not a request to an existing file or directory, rewrite that path to go through index.php. Thus, a request such as /games/8/ will now be passed as index.php?path=/games/8. You can then parse this path in index.php and call the appropriate controller for your view.
I just inherited a website built in PHP. The main page of www.mysite.com has a href to www.mysite.com/index/35.html somewhere in the page. In the site's root directory and its children there is no document 35.html.
The number 35 is actually an id found in a DB which also holds the html contents of the page.
If I load URL: www.mysite.com/index.php?id=35 the same page loads.
How does PHP know how to automatically convert
/index/35.html
to
/index.php?id=35
EDIT
Based on the answers, I have found a .htaccess file containing rewrite instructions that would explain the functionality.
However, IIS doesn't seem to (or is not configured) know how to use this. (probably because this is an Apache feature?)
So this begs the following question: Is there a way to configure IIS to work with this?
it will be done usign URL Rewriting using .htaccess - should be in the webroot.
It may look something like:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
May have other bits, but what this basically tells apache is to send anything that DOES NOT physically exist to index.php
It doesn't. There is a mod_rewrite rule that rewrites from /index/foo to /index.php?id=foo, either in a .htaccess file somewhere or in the httpd configuration itself.
RewriteEngine On
RewriteRule ^index/([\d]+)\.html /index.php?id=$1 [NC,L]
This is off the top of my head. Any browsers trying to load an address starting with index/ has any number ending in .html will be internally redirected to index.php?id= whatever the number is.
Edit: Just saw that your working on IIS. This probably won't work for you. Sorry.
I think you will be using .htaccess to redirect all requests to index.php. From there You can pass the query string a routing class, which will parse the url and identify the unique ids.
In this case we can say like, your routing class will parse the request /index/35.html to indexController, indexAction, id=35. now you can pass this id to the model to get corresponding page contents
NB : Here I a am assuming you are using mvc pattern. Anyway it can be treated in your own way, with the concept remaining the same. Hope this make sence.