Who adds a slash at the end of my url? - apache

I'm using mod_rewrite to rewrite /products to /products.php. I've got this code in /.htaccess
Options FollowSymLinks
RewriteEngine on
RewriteRule ^([a-zA-z]+)$ /$1.php [PT,L]
Unfortunately there is also a folder /products/ on my server.
My problem is, when I try to access http://mydomain.com/products my request is redirected to http://mydomain.com/products/ and showing me an error because I don't have an index for that directory.
Who is redirecting me? Apache, my UserAgent?
How do I prevent that this happens without changing the folder name or the rewrite rule?

You need to look up the "DirectorySlash Directive".
The DirectorySlash directive
determines whether mod_dir should
fixup URLs pointing to a directory or
not.
http://httpd.apache.org/docs/2.2/mod/mod_dir.html
You could also try adding an optional slash to you rewrite rule:
RewriteRule ^([a-zA-z]+)/?$ /$1.php [PT,L]
Trailing slashes problem

You have probably enabled MultiViews on your Apache.

Every browser is adding the trailing slash after your request if it doesn't by ".something" because it thinks it is a folder. To avoid this, your rewrite rule should look like this:
RewriteRule /products(.*)$ /index.php?page=products
OR
RewriteRule /products /index.php?page=products
That way, it will rewrite every request with "/products" in it, with or without the trailing slash.
The only thing is your folder /products/ will not be accessible by an http request. If you want so, you must change the name of the folder or the page name.

Related

rewrite request for /folder to folder/index.php without 301 redirect with apache

So I put an index.php in /pipe/index.php
I'd like to rewrite (internal, not redirect)
https://host/pipe?token=abc to https://host/pipe/index.php?token=abc
what I tried (caveat, assumes there is always a ? in the url):
RewriteEngine on
RewriteRule "^([^?]*)(.*)$" "$1/$2" [PT]
my hope was to split at the ? and just insert a / there.
But it seems apache finds out that "oh, pipe is a folder" before checking my .htacces (?) Because despite my [PT] it still redirects with 301 to /pipe/?token=abc, when I hoped for internal rewrite.
But it seems apache finds out that "oh, pipe is a folder" before checking my .htacces (?)
Yes, mod_dir will append the trailing slash with a 301 redirect. Although this occurs after mod_rewrite has processed the URL (if indeed it is being processed at all - see below). (The PT flag is irrelevant in .htaccess, since the resulting rewrite is passed through as a URL-path by default.)
RewriteRule "^([^?]*)(.*)$" "$1/$2" [PT]
However, your existing rule (by itself) would result in a rewrite-loop (500 Internal Server Error) since it matches itself and repeatedly appends a slash. If you are seeing a 301 redirect as mentioned above then either this rule is not doing anything (are .htaccess overrides enabled?) or you have a conflict with other rules.
As you've stated, this rule also assumes that the query string (with leading ?) is also matched by the RewriteRule pattern. The RewriteRule directive matches against the URL-path only, not the query string. $2 in the above rule is therefore always empty (unless you have %3F in the URL-path, ie. a %-encoded ?).
The query string is contained in its own variable, QUERY_STRING. But you simply want to pass through the same query string, so you don't need to do anything special here, since that happens by default.
Solution
To prevent mod_dir appending the trailing slash, you need to set DirectorySlash Off at the top of the root .htaccess file.
Note that these directives must go in the .htaccess file in the root/parent directory, as opposed to the subdirectory that has the trailing slash omitted. This is because the mod_rewrite directives (that "fix" the URL by appending the trailing slash) would never actually be processed in the subdirectory .htaccess file. The trailing slash would seem to be required for mod_rewrite to function. (However, the mod_dir DirectorySlash Off directive would still be processed successfully, so the slash would not be appended.)
For example:
# Prevent mod_dir appending the trailing slash
DirectorySlash Off
# Must disable directory listings when "DirectorySlash Off" is set
Options -Indexes
However, you need to then manually append the trailing slash to any directory, where it is omitted, with an internal rewrite to "fix" the URL (and to correctly serve the DirectoryIndex document, ie. index.php).
# Ensure DirectoryIndex is set correctly
DirectoryIndex index.php
RewriteEngine On
# Append trailing slash to any directory where it has been omitted
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ $1/ [L]
The trailing slash on the directory (via the internal rewrite) is required in order to serve the DirectoryIndex document, otherwise, you get a 403 Forbidden, even if the DirectoryIndex document is present.
If the trailing slash is omitted and directory listings (mod_autoindex) are enabled (disabled above) then a directory listing would be generated even if a DirectoryIndex document is present in that directory. (Which is why directory listings must be disabled when DirectorySlash Off is set.)
NB: You will need to make sure the browser cache is cleared since the earlier 301 redirect by mod_dir to append the trailing slash will have been cached by the browser.
This probably is what you are looking for:
RewriteEngine on
RewriteRule ^/?pipe/?$ /pipe/index.php [QSA,L]
The QSA flag is actually redundant here, it is the default, but it makes things clearer if you compare it to that variant (both work):
RewriteEngine on
RewriteRule ^/?pipe/?$ /pipe/index.php?%{QUERY_STRING} [QSD,L]
The documentation of the rewriting module, more specific of the RewriteRule directive clearly points out that the query string is not part of the path the rule's pattern is matched against.
If you want to have more control about the content of the query string you can use a RewriteCond:
RewriteEngine on
RewriteCond %{QUERY_STRING} ^token=(.*)$
RewriteRule ^/?pipe/?$ /pipe/index.php?token=%1 [QSD,L]
Also you might want to redirect the original URL:
RewriteEngine on
RewriteRule ^/?pipe/index.php /pipe [QSA,R=301,END]
RewriteRule ^/?pipe/?$ /pipe/index.php [QSA,L]
And finally you might also want to take a look at the DirectoryIndex directive which might offer a solution without any rewriting at all, though this depends a bit on your setup ...

