The weirdest thing. Both rewrite rules are working on our Test server but the second one locations is not working on Production and adds a / at the end of locations/ for some reason. The configuration is the same on both servers.
I am trying to simplify the URL without renaming the file. So that if the user enters site.php/locations it will load the content of the redirect page but retain the simplified URL
Any ideas as to why the locations redirect is not working?
RewriteEngine on
RewriteBase /
// The next two are statements are just for context. They preceded the faq and locations forward
RewriteCond %{REQUEST_URI} ^/index.php$
RewriteRule (.*) / [R=301,L]
// The two rewrites that I want
RewriteRule ^faq$ /faq-mailbox-account.php [NC,L]
RewriteRule ^locations$ /choose-digital-mailbox-location.php [NC,L]
... on Production and adds a / at the end of locations/ for some reason
This will happen if locations exists as a physical directory on the filesystem. (Or existed and the response was cached.)
If you request /locations and /locations exists as a physical directory then mod_dir will issue a 301 external redirect to append the trailing slash - ordinarily, this is necessary in order to "fix" the URL.
This external "redirect" by mod_dir will happen regardless of whether your rule matches or not*1, since it is "only" an internal rewrite and not another redirect. (*1 In fact, it does match and the rewrite does occur, but it is effectively overridden by the mod_dir redirect.)
You could append an optional slash to your RewriteRule pattern, eg. ^locations/?$ - but the redirect will still occur first if you are requesting /locations without the trailing slash. You would need to request a URL that already contains the trailing slash.
You could prevent mod_dir from appending the trailing slash using DirectorySlash Off, however, this potentially has other implications for your system.
Note also, that since this is a 301 (permanent) redirect, it will likely be cached persistently by your browser. So, if the /locations directory has since been deleted on the server, the browser will still redirect the user until all client-side caches have been cleared also.
The configuration is the same on both servers.
So, there is (or was) a /locations directory on both servers?
If the configuration is the same on both servers then you would get the same response, so there must be some difference. Or, there is a client-side caching issue.
So that if the user enters site.php/locations
I assume you meant site.com/locations - otherwise, the directives you posted have no hope of working, as they simply won't match.
The problem was due to a symbolically linked drive on Prod
Related
I did some .htaccess code to make PHP API route.
It's working in apache ( local server )
Options -MultiViews
RewriteEngine On
#What does this mean??
RewriteRule ^(.+)$ quizAPI.php?url=$1 [QSA,L]
But when I moved mine code to server it's not working because it not an apache.
I am trying to make API URL Like this :
example.com/users/get/
#What does this mean??
RewriteRule ^(.+)$ quizAPI.php?url=$1 [QSA,L]
Not quite sure of the difference between Apache and LiteSpeed in this respect (perhaps a difference in how the request is mapped to the filesystem?), however, this is only working on Apache arguably by "chance". The reason being, when you request /users/get/ the above rewrites as follows:
Request /user/get/
Rewrite (1st pass) to quizAPI.php?url=user/get/
Rewrite process then starts over (due to the L flag)
Rewrite (2nd pass) to quizAPI.php?url=quizAPI.php&url=user/get/ (due to the QSA flag)
Rewrite process then starts over (due to the L flag)
Rewrite (3rd pass) to quizAPI.php?url=quizAPI.php&url=user/get/ (again)
Rewriting process stops since the URL has passed through unchanged.
This still "works" (on Apache) since the url parameter (as read by your PHP script) is still user/get/ (the 2nd instance of the url param overwrites the first in the $_GET array). And there is no rewrite-loop. LiteSpeed, however, might be triggering another pass by the rewrite engine (causing a "loop").
However, we need to prevent that second pass by the rewrite engine (on Apache as well) and I would expect this would resolve the issue on LiteSpeed as well.
One way is to prevent the rewrite from occurring when quizAPI.php is requested. For example:
RewriteCond %{REQUEST_URI} !^/quizAPI\.php$
RewriteRule (.+) quizAPI.php?url=$1 [QSA,L]
However, this still rewrites all static assets (CSS, JS, images, etc.) to your script (which I'm assuming must "OK", since it "works" on Apache), but this might need further modification in the future.
Alternatively, if your URLs that you pass to quizAPI.php don't contain dots (that otherwise delimit file-extensions) then it would be simpler to only match URLs that don't contain dots instead (which avoids the need for the preceding condition). For example:
RewriteRule ^([^.]+)$ quizAPI.php?url=$1 [QSA,L]
And this naturally avoids rewriting requests for your static assets as well.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
i am newbie of php
How to create simple remove .php extension with .htaccess page?
My aims is type this url http://site/Test
it can visit hello.php content, anyone know how to do that?? thx
I have one folder that call "Test", there are two file on "Test" Folder
Test/
-hello.php
-.htaccess
hello.php
<?php echo "Hello World"; ?>
.htaccess
RewriteEngine on
RewriteRule ^(.*)$ $1.php
finally, it is not successful
it display the following error message
**Internal Server Error**
The server encountered an internal error or misconfiguration and was unable to complete your request.
anyidea to solve this??? Thank you very much
My aims is type this url http://site/Test it can visit hello.php content, anyone know how to do that?
This isn't simply "file extension removal". If it was then /Test would serve the content from /Test.php. In your example, you are wanting to serve the contents of an entirely different file.
Rewriting the request with mod_rewrite
Since you are requesting a directory (/Test/) and wanting to serve a file from within that directory and the .htaccess file itself is actually located in that directory, you would need to write your RewriteRule like this:
RewriteRule ^$ hello.php [L]
In .htaccess (directory context), the RewriteRule pattern matches the URL-path relative to the location of the .htaccess file. So, in this case the URL-path we are matching against is simply an empty string, ie. ^$, since we are wanting to match /Test/<nothing>.
Likewise, when the susbtitution string (ie. hello.php) is relative (as it is here), it is relative to the location of the .htaccess file. So, in this case it effectively rewrites the request to /Test/hello.php (it's actually the absolute filesystem path, eg. /var/www/user/public_html/Test/hello.php - after the directory-prefix is added back).
Additional issues with this example
Since you are rewriting a request that would otherwise map to a physical directory there are a couple of potential issues you need to be aware of...
You should request the directory with a trailing slash, ie. /Test/, not /Test (as you stated in your initial example), otherwise mod_dir will issue a 301 redirect to append the slash before your rewrite is successful.
(There are ways to avoid the trailing slash, but this does increase the complexity and requires further manual rewrites.)
An additional complication occurs if there is a DirectoryIndex document in this subdirectory. eg. /Test/index.php. In this case mod_dir issues an internal subrequest to the DirectoryIndex document (eg. index.php) and this takes priority over your internal rewrite. (Your rewrite does still occur, but mod_dir "wins".) If this is the case then you can rewrite the DirectoryIndex document instead of an empty URL-path. For example:
RewriteRule ^index\.php$ hello.php [L]
This is perhaps counter-intuitive, as we are now rewriting the internal subrequest that mod_dir has issued in a later pass through the file.
You could handle both scenarios and make index.php optional. For example:
RewriteRule ^(index\.php)?$ hello.php [L]
RewriteRule ^(.*)$ $1.php
Your example would result in an internal rewrite loop (500 Internal Server Error response) since the pattern ^(.*)$ also matches the rewritten URL and it gets stuck in an endless loop. (The rewriting process doesn't just consist of a single pass through the file. The process repeats until the URL passes through unchanged.)
(Incidentally, this IS an extensionless URL type of rewrite, but it doesn't help you achieve what you stated in your example.)
There are various ways to prevent this "endless loop":
Use a more specific regex, that won't also match the rewritten URL. eg. a regex that excludes a dot such as ^([^.]+)$.
Use a RewriteCond (condition) directive that prevents the rule being triggered on the rewritten URL. eg. Exclude .php files or check that the request does not map to a file, etc.
Use the END flag on the RewriteRule to stop all further processing by the rewrite engine.
Alternative - change the DirectoryIndex
Instead of using mod_rewrite, as explained above, to internally rewrite the request, we could instead change the DirectoryIndex document.
This only works in this particular case where you are requesting a directory and wanting to serve a file from that directory (although strictly speaking the file could be anywhere).
The DirectoryIndex is the document that mod_dir will look for when requesting a directory (eg. /test/). By default, it looks for index.html (and often index.php) and possibly others. If a DirectoryIndex document is not found, you get a 403 Forbidden when requesting that directory (assuming auto-directory indexes are disabled).
For example, you could set the following:
DocumentIndex hello.php
And now when you request /Test/, mod_dir will serve hello.php in that directory.
However, this method (by itself) is limiting and potentially confusing for readers of your code (if changing the DirectoryIndex on a directory by directory basis). It is generally expected that the DirectoryIndex document(s) is consistent throughout your site.
I have a very small site with my .htaccess set up to allow urls like:
mysite.com/brand/login
mysite.com/brand/dashboard
mysite.com/controller
These all redirect to:
mysite.com/driver.php?___=brand/login
mysite.com/driver.php?___=brand/dashboard
mysite.com/driver.php?___=controller
I'm simply using one rewrite rule for this:
RewriteRule ^(([a-zA-Z0-9\-\_]+/?)*)$ index.php?___=$1 [L,QSA]
But anyway, it works great, until I have a page with the same name as a folder in my site.
// I navigate to:
mysite.com/javascript
// The site automatically provides a 301 redirect to
mysite.com/javascript/? ___=javascript
And now that ugly URL is showing up in my users' browsers. Is there any way to tell the site that I want to take care of all redirects myself?
EDIT: I determined this using fiddler. Another example:
Welp found the answer right after posting this. This line in .htaccess fixed the problem.
DirectorySlash Off
I then, of course, had to clear my browser cache to make it forget about the 301.
https://httpd.apache.org/docs/2.4/mod/mod_dir.html#directoryslash
The DirectorySlash directive determines whether mod_dir should fixup
URLs pointing to a directory or not.
Typically if a user requests a resource without a trailing slash,
which points to a directory, mod_dir redirects him to the same
resource, but with trailing slash
And a security warning:
Turning off the trailing slash redirect may result in an information
disclosure. Consider a situation where mod_autoindex is active
(Options +Indexes) and DirectoryIndex is set to a valid resource (say,
index.html) and there's no other special handler defined for that URL.
In this case a request with a trailing slash would show the index.html
file. But a request without trailing slash would list the directory
contents.
I have some difficulties with the mod_rewrite rules for language folders. I want to rewrite any request on:
www.example.com/lang/*
to:
www.example.com/*
I add rule
RewriteRule ^lang/(.*)$ \/$1
As I use several language I'd like to save in enviroment wich exactly language in URL is typed at first opening of site.
Futher I use rule
SetEnvIf Referer "www.example.com/lang1/" LANG=1
SetEnvIf Referer "www.example.com/lang2/" LANG=2
So I got language to show on site
However I could not get this enviroment when typing address www.example.com/lang1/ in browser
As this is an internal rewrite (the new path is used instead of the old one), there is no communication with the client and therefore no new Referer set.
But using the referer is always unreliable. Consider modifying the RewriteRule so that it contains the original request URI in the query string.
This would be
RewriteRule ^lang/(.*)$ \/$1&uri=%{REQUEST_URI}
if your requests contain a query string, and
RewriteRule ^lang/(.*)$ \/$1?uri=%{REQUEST_URI}
if not. The original URI would then be contained in the variable $_GET['uri'].
I have clean path with the same name as existing directory.
I use these .htaccess rules to support clean path for the path:
RewriteCond ${REQUEST_URI} ^/mydir
RewriteCond ${REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
everything works correctly (I have a "mydir" clean path working and I can access existing files in the /mydir directory directly), but apache appends the trailing slash all the time to requests.
I request http://domain.com/mydir, and it redirects me 301 to http://domain.com/mydir/.
What is the reason?
Trailing slash after /mydir/ is added by an Apache module called mod_dir that adds a trailing slash after all the directories. This is due to this setting turned on by default:
DirectorySlash On
You can turn it off using:
DirectorySlash Off
However it might expose some directories by showing their listings.
Security Warning
Turning off the trailing slash redirect may result in an information
disclosure. Consider a situation where mod_autoindex is active
(Options +Indexes) and DirectoryIndex is set to a valid resource (say,
index.html) and there's no other special handler defined for that URL.
In this case a request with a trailing slash would show the index.html
file. But a request without trailing slash would list the directory
contents.
Apache's proper URL always ends in a slash /. Because it treats URL's as if they were a disk file path (which always ends in a slash). If it's not there, the server needs to take one additional step to internally add it. I say let it be.
Plus Google (supposedly) likes the trailing slashes.
I say keep it as is.
Please read more: http://cdivilly.wordpress.com/2014/03/11/why-trailing-slashes-on-uris-are-important/
and here: http://bit.ly/1uSvbfy :)