I am relatively new to mod_rewrite, but have a site which I would like to have "pretty urls." Similarly to SO :).
I am attempting to have things like: "http://www.whatever.com/search/test" get rewritten to "http://www.whatever.com/search.php?q=test" and have had some limited success. I believe that content negotiation is getting in my way...
For starters here's my test .htaccess file:
RewriteEngine on
RewriteBase /~user/mysite/
RewriteRule ^search$ search/ [R]
RewriteRule ^search/([^/]*)/?$ search.php?q=$1 [L]
Which unfortunately, does redirect to search.php, but does not pass my param in the q variable. However this does work:
RewriteEngine on
RewriteBase /~user/mysite/
RewriteRule ^search$ search/ [R]
RewriteRule ^search/([^/]*)/?$ s.php?q=$1 [L] # here i've renamed the search.php to s.php to dodge the content negotiation that is happening..
In fact, if I remove the rules all together, I get the same result as with the first version of the file. So my conclusion is that since apache is happily redirecting "foo" to "foo.php" even without any mod_rewrite rules, that it must be the content negotiation that is taking care of it. (This is further verified by the fact if I renamed my foo.php to foo.html, it still will find the file if i just go to "foo").
So, the question is. How do I properly use mod_rewrite with regard to content negotiation? Can I disable it for a particular file? Is there a way to ensure that my mod_rewrite rules happen before the content negotiation happens?
If it is relevant, here is the conf file for the mod_userdir part of my apache conf (this test site is in my user's homedir/public_html):
# Settings for user home directories
<IfDefine USERDIR>
<IfModule userdir_module>
# UserDir: The name of the directory that is appended onto a user's home
# directory if a ~user request is received. Note that you must also set
# the default access control for these directories, as in the example below.
UserDir public_html
# Control access to UserDir directories. The following is an example
# for a site where these directories are restricted to read-only.
<Directory /home/*/public_html>
AllowOverride FileInfo AuthConfig Limit Indexes
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
<Limit GET POST OPTIONS>
Order allow,deny
Allow from all
</Limit>
<LimitExcept GET POST OPTIONS>
Order deny,allow
Deny from all
</LimitExcept>
</Directory>
# Suexec isn't really required to run cgi-scripts, but it's a really good
# idea if you have multiple users serving websites...
<IfDefine SUEXEC>
<IfModule suexec_module>
<Directory /home/*/public_html/cgi-bin>
Options ExecCGI
SetHandler cgi-script
</Directory>
</IfModule>
</IfDefine>
</IfModule>
</IfDefine>
Look for this option in your configuration.
Options +Multiviews
It will look for
/foo/test
/foo/
/foo
and redirect them to
/foo.[any file]
based upon if it exists and if it fits the content-type requested.
Change the option to this to disable this.
Options -Multiviews
Related
I have an htaccess rule in a folder that disallows php scripts:
<FilesMatch "\.(?i:php)$">
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
</FilesMatch>
That works just fine. The problem is that there is a specific php script I do want to be able to call (via ajax), so I want to add another rule after the deny that says "but if it is this specific file then allow it". I've done this successfully with other htaccess files in the folder that the file resides with something like this:
<Files ajax_file.php>
<IfModule !mod_authz_core.c>
Order allow,deny
Allow from all
</IfModule>
<IfModule mod_authz_core.c>
Require all granted
</IfModule>
</Files>
The problem I am having is that I want to grant a single file access from the same htaccess as the original FilesMatch that blocks all .php files. I can't seem to make it work with adding a file path and am wondering if there is a better way to go about this. The file in question would be a few folders deeper than than the htaccess file that denies the php scripts.
I can see that this is a really old post but, since there is no marked answer I figured I'd try and solve this.
The code you need should look like this:
<FilesMatch "\.(?i:php)$">
<IfModule !mod_authz_core.c>
Order allow,deny
Deny from all
</IfModule>
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
</FilesMatch>
That blocks access to all php files and set the priority as allow then deny, so that we can override the deny all later.
Then to allow access to the specific php file use this:
<Files ajax_file.php>
<IfModule !mod_authz_core.c>
Allow from all
</IfModule>
<IfModule mod_authz_core.c>
Require all granted
</IfModule>
</Files>
I can see from your OP that this isn't that different to your own, so I can only assume that by re-adding the Order declaration you are causing some weirdness to mess things up, since you already set the priorities in the initial [block all php] files declaration.
I think mod_rewrite is the best and easiest solution to your problem.
RewriteEngine on
# allow access to ajax_file.php
RewriteCond %{THE_REQUEST} ajax_file\.php [NC]
RewriteRule ^ - [NC,L]
#disallow access to other php files
RewriteCond %{THE_REQUEST} .+\.php [NC]
RewriteRule ^ - [F,L]
which linux distribution do you use? there are some htaccess configurators which make it easier to configure these files. you could write something like this
require valid-user
for every file that gets access.
There are some PHP files on an external drive which is mapped to the Z: drive on a Windows 10 machine. This code is in the httpd-vhosts.conf Apache file:
<VirtualHost *:8080>
DocumentRoot "Z:/files/xampp/htdocs"
<Directory "Z:/files/xampp/htdocs">
Options Indexes
Require all granted
</Directory>
</VirtualHost>
The task at hand is to allow .htaccess overrides for a file path within the path shown above. In the httpd.conf file the rewrite module is enabled. That line looks like this: LoadModule rewrite_module modules/mod_rewrite.so. I tried adding this code to the httpd.conf file:
<Directory "Z:/files/xampp/htdocs/miscellaneous/WebServiceExamples">
AllowOverride All
</Directory>
The Apache web server was stopped and restarted after making these changes. The code in .htaccess looks like this:
<IfModule mod_rewrite.c>
# turn rewrite engine on
Options +FollowSymlinks
RewriteEngine on
# map neat URL to internal URL
RewriteRule ^mobile/list/$ RestController.php?view=all [nc,qsa]
RewriteRule ^mobile/show/([0-9]+)/$ RestController.php?view=single&id=$1 [nc,qsa]
</IfModule>
However, when a URL that should be handled by the rewrite rule in the .htaccess file is entered in the Chrome address bar the result is an Object not found! Error 404. Where did I go astray?
EDIT:
Another thing I tried was putting httpd.conf back to its original state, then modifying httpd-vhosts.conf as follows:
<VirtualHost *:8080>
DocumentRoot "Z:/files/xampp/htdocs"
<Directory "Z:/files/xampp/htdocs">
Options Indexes
Require all granted
</Directory>
<Directory "Z:/files/xampp/htdocs/miscellaneous/WebServiceExamples">
AllowOverride All
</Directory>
</VirtualHost>
After stopping and restarting the Apache web server, the result is still the same as before:
Object not found! Error 404.
Figured this out. The configuration files were left in the state as described in the Edit section in the original post. The Troubleshooting section in this link was a helpful guide for determining that the configuration files were set up correctly.
This was entered as the URL in Chrome's address bar: http://localhost:8080/miscellaneous/WebServiceExamples/SimpleRestfulWebService/mobile/list. Notice there is no trailing forward slash. The rewrite rule was in .htaccess was written in such a way that made a trailing forward slash mandatory. When the rewrite rule lines were modified to make the trailing slash optional, then it worked fine. Here are the modified rewrite rules:
RewriteRule ^mobile/list/?$ RestController.php?view=all [nc,qsa]
RewriteRule ^mobile/show/([0-9]+)/?$ RestController.php?view=single&id=$1 [nc,qsa]
Trying to fix this .htaccess, so it can work on a SSL apache server. Before it was hosted on another Linux server (http://) and was working without problems, but when uploading the files to another Linux server with apache and SSL (https://), it stopped working. The main function is to hide the .php extension...
HereĀ“s what I was using:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
# To externally redirect /dir/foo.php to /dir/foo
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
RewriteRule ^ %1 [R,L,NC]
## To internally redirect /dir/foo to /dir/foo.php
RewriteCond %{REQUEST_FILENAME}.php -f [NC]
RewriteRule ^ %{REQUEST_URI}.php [L]
Thanks for your help!
So, .htaccess files may not be allowed, and by default on many systems they are not allowed. To see if .htaccess is allowed, make this your .htaccess:
BREAK IT!
That should be the only contents in your .htaccess. Attempt to load any page on your website, and if .htaccess usage is enabled, you would see "Internal Server Error" or possibly some other error, but you would not see your actual page.
If you do see the error, that's actually good and means .htaccess usage is enabled. If you don't see the error, it's likely that you will have to find your Apache .conf file and inside look for the line(s):
AllowOverride None
Change that to:
AllowOverride All
If after doing that you still can't use .htaccess, then there may be other apache related files that have "AllowOverride None". On that comes to mind is your virtual host file, and on my system that is located at /etc/apache2/sites-available/.
If you still have problems, check this out:
https://docs.bolt.cm/3.3/howto/making-sure-htaccess-works
Solution is for the issue, need to change in apache2.conf file after that it will works,
Change this file /etc/apache2/apache2.conf
update it same
OLD:
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
New Updated Code:
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
I had a similar problem. Apache 2.4.23 with .htaccess error 404 set up.
Using it with HTTP works fine; access it with HTTPS didn't work.
I seted AllowOverride All in the http.conf and error 404 wors well.
I am unable to get the rewrite working on Dispatcher module of AEM.
Following is what's happening with my configuration:
Dispatcher configuration:
Snippet of my httpd.conf
LoadModule dispatcher_module modules/mod_dispatcher.so
<IfModule disp_apache2.c>
DispatcherConfig conf/dispatcher.any
DispatcherLog logs/dispatcher.log
DispatcherLogLevel 3
DispatcherNoServerHeader 0
DispatcherDeclineRoot 0
DispatcherUseProcessedURL 0
DispatcherPassError 0
</IfModule>
<VirtualHost *:80>
ServerName mobile.example.com.au
DocumentRoot "/var/www/html/content/mobile"
RewriteEngine on
RewriteRule ^/(.*)\.html$ /content/mobile/$1.html [PT]
<Directory "/var/www/html/content/mobile">
<IfModule disp_apache2.c>
SetHandler dispatcher-handler
ModMimeUsePathInfo On
</IfModule>
Options FollowSymLinks
AllowOverride None
# AddType text/html .html
# AddOutputFilter INCLUDES .html
# Options +Includes
</Directory>
</VirtualHost>
......
Now, if I try to access the mobile.example.com.au/home.html, it shows up this 404 and says no content:
Not Found
The requested URL /content/mobile/home.html was
not found on this server.
Though I am able to hit the page directly by using the full path:
http://mobile.example.com.au/content/mobile/home.html and the page is rendered.
What am I missing here? Is it something to do with the Document root?
Also, how do we set the default landing page for mobile.example.com.au to show up home.html.
Can you please check rewrite logs to see how request is flowing?
Also, to set default landing page, you can use following rule
RewriteRule ^/$ /content/mobile/home.html [PT,L]
I believe you need to change this line:
DispatcherUseProcessedURL 0
to
DispatcherUseProcessedURL 1
... so that Dispatcher uses the rewritten URL for filter checks, cache structure, and the request to AEM. You'll also need to add the RewriteRule as Mohit suggested, probably as the first rule - but only if you want / to show the /home.html page.
See also: Adobe documentation on Dispatcher configuration
My Apache2.2 seems to work like this: when I request www.site.com/name first it is looking for folder /name/, if not found, next it is searching for file name.php.
But when I turn on RewriteEngine On in .htaccess and add RewriteRule ^name$ name2.php, then Apache still will be looking if there is folder or file name in spite of RewriteRule.
How can I give RewriteRule priority?
I found solution here http://httpd.apache.org/docs/2.2/content-negotiation.html - "Negotiation in Apache" section, "Multiviews" subtitle:
The effect of MultiViews is as follows: if the server receives a request for /some/dir/foo, if /some/dir has MultiViews enabled, and /some/dir/foo does not exist, then the server reads the directory looking for files named foo.* (...)
So in my case (I use mod_userdir), I edited /etc/apache2/mods-enabled/userdir.conf
<IfModule mod_userdir.c>
(...)
<Directory /home/*public_html>
(...)
#Options MultiViewes # I COMMENTED OUT THIS OPTION
</Directory>
</IfModule>
Now if I request www.domain.com/foo apache won't search for file named foo in directory! And from now on RewriteRule ^name$ another-name.php will work.