How Mod Rewrite interacts with logs - php

I'm using CakePHP, and I'm not understanding how mod_rewrite affects custom logs.
In .htaccess:
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L,NE]
(index.php is where CakePHP starts to route the request)
And then in /etc/apache2/apache2.conf:
LogFormat "%U %q" custom
CustomLog "/var/log/apache/custom.log" custom
But for a request /foo?bar=1, I see
/foo ?url=foo&bar=1
I don't understand what is happening.
It seems like the log happens before rewrite with %U, but AFTER rewrite with %q. Is this expected behavior? Can I change it? (There are severe limits on my log size, and logging every path twice is undesirable.)

I'm not sure what Apache is doing here, but I can get CakePHP to work without using the query string at all:
RewriteRule ^(.*)$ index.php [QSA,L,NE,E=URL:$1]
And then in index.php:
$_GET['url'] = substr(getenv('REDIRECT_URL'), 1);
This seems a lot less hacky anyway than the normal CakePHP way.

This is not the way to go about it to look what mod_rewrite is doing; you need to see whats going on in the rewrite process. You need to enable rewrite log in order to accurately see what's going on in there:
The code is:
RewriteLog "/usr/local/var/apache/logs/rewrite.log"
You'll need to then restart apache considering you have the rewrite module enabled. This is going to help you in debugging. In addition, you have to put this in the virtual host entry.

Related

How to clean a url with php without using htaccess?

I have a problem with a project I'm doing with PHP and it's in the URLs.
When I load a script like index.php everything works fine, the problem is when I load a script that is located within two or more directories.
In the URL the scripts with the routes begin to be enmeshed
Here is an example of the problem I have
I need to load a script, even if it is in several levels of nesting, make its functionality and in the url is reflected as:
I need to have something like this
1:
I thank you in advance.
Regards
You can't use PHP to achieve this. PHP is not responsible for determining if PHP (let along a particular PHP script) will handle any given URL.
You have to configure your webserver to do it. Since you mention .htaccess but provide no further information about your server, I'm going to assume you are using Apache HTTPD.
For Apache, that means using mod_rewrite, Alias or something similar. You can put the configuration for those tools in .htaccess, but you don't want to and the documentation advises not to use them.
So put your mod_rewrite or Alias configuration in the main Apache configuration.
You're going to need an htaccess rule no matter what. However, it doesn't have to be a mod_rewrite rule. The reason you need this rule is because PHP is not responsible for the routing - it is merely responsible for the execution of your script.
The point of the rule is to direct apache and instruct it to execute the right script (in your case, script32.php) while keeping the request uri as intact as possible.
There are two ways around it, basically.
Way 1 (cleaner): mod_rewrite
This is pretty straightforward, the set of rules you need are as follows:
# If the requested file name is a valid file/inode
RewriteCond %{REQUEST_FILENAME} -f [OR]
# ...or a directory
RewriteCond %{REQUEST_FILENAME} -d
# ...then throw them straight on it
RewriteRule (.*) - [L]
# ...otherwise, redirect to script32.php with the full content of the request in query string
RewriteRule (.*) /welcome/script32.php?$1 [L]
The requested URL is now in $_SERVER['QUERY_STRING'] and you can now do whatever you like with it in PHP
Way 2: catchall
This does not rely on mod_rewrite and may therefore be slightly faster. However, technically, it's a cheap hack. The way around it is as follows:
ErrorDocument 404 /welcome/script32.php
The requested URL can now be found in $_SERVER['REQUEST_URI'] and is available for parsing in PHP. However, with this, you've also disabled "legit" 404 errors from being generated through apache - and should make sure to obey proper behaviour in PHP to compensate.

Apache mod_rewrite can't pass variable

