It depends where in the <VirtualHost>
container you are placing these directives.
If you are using a <Directory>
container (ie. a directory context) and disabling .htaccess
overrides altogether (otherwise .htaccess
will override the <Directory>
container!) then you can pretty much copy the directives as-is (assuming the <Directory>
container references the same directory as the .htaccess
file did).
However, if you are putting these directives directly inside the <VirtualHost>
container (outside of a <Directory>
container), ie. in a virtualhost context, then you need to make some changes. This is because the directives are processed earlier, before the request is mapped to the filesystem.
In the directives you've posted, only two changes would be required:
In a virtualhost context, the REQUEST_FILENAME
server variable has not yet been resolved to a filename. It is the same as REQUEST_URI
(ie. the URL that is requested). So, your filesystem check will always fail and the condition will always be successful! You either need to use a lookahead. eg. %{LA-U:REQUEST_FILENAME}
, or construct the absolute filename yourself. eg. %{DOCUMENT_ROOT}%{REQUEST_URI}
. For example:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
In a virtualhost context, the URL-path that is matched by the RewriteRule
pattern is root-relative (starting with a slash). Whereas in .htaccess
it is relative to the directory that contains the .htaccess
file - less the slash prefix. So, the rule as written would result in a double slash at the start of the URL-path, it should be rewritten like this instead:
RewriteRule ^/(.*)$ /$1/ [R,L]
(The NC
flag is not required here.)
Or (preferable) don't use a backreference here and use the REQUEST_URI
server variable instead (which would naturally work in .htaccess
as well). For example:
RewriteRule ^ %{REQUEST_URI}/ [R,L]
(Aside: This should probably also be a 301 permanent redirect (ie. R=301
). As it stands, this will default to a 302 temporary redirect. But only change to a 301 - if that is the intention - once you have confirmed that it works as intended.)
So, in summary, this would become:
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteCond %{REQUEST_URI} !^/application-module/(.*)$
RewriteCond %{REQUEST_URI} !(.*)json$ [NC]
RewriteCond %{REQUEST_URI} !playground/local-loader/(.*)$ [NC]
RewriteRule ^/(.*)$ /$1/ [R,L]
Aside:
The above can be immediately optimised a bit by moving the filesystem check (which is relatively expensive) to the last condition and moving the condition that checks that the request does not already end in a slash to the RewriteRule
directive. Also, the regex subpatterns (.*)
in each of the conditions are not required. So, the above could be rewritten more efficiently:
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} !^/application-module/
RewriteCond %{REQUEST_URI} !json$ [NC]
RewriteCond %{REQUEST_URI} !playground/local-loader/ [NC]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule !/$ %{REQUEST_URI}/ [R,L]
The filesystem check can perhaps be removed altogether if instead you exclude requests that contain (what looks like) a file extension, but this can depend on your file structure.
The condition that checks !json$
looks like it should really be checking for the .json
file extension, ie. !\.json$
. (This ties in with my comment above about excluding all requests that have a "file extension".)
The first condition that checks that the query string is empty seems a little odd (since it doesn't really matter whether there is a query string or not when appending a slash to the URL-path), but I assume this must be a specific requirement?