I have a HTML list of about 500 items and a "filter" box above it. I started by using jQuery to filter the list when I typed a letter (timing code added later): $('#filter').keyup( function() { var jqStart = (new Date).getTime(); var search = $(this).val().toLowerCase(); var $list = $('ul.ablist > li'); $list.each( function() { if ( $(this).text().toLowerCase().indexOf(search) === -1 ) $(this).hide(); else $(this).show(); } ); console.log('Time: ' + ((new Date).getTime() - jqStart)); } ); However, there was a couple of seconds delay after typing each letter (particularly the first letter). So I thought it may be slightly quicker if I used plain Javascript (I read recently that jQuery's each function is particularly slow). Here's my JS equivalent: document.getElementById('filter').addEventListener( 'keyup', function () { var jsStart = (new Date).getTime()...
Where to place mod_rewrite rules
ReplyDeletemod_rewrite rules may be placed within the httpd.conf file, or within the .htaccess file. if you have access to httpd.conf, placing rules here will offer a performance benefit (as the rules are processed once, as opposed to each time the .htaccess file is called).
Logging mod_rewrite requests
logging may be enabled from within the httpd.conf file (including <Virtual Host>):
# logs can't be enabled from .htaccess
# loglevel > 2 is really spammy!
RewriteLog /path/to/rewrite.log
RewriteLogLevel 2
Common use cases
to funnel all requests to a single point:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f # ignore existing files
RewriteCond %{REQUEST_FILENAME} !-d # ignore existing directories
RewriteRule ^(.*)$ index.php?query=$1 # map requests to index.php and append
# as a query string
handling 301/302 redirects:
RewriteEngine on
RewriteRule ^oldpage.html$ /newpage.html [R=302] # 302 Redirect
RewriteRule ^oldpage2.html$ /newpage.html [R=301] # 301 Redirect
note: external redirects are implicitly 302 redirects:
# this rule:
RewriteRule ^somepage.html$ http://google.com
# is equivalent to:
RewriteRule ^somepage.html$ http://google.com [R]
# and:
RewriteRule ^somepage.html$ http://google.com [R=302]
forcing SSL
RewriteEngine on
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://mysite.com/$1 [R,L]
common flag usage:
[R] force a redirect (default 302)
[R=301] force a 301 redirect
[L] stop rewriting process (see note below in common pitfalls)
[NC] case insensitive matches
you can mix and match flags:
RewriteRule ^olddir(.*)$ /newdir$1 [L,NC]
Common pitfalls
mixing mod_alias style redirects with mod_rewrite
# Bad
Redirect 302 /somepage.html http://mysite.com/otherpage.html
RewriteEngine on
RewriteRule ^(.*)$ index.php?query=$1
# Good (use mod_rewrite for both)
RewriteEngine on
RewriteRule ^somepage.html$ /otherpage.html [R=302,L] # 302 redirect, and stop processing
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?query=$1 # handle other redirects
note: you can mix mod_alias with mod_rewrite, but it involves more work than just handling basic redirects as above.
context affects syntax
within .htaccess files, a leading slash is not used in the pattern:
# given: GET /directory/file.html
# .htaccess
# result: /newdirectory/file.html
RewriteRule ^directory(.*)$ /newdirectory$1
# .htaccess
# result: no match!
RewriteRule ^/directory(.*)$ /newdirectory$1
# httpd.conf
# result: /newdirectory/file.html
RewriteRule ^/directory(.*)$ /newdirectory$1
# Works in both contexts:
RewriteRule ^/?directory(.*)$ /newdirectory$1
[L] is not last! (sometimes)
within the .htaccess context, [L] will not force mod_rewrite to stop. it will continue to trigger internal sub-requests:
RewriteRule ^dirA$ /dirB [L] # processing does not stop here
RewriteRule ^dirB$ /dirC # /dirC will be the final result
our rewrite log shows the details:
rewrite 'dirA' -> '/dirB'
internal redirect with /dirB [INTERNAL REDIRECT]
rewrite 'dirB' -> '/dirC'
The deal with RewriteBase:
ReplyDeleteYou almost always need to set RewriteBase. If you don't, apache guesses that your base is the physical disk path to your directory. So start with this:
RewriteBase /
if you need to 'block' internal redirects / rewrites from happening in the .htaccess, take a look at the
ReplyDeleteRewriteCond %{ENV:REDIRECT_STATUS} ^$
condition, as discussed here.
Equation can be done with following example:
ReplyDeleteRewriteCond %{REQUEST_URI} ^/(server0|server1).*$ [NC]
# %1 is the string that was found above
# %1<>%{HTTP_COOKIE} concatenates first macht with mod_rewrite variable -> "test0<>foo=bar;"
#RewriteCond search for a (.*) in the second part -> \1 is a reference to (.*)
# <> is used as an string separator/indicator, can be replaced by any other character
RewriteCond %1<>%{HTTP_COOKIE} !^(.*)<>.*stickysession=\1.*$ [NC]
RewriteRule ^(.*)$ https://notmatch.domain.com/ [R=301,L]
Dynamic Load Balancing:
If you use the mod_proxy to balance your system, it's possible to add a dynamic range of worker server.
RewriteCond %{HTTP_COOKIE} ^.*stickysession=route\.server([0-9]{1,2}).*$ [NC]
RewriteRule (.*) https://worker%1.internal.com/$1 [P,L]
Another great feature are rewrite-map-expansions. They're especially useful if you have a massive amout of hosts / rewrites to handle:
ReplyDeleteThey are like a key-value-replacement:
RewriteMap examplemap txt:/path/to/file/map.txt
Then you can use a mapping in your rules like:
RewriteRule ^/ex/(.*) ${examplemap:$1}
More information on this topic can be found here:
http://httpd.apache.org/docs/2.0/mod/mod%5Frewrite.html#mapfunc