I'm having a hard time figuring out why my rewrite rules work perfectly online (the site is up and running), but fail when I'm trying to run a local copy on my mac. I'm not using MAMP o LAMP and I have installed apache and php manually. Apache is 2.2.26 and php is 5.4.20.
There are more rules in my .htaccess file, but the ones I'm concerned about are these two:
RewriteRule ^category/([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/?$ category.php?slug=$1&page=$2 [L]
RewriteRule ^category/([a-zA-Z0-9_-]+)/?$ category.php?slug=$1 [L]
Basically the variables are not being passed to the php file. Besides this, the rule below works perfectly fine! Even on my local setup I can't see any difference except the fact that I have two rules beginning with "^category/"
RewriteRule ^project/([a-zA-Z0-9_-]+)/?$ project.php?slug=$1 [L]
Any clue why this works online (ubuntu) but fails locally?
I'm going to guess that you have multiviews turned on. This causes mod_negotiation to fuzzy match requests to file-path resources. So when it sees /category/something and sees the file category.php, it sends the request right to the php file (in this case, ala PATHINFO) thus completely bypassing mod_rewrite.
Try turning multiviews off:
Options -Multiviews

.htaccess direct domain to subdirectory

I am trying to redirect www.example.com to /example/ on my webserver, but it appears to only be redirecting the index.php page. An additional issue is the main file displays as http://tunedu.com/tunedu/ when I would like it to display as tunedu.com
Live example:
This page works: http://tunedu.com/tunedu/
This page doesn't work: http://tunedu.com/school.php?id=75
Any regex changes I do try end up just breaking everything. The .htacess code is this:
RewriteEngine on
RewriteRule ^$ /tunedu/ [L]
Thanks.
The proper way to do such a thing is by setting VirtualHosts on your webserver (either Apache, nginx or another...). Using htaccess for this seems quite painful.
Assuming you're using Apache, here's a useful link: http://httpd.apache.org/docs/current/vhosts/examples.html
I'm not sure why you are not using VirtualHost to set that up.
But in case you want to go the mod_rewrite way here is an useful link:
http://httpd.apache.org/docs/2.2/rewrite/vhosts.html
I hope that helps.

htaccess rewrite rule not passing url vars when script file is same as rewrite directory

I'm trying to create nice urls with .htaccess files and have come across a weird issue.
I want to change portfolio.php?id=2 to /portfolio/2/
seems pretty simple solution
RewriteRule ^portfolio/([0-9]+)/$ /portfolio.php?id=$1 [L]
this does redirect to the correct script but when i try and run <?=$_GET['id'];?> it is undefined. but if change the script to something that does not equal the fake directory it works.
RewriteRule ^portfolio/([0-9]+)/$ /portfolioitem.php?id=$1 [L]
and just to make sure that it wasn't being caught by any other rules I tested this
RewriteRule ^portfolioitem/([0-9]+)/$ /portfolioitem.php?id=$1 [L]
and again it failed to pick up the id paramater!
any ideas?!
Cheers
This sounds suspiciously like a Multiviews related problem coupled with some PATH_INFO. The Multiviews option is part of mod_negotiation and it will try to match a requested URL path to a file path. It sees:
/portfolio/2/
And sees that there's a /portfolio.php file in the filesystem and assumes that this is what you want (which it is, but not in the same way). I'm willing to bet that instead of looking at $_GET['id'], which is blank of course since there are no GET params, if you look at $_SERVER['PATH_INFO'], you'll see it set to /2/. This is equivalent to going to:
/portfolio.php/2/
where the /2/ part gets passed to portfolio.php as part of the PATH_INFO. And since mod_negotiation is further up in the processing pipeline than mod_rewrite, your rewrite rules never get applied.
Try turning off multiviews. You can do this in your htaccess file using the Options directive (assuming your host has allowed Options):
Options -Multiviews

Apache Url Rewriting won't work

In the httpd.conf file I have AllowOverride FileInfo. In the .htaccess file in top level of my webserver with all the other files, I have this:
RewriteEngine On
RewriteRule ^downloads/?$ index.php?page=downloads [L,NC]
But it doesn't work. mywebsite/downloads and mywebsite/downloads/ always give a 404 not found. Any idea why? Thanks. (mywebsite/index.php?page=downloads does work).
And I'm restarting apache every time I change it.
And when I put the code above in httpd.conf, the website won't even load at all, just blank, spinning safari wheel forever.
Its fine if I just do RewriteEngine On, but if I do anything else (RewriteBase, RewriteRule), the web browser spend ages trying to load and finally giving this error:
Safari can’t open the page “http://mk12.gotdns.com/” because the server where this page is located isn’t responding.
Anyone have any idea what's wrong?
EDIT: I'm able to make, for example, css files forbidden with rewrite, and it works, but any rule that goes from downloads to index.php?page=downloads makes the server not respond (see above), it doesn't matter what page, the website won't load at all. Any ideas..?
The best way to debug rewrite rules is to enable rewrite logging so you can see what's going wrong.
It Worked!! I was putting the code in the wrong spot. It was in httpd.conf, but at the end. Move it into <Directory> and its good. Thanks for your help!
EDIT: Also, I found that It won't work if the flags are like this: [L, NC]. It has to be [L,NC] (no spaces).
So the two problems where that it wasn't inside <Directory "/Library/WebServer/Documents">, and there were spaces between the flags. Hopefully this will help someone else in the future.
Have you tired adding a slash in front of the "download" like below
RewriteRule ^/downloads/?$ index.php?page=downloads
EDIT: Try the code below:
RewriteEngine On
RewriteBase /
RewriteRule ^downloads/?$ /index.php?page=downloads
I would try removing the trailing slash and question mark after downloads, and the leading slash before index.php.
RewriteEngine On
RewriteBase /
RewriteRule ^downloads$ index.php?page=downloads.

Categories