mod_rewrite rule is ignored with Wordpress

I am trying to use mod_rewrite to redirect all requests to a certain directory to a specific page:
RewriteEngine On # Turn on rewriting
RewriteRule /about/(.*) /wp-content/themes/twentyfiteen/test.php
From here I plan to get the requested URI and serve up the appropriate page.
But it seems that this rule does not even get triggered.
Thanks
URI's that are sent through rewrite rules in an htaccess file have the leading slash removed, so you can't match /about/, you need to remove the leading slash:
RewriteEngine On
RewriteRle ^about/(.*)$ /wp-content/themes/twentyfiteen/test.php [L]

Apache mod_rewrite links proxy

I want to make a proxy for external links with apache's mod_rewrite module.
I want it to redirect user from, ie http://stackoverflow.com/go/http://example.com/ to http://example.com/ where http://stackoverflow.com/ is my site's URL. So I added a rule to .htaccess file.
RewriteRule ^/go/http://(.+) http://$1 [R=302,L]
But it doesn't work at all. How to fix this?
I am not sure if Apache or the browser reduces // to /, but since it doesn't change the directory one of them reduces this to a single slash on my setup. That's why the second slash has a ? behind it in the rule below:
RewriteRule ^go/http://?(.*)$ http://$1 [R,L]
This will redirect the user to that domain.
This will rewrite all urls (without the beginning http://) to new complete URL. If you're gonna use https links also, you need something like the second rule.
RewriteRule ^go/(.*) http://$1 [R=302,L,QSA,NE]
RewriteRule ^gos/(.*) https://$1 [R=302,L,QSA,NE]
I also added the QSA if your need to include parameters

.htaccess to show a directory index.html without a trailing slash

I've got a Jekyll generated site running on an Apache server and I'm having some trouble getting my .htaccess file set up correctly. Jekyll places index.html files into folders which represent each page so my URLs currently look like domain.com/foo/
I'd like to remove that trailing slash from the URL so that it exactly matches what I had set up previously (and also because I think it looks better).
Currently the section of my .htaccess file dealing with rewites looks like:
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
</IfModule>
Options -Indexes
DirectoryIndex index.xml index.html
I have tried following the advice here but that puts me into a redirect loop.
Can anybody help me out? In brief, what I want is for a domain.com/foo URL to show the index.html file form the /foo directory and for domain.com/foo/ and domain.com/foo/index.html to redirect to domain.com/foo.
You should be able to use this to turn off the addition of slashes.
DirectorySlash Off
Note that the trailing slash is added for a good reason. Having the trailing slash in the directory name will make relative URLs point at the same thing regardless of whether the URL ends with "foo/bar/index.html" or just "foo/bar/". Without the trailing slash, relative URLs would reference something up one level from what they normally point at. (eg: "baz.jpg" would give the user "/foo/baz.jpg" instead of "/foo/bar/baz.jpg", as the trailing "bar" will get removed if it isn't protected by a trailing slash.) So if you do this, you probably want to avoid relative URLs.
To then rewrite the directory name to return the index.html you could probably do something like this:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}/index.html -f
RewriteRule ^(.*)$ /$1/index.html [L]
This checks if REQUEST_URI/index.html exists, and if it does performs an internal redirect.

Stripping trailing slash in URL doesn't work in subdirectory

The following rule works to remove the trailing slash for all pages in my web root:
RewriteRule ^(.+)/$ /$1 [L,R=301]
However, it does not work when placed in a sub folder. I've also tried:
RewriteRule (.*)/$ /$1 [L,R=301]
to no avail. What happens is, it redirects
http://example.com/testfolder/testpage/
to
http://example.com/testpage
What am I missing? Thanks in advance!
Have you tried omitting the leading slash from your replacement?
RewriteRule ^(.+)/$ $1 [L,R=301]
It's just a stone's throw from what you have. The context of the directory rewrite (being "in" /testfolder) may be the root cause of the trouble.
you may be able to define this in variables also make sure Rewrite mods are enabled in your php.ini if there is no other way of doing what you need.
The trailing slash fixup is being done by mod_dir. Rewrites in your per-directory context are re-injected into the URL processing chain and subject to the fixup again.
The behavior is configurable. E.g.
<Directory /path/to/wherever>
DirectorySlash Off
...
</Directory>
The context for this is not only Directory: it is server config, virtual host, directory, .htaccess.