.htaccess RewriteRule causing 403 Forbidden - php

I'm trying to install the Recess PHP framework on my web host (Dreamhost). It includes the following .htaccess:
Options FollowSymLinks
RewriteEngine On
RewriteRule ^([^.]+)$ $1.html [QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ bootstrap.php [QSA,L]
This works fine on my machine (XAMPP 1.7.7 on Windows 7) but results in 403 Forbidden errors on some files my web host. All directory permissions are set to 755 and all file permissions are set to 644. PHP runs under the same user that owns the files.
The following URLs result in 403s:
http://test.dd.moofz.com/
http://test.dd.moofz.com/recess-conf.php
http://test.dd.moofz.com/index.php
http://test.dd.moofz.com/bootstrap.php
http://test.dd.moofz.com/MIT-LICENSE
The following URLs don't:
http://test.dd.moofz.com/.gitignore
http://test.dd.moofz.com/httpd_logo_wide.gif
http://test.dd.moofz.com/README.textile
http://test.dd.moofz.com/the-book-of-recess.pdf
What would cause this to happen?

As it turns out, I needed to change the line:
Options FollowSymLinks
to:
Options +FollowSymLinks

Not familiar with that framework, but it looks like either there are some lines elsewhere or it may need tweaking.
Though I admittedly am no mod rewrite expert, looks like first line is directing all requests to request_file.html, then on line 2 if the file does not exist it calls up boostrap.php on line 3.
Your problem may lie in boostrap.php, see what happens in that script and how the request is handled. A debugger may be useful at that step. Although you may get this to work, it seems to me it may not be optimal as is. For instance, I believe usually there is a ruleset that avoid havings .gif, .jpg .css directed to your routing script. Something like this:
RewriteCond $1 !^(favicon\.ico|favicon\.png|media|robots\.txt|crossdomain\.xml|css|js)
This avoids the overhead of having php handle the requests for those types of files. There would even be more things to consider for robust application production usage, just tweak your rules so everything is routed proper and things should be fine.

Related

.htaccess url rewrite not passing parameter - could there be apache settings somewhere that is preventing this?

Okay, so this problem has completely stumped me and the other devs I work with. Here is the rundown:
I have a local dev environment setup with Mac Apache2 pointed at /Users/myusername/Sites/
Within /Sites I have two folders, /site-1 and /site-2, both of which have virtual hosts pointed at them site-1.dev & site-2.dev. Both site-1 and site-2 are running local installs of PerchCMS.
Within /site-2 I have an .htaccess file which I am trying to set up a URL rewrite that takes the URL /detail/slug-here and translates it into /detail.php?s=slug-here
I have tried the following rewrites (at the suggestion of PerchCMS support) and both have failed to pass the s param:
RewriteRule ^detail/([a-zA-Z0-9-/]+)$ detail.php?s=$1 [L]
RewriteRule ^site-2/detail/([a-zA-Z0-9-/]+)$ /site-2/detail.php?s=$1 [L]
Additional info:
Yes mod_rewrite is enabled in apache... in the same .htaccess file it totally works if I do a simple rewrite like this...
RewriteRule dangerzone.html index.php
One odd behavior that I've noticed is that if I remove everything from .htaccess I can still pull up detail.php by pointing my browser at /detail/test-item-1...(yes I have restarted my server) so its behaving as if there is still some sort of rewrite in place and loading detail.php sans param just as it continues to do with the rewrite in place - is this a clue that there is something off somewhere else in my server config? Note, RewriteRule dangerzone.html index.php does NOT work once it is removed from .htaccess.
Have this code in your site root .htaccess (inside /site-2/):
Options -MultiViews
RewriteEngine On
RewriteRule ^detail/([a-zA-Z0-9/-]+)/?$ detail.php?s=$1 [L,QSA,NC]
Important is to turn off MultiViews options here. Option MultiViews is used by Apache's content negotiation module that runs before mod_rewrite and makes Apache server match extensions of files. So /file can be in URL but it will serve /file.php.

Go to file by link

I store data in text file.
And when user enter in address bar something like
my_syte.com/aaa - (without extension)- I need to file_get_contents aaa.txt file
my_syte.com/bbb - I need to file_get_contents bbb.txt file
Please advise the most powerful way of do it. Apache server.
Thanks
On Apache servers you can use mod-rewrite in .htaccess file:
RewriteEngine on
RewriteRule ^([a-zA-Z]+)$ /$1.txt [L]
if your files can contain - or _ or numbers then use:
RewriteEngine on
RewriteRule ^([a-zA-Z0-9_-]+)$ /$1.txt [L]
On nginx servers it's more complicated but some of them works with .htaccess. On other servers there may be entirely different approach. It's hard to help you without more informations.
As you said it's Apache, then use examples above. Either edit or create .htaccess file on your webroot (directory which is accessed by domain). First check if it were there (could be hidden) and if it exists then only edit it (add lines at the top).
If it doesn't exist, then create one by yourself.
Can you please give us some insights about your server? Apache nginx?
In Apache, you can achieve that with url rewriting.
Enable mod_rewrite in apache
Put the following line of code in .htaccess on the same location of my_site.com/
RewriteEngine on
RewriteRule ^/foo$ /foo.txt [PT]
to make it generic
RewriteEngine on
RewriteRule ^/*$ /foo.txt [PT]
Maybe I am wrong in sytax based on your specific server configuration. You need to make the best possible regular expression for this case.

Laravel 4 on PHP built-in web server (CGI) instead of Apache

I am trying to run laravel4 on a service that cannot use Apache or nginx.
everything is good till I wanted to use Routes on my project.
I've tried using /index.php/... on the URL but could not make this work.
is there any way to force laravel not to use .htaccess file or any ways to use raw PHP routing?
Try setting the "application.url" option in one of configuration files, probably in app/config/application.php or application/config/application.php:
https://github.com/laravel/laravel/blob/4cb904f44d24f856ec9c1040d2198ed8f009723b/application/config/application.php
Set it to http://127.0.0.1:54007/index.php. Now when laravel creates url it will use this as a root and the final urls should be like http://127.0.0.1:54007/index.php/account/signin.
Also you need to modify PHP Desktop settings so that it uses a fixed port. Edit settings.json file and set it like this:
"web_server": {
"listen_on": ["127.0.0.1", 54007],
In laravel's .htaccess I've found this:
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
So it should work fine to add "/index.php" to root url, because this is what apache's mod_rewrite does.
If something doesn't work, take a look at some other files named "url.php", "uri.php".
Let us know if that works.
EDIT.
You may also try setting root url to "index.php", without the "http://". This way it wouldn't be required to set a fixed web server port.
UPDATE
There was a bug in Mongoose web server in PHP Desktop, that prevented urls like "index.php/company/5" from working properly. See the __fix_mongoose_env_variables() php function in Issue 137 that fixes it:
https://code.google.com/p/phpdesktop/issues/detail?id=137

POST request to SEO URL Forbidden

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]

How do I make this mod_rewrite scheme work with PHP as CGI/FCGI?

Here's the contents of .htaccess:
Options -Indexes
RewriteEngine On
RewriteBase "/"
# Disallow direct access to PHP files.
RewriteRule ^(.*)\.php$ $1 [F,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(?<!common/dispatch\.php/)(.*)?$ common/dispatch.php/$1 [NS,L]
Essentially I have all my pages (PHP files) arranged as they would be for direct access without mod_rewrite but I also have dispatch.php in a directory called common, through to which I want all requests to be directed so that I can do some processing before the page script is executed.
It's basically the same idea as used by most frameworks, except I want the page hierarchy to be at the top level and the dispatch script to be kept out of the way with some other bits and pieces in its own subdirectory.
This script works fine on my development machine (which is running PHP as mod_php), but on the production machine it produces an error saying "No input file specified." if running under FCGI. Under normal CGI it works for the most part but if, for example, I go to /foo/bar (with trailing slash missing) and /foo/bar is a directory in the docroot, it sends me to /foo/bar/?/foo/bar. The rest of the script works fine but I don't really want my URIs getting mangled like this, and ideally I'd like to be able to use FCGI as well.
A potential fix for the problem with FCGI seems to be to put the matched $1 in the query string (i.e. after a ?), but this causes all sorts of other odd behaviour that I haven't been able to fix. Is there a straightforward way of fixing this?
Would it not be easier just to use the auto_prepend_file directive in php?

Categories