# Check if Accept header is image/webp, if an image is requested in "classic" folder with a classic format, and check if the corresponding webp image exists. If yes, rewrite the requested classic image URI to the WebP image URI.RewriteCond%{HTTP_ACCEPT}image/webpRewriteCond%{REQUEST_FILENAME}(.*)images/classic/(.*)\.(png|jpg|gif)$RewriteCond%1images/webp/%2\.webp-fRewriteRule.*images/webp/%2.webp [L]
You should add a mecanism to redirect HTTP to HTTPS too. It's adviced to use VirtualHost:
<IfModule mod_rewrite.c> # Force HTTPS # Inspired from https://stackoverflow.com/questions/13376219/htaccess-redirect-http-to-https/RewriteEngine onRewriteCond%{HTTPS}!on # Header used by proxies or load balancers (CDN):RewriteCond%{HTTP:X-Forwarded-Proto}!https # Some load balancer use other methods: # RewriteCond %{HTTPS} !1 # RewriteCond %{SERVER_PORT} !443 # RewriteCond %{HTTP:X-Forwarded-SSL} !on # RewriteCond %{HTTP:CF-Visitor} '"scheme":"http"' # RewriteCond %{ENV:HTTPS} !onRewriteRule^https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]</IfModule>
<IfModule mod_headers.c> # Force HTTPSHeader always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"</IfModule>
<IfModule mod_headers.c> # Force HTTPS only for www.example.comSetEnvIf Host "^www\.example\.com$" StrictTransportSecurityHeader always set Strict-Transport-Security "max-age=63072000; preload" env=StrictTransportSecurity</IfModule>
<IfModule mod_rewrite.c>RewriteEngine on # Determine the RewriteBase automatically and set it as environment variable. # If you are using Apache aliases to do mass virtual hosting or installed the # project in a subdirectory, the base path will be prepended to allow proper # resolution of the files and to redirect to the correct URI. It will # work in environments without path prefix as well, providing a safe, one-size # fits all solution. But as you do not need it in this case, you can comment # the following 2 lines to eliminate the overhead.RewriteCond%{REQUEST_URI}::$1^(/.+)/(.*)::\2$RewriteRule^(.*)- [E=BASE:%1]RewriteCond%{REQUEST_URI}!^%{ENV:BASE}/subfolder/RewriteRule^(.*)$%{ENV:BASE}/subfolder/$1 [L]</IfModule>
<IfModule rewrite_module>RewriteEngine onRewriteCond%{DOCUMENT_ROOT}^(.*)$ [NC]RewriteRule^- [E=doc_root:%1] # Will add an header `X-Debug` with value equal DOCUMENT_ROOT (see the syntax `%{xxxx}e`)Header append X-Debug "%{doc_root}e" # Add cookie `test` to `1`RewriteRule^- [CO=test:1:%{HTTP_HOST}] # Test cookie `test` == `1`RewriteCond%{HTTP:Cookie}\test=1(;|$) # Skip next RewriteRule (use 2 instead 1 to skip more, 3... or use L)RewriteRule^- [S=1] # Test if env var `test` equal `1`RewriteCond%{ENV:test}^1$RewriteRule...</IfModule>
# Use the front controller as index file. It serves as a fallback solution when# every other rewrite/redirect fails (e.g. in an aliased environment without# mod_rewrite). Additionally, this reduces the matching process for the# start page (path "/") because otherwise Apache will apply the rewriting rules# to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl).DirectoryIndex app.php# By default, Apache does not evaluate symbolic links if you did not enable this# feature in your server configuration. Uncomment the following line if you# install assets as symlinks or if you experience problems related to symlinks# when compiling LESS/Sass/CoffeScript assets.# Options FollowSymlinks# Disabling MultiViews prevents unwanted negotiation, e.g. "/app" should not resolve# to the front controller "/app.php" but be rewritten to "/app.php/app".<IfModule mod_negotiation.c>Options -MultiViews</IfModule><IfModule mod_rewrite.c>RewriteEngine on # Determine the RewriteBase automatically and set it as environment variable. # If you are using Apache aliases to do mass virtual hosting or installed the # project in a subdirectory, the base path will be prepended to allow proper # resolution of the app.php file and to redirect to the correct URI. It will # work in environments without path prefix as well, providing a safe, one-size # fits all solution. But as you do not need it in this case, you can comment # the following 2 lines to eliminate the overhead.RewriteCond%{REQUEST_URI}::$1^(/.+)/(.*)::\2$RewriteRule^(.*)- [E=BASE:%1] # Sets the HTTP_AUTHORIZATION header removed by ApacheRewriteCond%{HTTP:Authorization}.RewriteRule^- [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] # Redirect to URI without front controller to prevent duplicate content # (with and without `/app.php`). Only do this redirect on the initial # rewrite by Apache and not on subsequent cycles. Otherwise we would get an # endless redirect loop (request -> rewrite to front controller -> # redirect -> request -> ...). # So in case you get a "too many redirects" error or you always get redirected # to the start page because your Apache does not expose the REDIRECT_STATUS # environment variable, you have 2 choices: # - disable this feature by commenting the following 2 lines or # - use Apache >= 2.3.9 and replace all L flags by END flags and remove the # following RewriteCond (best solution)RewriteCond%{ENV:REDIRECT_STATUS}^$RewriteRule^app\.php(?:/(.*)|$)%{ENV:BASE}/$1 [R=301,L] ## Not part of Symfony # Ignore /admin/ and /mobile/ subfolders # https://stackoverflow.com/a/24319167/470117RewriteCond"%{ENV:BASE}/admin/%{REQUEST_URI}" "(^[^ ]*) \1" [OR]RewriteCond"%{ENV:BASE}/mobile/%{REQUEST_URI}" "(^[^ ]*) \1"RewriteRule^- [L] ## /Not part of Symfony # If the requested filename exists, simply serve it. # We only want to let Apache serve files and not directories.RewriteCond%{REQUEST_FILENAME}-fRewriteRule^- [L] # Rewrite all other queries to the front controller.RewriteRule^%{ENV:BASE}/app.php [L]</IfModule><IfModule !mod_rewrite.c> <IfModule mod_alias.c> # When mod_rewrite is not available, we instruct a temporary redirect of # the start page to the front controller explicitly so that the website # and the generated links can still be used.RedirectMatch 302 ^/$/app.php/ # RedirectTemp cannot be used instead </IfModule></IfModule>
///WAP-redirect, based upon accepted file typeRewriteCond%{HTTP_ACCEPT}(x-)*(application|text)/(x-)*(vnd[-.])*(wap[-.]|wml)+RewriteRule^(index.html)*$index.wml [L]
# http://www.mysite.com/keyword/j1_1/j2_2/j3_3/j4_4/j5_5/j6_6/j7_7/... -> http://www.mysite.com/index.php?j1=1&j2=2&j4=4&j5=5&j7=7...# http://www.mysite.com/keyword/j2_2/j3_3/j4_4/j5_5/j6_6/j7_7/... -> http://www.mysite.com/index.php?j2=2&j4=4&j5=5&j7=7...# Skip following section if not a "keyword/" requestrewriterule !^keyword/ - [S=9]## Else copy/append keywords to user-defined variable "tQuery"rewriterule ^keyword(/[^/]+)*/j1_([^/]+) - [NC,E=tQuery:%{ENV:tQuery}j1=$2]rewriterule ^keyword(/[^/]+)*/j2_([^/]+) - [NC,E=tQuery:%{ENV:tQuery}&j2=$2]rewriterule ^keyword(/[^/]+)*/j3_([^/]+) - [NC,E=tQuery:%{ENV:tQuery}&j3=$2]rewriterule ^keyword(/[^/]+)*/j4_([^/]+) - [NC,E=tQuery:%{ENV:tQuery}&j4=$2]rewriterule ^keyword(/[^/]+)*/j5_([^/]+) - [NC,E=tQuery:%{ENV:tQuery}&j5=$2]rewriterule ^keyword(/[^/]+)*/j6_([^/]+) - [NC,E=tQuery:%{ENV:tQuery}&j6=$2]rewriterule ^keyword(/[^/]+)*/j7_([^/]+) - [NC,E=tQuery:%{ENV:tQuery}&j7=$2]## Strip leading "&" from tQuery (if any)RewriteCond%{ENV:tQuery}^&(.+)$rewriterule ^keyword/ - [NC,E=tQuery:%1]# Tweaked to look for city name (if any)rewriterule ^keyword(_[^/]+)? - [NC,E=tQuery:%1]# Rewrite the URL-path to index.php query format# Tweaked to look for city name (if any)rewriterule ^keyword(_[^/]+)? /index.php?%{ENV:tQuery} [NC,L]
# http://mysite.com/keyword/test/page2 -> http://mysite.com/data.php?method=keyword&criteria=test&page=2# http://mysite.com/date/06-05-02 -> http://mysite.com/data.php?method=keyword&criteria=06-05-02# Skip following section if not a "keyword/" requestrewriterule !^(keyword|date|category) - [skip=4]# Else copy/append keywords to user-defined variable "tmpQuery"RewriteRule^(keyword|date|category).*$- [env=tmpQuery:%{ENV:tmpQuery}method=$1]RewriteRule^(keyword|date|category)/([^/]*).*$- [env=tmpQuery:%{ENV:tmpQuery}&criteria=$2]RewriteRule^(keyword|date|category)/([^/]*)/page(\d+).*$- [env=tmpQuery:%{ENV:tmpQuery}&page=$3]# Rewrite the URL-path to data.php query formatrewriterule ^(keyword|date|category).* /data.php?%{ENV:tmpQuery} [last]# http://www.dracos.co.uk/code/apache-rewrite-problem/
/// Rewrite by accept language given by clientRewriteEngine onRewriteCond%{HTTP:Accept-Language}(sv) [NC]RewriteRule.*http://www.sverige.hms-solutions.com [R,L]RewriteCond%{HTTP:Accept-Language}(nn) [NC]RewriteRule.*http://www.norge.hms-solutions.com [R,L]RewriteCond%{HTTP:Accept-Language}(da) [NC]RewriteRule.*http://www.danmark.hms-solutions.com [R,L]RewriteCond%{HTTP:Accept-Language}(en) [NC]RewriteRule.*http://www.english.hms-solutions.com [R,L]RewriteCond%{HTTP:Accept-Language}.* [NC]RewriteRule.*http://www.international.hms-solutions.com [R,L]
# In the .htaccess<IfModule mod_alias.c> # Use status "gone" for 410 (HTTP status) # Note: if you need to match query string, use mod_rewrite instead. # See https://web.archive.org/web/20220820210007/https://simonecarletti.com/blog/2009/01/apache-query-string-redirects/Redirect gone /aRedirect gone /bRedirectMatch gone \.gif$</IfModule>
# This code sends the Set-Cookie header to create a cookie on the client with the value of a matching item in 2nd parantheses.RewriteRule^(.*)(de|es|fr|it|ja|ru|en)/$- [co=lang:$2:.askapache.com:7200:/]
<IfModule mod_expires.c>ExpiresActive on# Perhaps better to allowlist expires rules? Perhaps.ExpiresDefault "access plus 1 month"# cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5)ExpiresByType text/cache-manifest "access plus 0 seconds"# Your document htmlExpiresByType text/html "access plus 0 seconds"# CSS and JavaScriptExpiresByType text/css "access plus 1 year"ExpiresByType text/javascript "access plus 1 year"# DataExpiresByType text/xml "access plus 0 seconds"ExpiresByType application/xml "access plus 0 seconds"ExpiresByType application/json "access plus 0 seconds"ExpiresByType application/ld+json "access plus 0 seconds"ExpiresByType application/vnd.geo+json "access plus 0 seconds"# FeedExpiresByType application/rss+xml "access plus 1 hour"ExpiresByType application/atom+xml "access plus 1 hour"# Favicon (cannot be renamed)ExpiresByType image/x-icon "access plus 1 week"# Manifest filesExpiresByType application/manifest+json "access plus 1 year"ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"ExpiresByType text/cache-manifest "access plus 0 seconds"# Media: images, video, audioExpiresByType image/gif "access plus 1 month"ExpiresByType image/png "access plus 1 month"ExpiresByType image/jpg "access plus 1 month"ExpiresByType image/jpeg "access plus 1 month"ExpiresByType video/ogg "access plus 1 month"ExpiresByType audio/ogg "access plus 1 month"ExpiresByType video/mp4 "access plus 1 month"ExpiresByType video/webm "access plus 1 month"# WebfontsExpiresByType application/font-woff "access plus 1 month"ExpiresByType application/font-woff2 "access plus 1 month"ExpiresByType application/vnd.ms-fontobject "access plus 1 month"ExpiresByType application/x-font-ttf "access plus 1 month"ExpiresByType font/opentype "access plus 1 month"ExpiresByType image/svg+xml "access plus 1 month"</IfModule>
# 1 YEAR<FilesMatch "\.(ico|pdf|flv)$">Header set Cache-Control "max-age=29030400, public"</FilesMatch># 1 WEEK<FilesMatch "\.(jpg|jpeg|png|gif|swf)$">Header set Cache-Control "max-age=604800, public"</FilesMatch># 2 DAYS<FilesMatch "\.(xml|txt|css|js)$">Header set Cache-Control "max-age=172800, proxy-revalidate"</FilesMatch># 1 MIN<FilesMatch "\.(html|htm|php)$">Header set Cache-Control "max-age=60, private, proxy-revalidate"</FilesMatch>
ETag removal
# FileETag None is not enough for every server.<IfModule mod_headers.c>Header unset ETag</IfModule># Since we're sending far-future expires, we don't need ETags for# static content.# developer.yahoo.com/performance/rules.html#etagsFileETag None
This limitation of mod_deflate is prominently mentioned in the documentation, which recommends using mod_rewrite to rewrite requests to their compressed alternatives when appropriate. Although this method can work [...] it has the major drawback that you are reimplementing content negotiation (which mod_negotiation was designed to do) and are likely to get it wrong and lack features supported by mod_negotiation. Some common problems and pitfalls with this approach:
Sending an incorrect or missing Content-Encoding header.
Not sending the Vary header or setting it incorrectly (overwriting previous values for other headers which cause the response to vary).
Sending Content-Type: application/x-gzip instead of the underlying type.
Sending double-gzipped content due to forgetting to set no-gzip in the environment to exclude the response from mod_deflate.
Not respecting client preferences (i.e. quality values/qvalues). According to RFC 7231 (and RFC 2616 before it) clients can send a numeric value between 0 and 1 (inclusive) to express their relative preference for each encoding. An Accept-Encoding: gzip;q=0 header would signify that the client wants “anything but gzip”. Most mod_rewrite implementations would send them gzip. A more realistic example would be a client that sends Accept-Encoding: br;q=1, gzip;q=0.5, deflate;q=0.1 to signify that they prefer Brotli, then gzip, then deflate. Writing mod_rewrite rules which properly handle these sorts of expressed preferences is extremely difficult.
# If the browser accepts gzip/br and the requested file exists under pre-encoded version, then serve that version directly.<IfModule mod_rewrite.c> <IfModule mod_headers.c> # Brotli <IfModule mod_brotli.c>RewriteEngine OnRewriteCond%{HTTP:Accept-Encoding}brRewriteCond%{REQUEST_FILENAME}.br-fRewriteRule(.*)$1.br [L,E=no-brotli:1,E=PRE_ENCODED_CODING:br] </IfModule> # Deflate / Gzip <IfModule mod_deflate.c>RewriteEngine OnRewriteCond%{HTTP:Accept-Encoding}gzipRewriteCond%{REQUEST_FILENAME}.gz-fRewriteRule(.*)$1.gz [L,E=no-gzip:1,E=PRE_ENCODED_CODING:gzip] # Special case for *.svg -> *.svgzRewriteCond%{HTTP:Accept-Encoding}gzipRewriteCond%{REQUEST_FILENAME}.svg$RewriteCond%{REQUEST_FILENAME}z-fRewriteRule(.*)$1z [L,E=no-gzip:1,E=PRE_ENCODED_CODING:gzip] </IfModule> # Special case for internal redirection (pre encoded) response only # For "REDIRECT_" env var prefix see https://stackoverflow.com/questions/3050444 # Some directives support env vars conditions (Header does, but RemoveType doesn't) <If "-n env('REDIRECT_PRE_ENCODED_CODING')"> # Debian (and related distributions) set AddType application/x-gzip gz in their default conf (/etc/apache2/mods-available/mime.conf) # or you the Content-Type will be override to application/x-gzipRemoveType gzHeader always set Content-Encoding %{REDIRECT_PRE_ENCODED_CODING}e # Apache already append Accept-Encoding to Vary http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritecond </If> </IfModule></IfModule>
You need to restrict content negotiation by include directives in a <Directory>, <Files> or .htaccess for a subset of directories, file types.
The major drawback, only requests for files which do not exist are negotiated. That means you need to rename uncompressed files for an additional extension (ex: index.html.html and index.html.gz for https://example.com/index.html) which is not pratical.
# Let Apache choose media type, encoding, etc. based on client preferences.# Need rewrite to force use pre encoded version because MultiViews only negotiates requests for files which do not exist.<IfModule mod_mime.c> <IfModule mod_rewrite.c> # Brotli <IfModule mod_brotli.c>Options +MultiViewsRewriteEngine On # Note: BR is a RFC 3066 languageRemoveLanguage brAddEncoding br br </IfModule> # Deflate / Gzip <IfModule mod_deflate.c>Options +MultiViewsRewriteEngine On # Case for * -> *.gz # Debian (and related distributions) set AddType application/x-gzip gz in their default conf (/etc/apache2/mods-available/mime.conf)RemoveType .gzAddEncoding gzip gz # Case for *.svg -> .svgzAddEncoding gzip svgz </IfModule> </IfModule></IfModule>
# Treat not as application/gzip typeRemoveType .gz# Handle type mapsAddHandler type-map .varRewriteCond%{REQUEST_FILENAME}.var-fRewriteRule(.*)$1.var [QSA]
Exemple, for test.htmltest.html.gz and test.html.br, create a file test.var, for a request /test
RewriteEngine onRewriteBase /RewriteRule.*- [E=INFO_API_VERSION:%{API_VERSION},NE]RewriteRule.*- [E=INFO_AUTH_TYPE:%{AUTH_TYPE},NE]RewriteRule.*- [E=INFO_CONTENT_LENGTH:%{CONTENT_LENGTH},NE]RewriteRule.*- [E=INFO_CONTENT_TYPE:%{CONTENT_TYPE},NE]RewriteRule.*- [E=INFO_DOCUMENT_ROOT:%{DOCUMENT_ROOT},NE]RewriteRule.*- [E=INFO_GATEWAY_INTERFACE:%{GATEWAY_INTERFACE},NE]RewriteRule.*- [E=INFO_HTTPS:%{HTTPS},NE]RewriteRule.*- [E=INFO_HTTP_ACCEPT:%{HTTP_ACCEPT},NE]RewriteRule.*- [E=INFO_HTTP_ACCEPT_CHARSET:%{HTTP_ACCEPT_CHARSET},NE]RewriteRule.*- [E=INFO_HTTP_ACCEPT_ENCODING:%{HTTP_ACCEPT_ENCODING},NE]RewriteRule.*- [E=INFO_HTTP_ACCEPT_LANGUAGE:%{HTTP_ACCEPT_LANGUAGE},NE]RewriteRule.*- [E=INFO_HTTP_CACHE_CONTROL:%{HTTP_CACHE_CONTROL},NE]RewriteRule.*- [E=INFO_HTTP_CONNECTION:%{HTTP_CONNECTION},NE]RewriteRule.*- [E=INFO_HTTP_COOKIE:%{HTTP_COOKIE},NE]RewriteRule.*- [E=INFO_HTTP_FORWARDED:%{HTTP_FORWARDED},NE]RewriteRule.*- [E=INFO_HTTP_HOST:%{HTTP_HOST},NE]RewriteRule.*- [E=INFO_HTTP_KEEP_ALIVE:%{HTTP_KEEP_ALIVE},NE]RewriteRule.*- [E=INFO_HTTP_MOD_SECURITY_MESSAGE:%{HTTP_MOD_SECURITY_MESSAGE},NE]RewriteRule.*- [E=INFO_HTTP_PROXY_CONNECTION:%{HTTP_PROXY_CONNECTION},NE]RewriteRule.*- [E=INFO_HTTP_REFERER:%{HTTP_REFERER},NE]RewriteRule.*- [E=INFO_HTTP_USER_AGENT:%{HTTP_USER_AGENT},NE]RewriteRule.*- [E=INFO_IS_SUBREQ:%{IS_SUBREQ},NE]RewriteRule.*- [E=INFO_ORIG_PATH_INFO:%{ORIG_PATH_INFO},NE]RewriteRule.*- [E=INFO_ORIG_PATH_TRANSLATED:%{ORIG_PATH_TRANSLATED},NE]RewriteRule.*- [E=INFO_ORIG_SCRIPT_FILENAME:%{ORIG_SCRIPT_FILENAME},NE]RewriteRule.*- [E=INFO_ORIG_SCRIPT_NAME:%{ORIG_SCRIPT_NAME},NE]RewriteRule.*- [E=INFO_PATH:%{PATH},NE]RewriteRule.*- [E=INFO_PATH_INFO:%{PATH_INFO},NE]RewriteRule.*- [E=INFO_PHP_SELF:%{PHP_SELF},NE]RewriteRule.*- [E=INFO_QUERY_STRING:%{QUERY_STRING},NE]RewriteRule.*- [E=INFO_REDIRECT_QUERY_STRING:%{REDIRECT_QUERY_STRING},NE]RewriteRule.*- [E=INFO_REDIRECT_REMOTE_USER:%{REDIRECT_REMOTE_USER},NE]RewriteRule.*- [E=INFO_REDIRECT_STATUS:%{REDIRECT_STATUS},NE]RewriteRule.*- [E=INFO_REDIRECT_URL:%{REDIRECT_URL},NE]RewriteRule.*- [E=INFO_REMOTE_ADDR:%{REMOTE_ADDR},NE]RewriteRule.*- [E=INFO_REMOTE_HOST:%{REMOTE_HOST},NE]RewriteRule.*- [E=INFO_REMOTE_IDENT:%{REMOTE_IDENT},NE]RewriteRule.*- [E=INFO_REMOTE_PORT:%{REMOTE_PORT},NE]RewriteRule.*- [E=INFO_REMOTE_USER:%{REMOTE_USER},NE]RewriteRule.*- [E=INFO_REQUEST_FILENAME:%{REQUEST_FILENAME},NE]RewriteRule.*- [E=INFO_REQUEST_METHOD:%{REQUEST_METHOD},NE]RewriteRule.*- [E=INFO_REQUEST_TIME:%{REQUEST_TIME},NE]RewriteRule.*- [E=INFO_REQUEST_URI:%{REQUEST_URI},NE]RewriteRule.*- [E=INFO_SCRIPT_FILENAME:%{SCRIPT_FILENAME},NE]RewriteRule.*- [E=INFO_SCRIPT_GROUP:%{SCRIPT_GROUP},NE]RewriteRule.*- [E=INFO_SCRIPT_NAME:%{SCRIPT_NAME},NE]RewriteRule.*- [E=INFO_SCRIPT_URI:%{SCRIPT_URI},NE]RewriteRule.*- [E=INFO_SCRIPT_URL:%{SCRIPT_URL},NE]RewriteRule.*- [E=INFO_SCRIPT_USER:%{SCRIPT_USER},NE]RewriteRule.*- [E=INFO_SERVER_ADDR:%{SERVER_ADDR},NE]RewriteRule.*- [E=INFO_SERVER_ADMIN:%{SERVER_ADMIN},NE]RewriteRule.*- [E=INFO_SERVER_NAME:%{SERVER_NAME},NE]RewriteRule.*- [E=INFO_SERVER_PORT:%{SERVER_PORT},NE]RewriteRule.*- [E=INFO_SERVER_PROTOCOL:%{SERVER_PROTOCOL},NE]RewriteRule.*- [E=INFO_SERVER_SIGNATURE:%{SERVER_SIGNATURE},NE]RewriteRule.*- [E=INFO_SERVER_SOFTWARE:%{SERVER_SOFTWARE},NE]RewriteRule.*- [E=INFO_THE_REQUEST:%{THE_REQUEST},NE]RewriteRule.*- [E=INFO_TIME:%{TIME},NE]RewriteRule.*- [E=INFO_TIME_DAY:%{TIME_DAY},NE]RewriteRule.*- [E=INFO_TIME_HOUR:%{TIME_HOUR},NE]RewriteRule.*- [E=INFO_TIME_MIN:%{TIME_MIN},NE]RewriteRule.*- [E=INFO_TIME_MON:%{TIME_MON},NE]RewriteRule.*- [E=INFO_TIME_SEC:%{TIME_SEC},NE]RewriteRule.*- [E=INFO_TIME_WDAY:%{TIME_WDAY},NE]RewriteRule.*- [E=INFO_TIME_YEAR:%{TIME_YEAR},NE]RewriteRule.*- [E=INFO_TZ:%{TZ},NE]RewriteRule.*- [E=INFO_UNIQUE_ID:%{UNIQUE_ID},NE]RequestHeader set INFO_API_VERSION "%{INFO_API_VERSION}e"RequestHeader set INFO_AUTH_TYPE "%{INFO_AUTH_TYPE}e"RequestHeader set INFO_CONTENT_LENGTH "%{INFO_CONTENT_LENGTH}e"RequestHeader set INFO_CONTENT_TYPE "%{INFO_CONTENT_TYPE}e"RequestHeader set INFO_DOCUMENT_ROOT "%{INFO_DOCUMENT_ROOT}e"RequestHeader set INFO_GATEWAY_INTERFACE "%{INFO_GATEWAY_INTERFACE}e"RequestHeader set INFO_HTTPS "%{INFO_HTTPS}e"RequestHeader set INFO_HTTP_ACCEPT "%{INFO_HTTP_ACCEPT}e"RequestHeader set INFO_HTTP_ACCEPT_CHARSET "%{INFO_HTTP_ACCEPT_CHARSET}e"RequestHeader set INFO_HTTP_ACCEPT_ENCODING "%{INFO_HTTP_ACCEPT_ENCODING}e"RequestHeader set INFO_HTTP_ACCEPT_LANGUAGE "%{INFO_HTTP_ACCEPT_LANGUAGE}e"RequestHeader set INFO_HTTP_CACHE_CONTROL "%{INFO_HTTP_CACHE_CONTROL}e"RequestHeader set INFO_HTTP_CONNECTION "%{INFO_HTTP_CONNECTION}e"RequestHeader set INFO_HTTP_COOKIE "%{INFO_HTTP_COOKIE}e"RequestHeader set INFO_HTTP_FORWARDED "%{INFO_HTTP_FORWARDED}e"RequestHeader set INFO_HTTP_HOST "%{INFO_HTTP_HOST}e"RequestHeader set INFO_HTTP_KEEP_ALIVE "%{INFO_HTTP_KEEP_ALIVE}e"RequestHeader set INFO_HTTP_MOD_SECURITY_MESSAGE "%{INFO_HTTP_MOD_SECURITY_MESSAGE}e"RequestHeader set INFO_HTTP_PROXY_CONNECTION "%{INFO_HTTP_PROXY_CONNECTION}e"RequestHeader set INFO_HTTP_REFERER "%{INFO_HTTP_REFERER}e"RequestHeader set INFO_HTTP_USER_AGENT "%{INFO_HTTP_USER_AGENT}e"RequestHeader set INFO_IS_SUBREQ "%{INFO_IS_SUBREQ}e"RequestHeader set INFO_ORIG_PATH_INFO "%{INFO_ORIG_PATH_INFO}e"RequestHeader set INFO_ORIG_PATH_TRANSLATED "%{INFO_ORIG_PATH_TRANSLATED}e"RequestHeader set INFO_ORIG_SCRIPT_FILENAME "%{INFO_ORIG_SCRIPT_FILENAME}e"RequestHeader set INFO_ORIG_SCRIPT_NAME "%{INFO_ORIG_SCRIPT_NAME}e"RequestHeader set INFO_PATH "%{INFO_PATH}e"RequestHeader set INFO_PATH_INFO "%{INFO_PATH_INFO}e"RequestHeader set INFO_PHP_SELF "%{INFO_PHP_SELF}e"RequestHeader set INFO_QUERY_STRING "%{INFO_QUERY_STRING}e"RequestHeader set INFO_REDIRECT_QUERY_STRING "%{INFO_REDIRECT_QUERY_STRING}e"RequestHeader set INFO_REDIRECT_REMOTE_USER "%{INFO_REDIRECT_REMOTE_USER}e"RequestHeader set INFO_REDIRECT_STATUS "%{INFO_REDIRECT_STATUS}e"RequestHeader set INFO_REDIRECT_URL "%{INFO_REDIRECT_URL}e"RequestHeader set INFO_REMOTE_ADDR "%{INFO_REMOTE_ADDR}e"RequestHeader set INFO_REMOTE_HOST "%{INFO_REMOTE_HOST}e"RequestHeader set INFO_REMOTE_IDENT "%{INFO_REMOTE_IDENT}e"RequestHeader set INFO_REMOTE_PORT "%{INFO_REMOTE_PORT}e"RequestHeader set INFO_REMOTE_USER "%{INFO_REMOTE_USER}e"RequestHeader set INFO_REQUEST_FILENAME "%{INFO_REQUEST_FILENAME}e"RequestHeader set INFO_REQUEST_METHOD "%{INFO_REQUEST_METHOD}e"RequestHeader set INFO_REQUEST_TIME "%{INFO_REQUEST_TIME}e"RequestHeader set INFO_REQUEST_URI "%{INFO_REQUEST_URI}e"RequestHeader set INFO_SCRIPT_FILENAME "%{INFO_SCRIPT_FILENAME}e"RequestHeader set INFO_SCRIPT_GROUP "%{INFO_SCRIPT_GROUP}e"RequestHeader set INFO_SCRIPT_NAME "%{INFO_SCRIPT_NAME}e"RequestHeader set INFO_SCRIPT_URI "%{INFO_SCRIPT_URI}e"RequestHeader set INFO_SCRIPT_URL "%{INFO_SCRIPT_URL}e"RequestHeader set INFO_SCRIPT_USER "%{INFO_SCRIPT_USER}e"RequestHeader set INFO_SERVER_ADDR "%{INFO_SERVER_ADDR}e"RequestHeader set INFO_SERVER_ADMIN "%{INFO_SERVER_ADMIN}e"RequestHeader set INFO_SERVER_NAME "%{INFO_SERVER_NAME}e"RequestHeader set INFO_SERVER_PORT "%{INFO_SERVER_PORT}e"RequestHeader set INFO_SERVER_PROTOCOL "%{INFO_SERVER_PROTOCOL}e"RequestHeader set INFO_SERVER_SIGNATURE "%{INFO_SERVER_SIGNATURE}e"RequestHeader set INFO_SERVER_SOFTWARE "%{INFO_SERVER_SOFTWARE}e"RequestHeader set INFO_THE_REQUEST "%{INFO_THE_REQUEST}e"RequestHeader set INFO_TIME "%{INFO_TIME}e"RequestHeader set INFO_TIME_DAY "%{INFO_TIME_DAY}e"RequestHeader set INFO_TIME_HOUR "%{INFO_TIME_HOUR}e"RequestHeader set INFO_TIME_MIN "%{INFO_TIME_MIN}e"RequestHeader set INFO_TIME_MON "%{INFO_TIME_MON}e"RequestHeader set INFO_TIME_SEC "%{INFO_TIME_SEC}e"RequestHeader set INFO_TIME_WDAY "%{INFO_TIME_WDAY}e"RequestHeader set INFO_TIME_YEAR "%{INFO_TIME_YEAR}e"RequestHeader set INFO_TZ "%{INFO_TZ}e"RequestHeader set INFO_UNIQUE_ID "%{INFO_UNIQUE_ID}e"
# Protect files and directories from prying eyes.<FilesMatch "\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)(~|\.sw[op]|\.bak|\.orig|\.save)?$|^(\..*|Entries.*|Repository|Root|Tag|Template|composer\.(json|lock))$|^#.*#$|\.php(~|\.sw[op]|\.bak|\.orig\.save)$">Order allow,deny</FilesMatch>
<IfModule mod_rewrite.c>RewriteEngine on # Set "protossl" to "s" if we were accessed via https://. This is used later # if you enable "www." stripping or enforcement, in order to ensure that # you don't bounce between http and https.RewriteRule^- [E=protossl]RewriteCond%{HTTPS}onRewriteRule^- [E=protossl:s] # Make sure Authorization HTTP header is available to PHP # even when running as CGI or FastCGI.RewriteRule^- [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] # Block access to "hidden" directories whose names begin with a period. This # includes directories used by version control systems such as Subversion or # Git to store control files. Files whose names begin with a period, as well # as the control files used by CVS, are protected by the FilesMatch directive # above. # # NOTE: This only works when mod_rewrite is loaded. Without mod_rewrite, it is # not possible to block access to entire directories from .htaccess, because # <DirectoryMatch> is not allowed here. # # If you do not have mod_rewrite installed, you should remove these # directories from your webroot or otherwise protect them from being # downloaded.RewriteRule"(^|/)\."- [F] # If your site can be accessed both with and without the 'www.' prefix, you # can use one of the following settings to redirect users to your preferred # URL, either WITH or WITHOUT the 'www.' prefix. Choose ONLY one option: # # To redirect all users to access the site WITH the 'www.' prefix, # (http://example.com/... will be redirected to http://www.example.com/...) # uncomment the following: # RewriteCond %{HTTP_HOST} . # RewriteCond %{HTTP_HOST} !^www\. [NC] # RewriteRule ^ http%{ENV:protossl}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # # To redirect all users to access the site WITHOUT the 'www.' prefix, # (http://www.example.com/... will be redirected to http://example.com/...) # uncomment the following: # RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] # RewriteRule ^ http%{ENV:protossl}://%1%{REQUEST_URI} [L,R=301]</IfModule>
Special chars with RewriteRule
Ex: a file or folder named tést $a? (te%CC%81st%20%24a%3F) is translated internaly to te\xcc\x81st $a (discarding handling ?)
Potential solution: use flag B or double URL encoding ?
# redirect bots to one pageRewriteEngine onRewriteCond%{HTTP_USER_AGENT}facebookexternalhit [NC,OR]RewriteCond%{HTTP_USER_AGENT}Facebot [NC,OR]RewriteCond%{HTTP_USER_AGENT}Twitterbot [NC,OR]RewriteCond%{HTTP_USER_AGENT}Baiduspider [NC,OR]RewriteCond%{HTTP_USER_AGENT}MetaURI [NC,OR]RewriteCond%{HTTP_USER_AGENT}mediawords [NC,OR]RewriteCond%{HTTP_USER_AGENT}FlipboardProxy [NC]RewriteCond%{REQUEST_URI}!\/nocrawler.htmlRewriteRule.*/nocrawler.html [L]
Or
# show a 403SetEnvIfNoCaseUser-Agent "facebookexternalhit" botSetEnvIfNoCaseUser-Agent "Facebot" botSetEnvIfNoCaseUser-Agent "Twitterbot" botSetEnvIfNoCaseUser-Agent "Baiduspider" botSetEnvIfNoCaseUser-Agent "MetaURI" botSetEnvIfNoCaseUser-Agent "mediawords" botSetEnvIfNoCaseUser-Agent "FlipboardProxy" bot<Limit GET POST HEAD>OrderAllow,DenyAllow from allDeny from env=bot</Limit>
Or use robot.txt
To get the list: add a honeypot URL, or use wp-login if it's a Wordpress website (but it will including you and others humans admin/users)