public
Last active — forked from chriskottom/Rack::DomainSprinkler

  • Download Gist
Rack::DomainSprinkler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
require 'nokogiri'
require 'pstore'
 
 
#
# Rack::DomainSprinkler
#
# Modifies outgoing HTML markup so that common static assets like script source
# files, images, and stylesheets will be served from one of a number of domains
# rather than just a single one in order to improve parallelization of resource
# downloads during page loads.
#
module Rack
class DomainSprinkler
 
#
# Options:
# A list of domains across which to spread requests
# The name of the file to be used for caching URL/path mappings
#
def initialize(app, domains=[], cache_loc="tmp/sprinklins.pstore")
@app = app
@@domains = domains
@@url_cache = PStore.new(cache_loc)
end
 
 
def call(env)
dup._call(env)
end
 
 
#
# Currently only looks for <link>, <script>, and <img> tags.
# Should be refactored to provide more generic mapping.
#
def _call(env)
status, headers, response = @app.call(env)
if headers["Content-Type"] =~ /^text\/html/
document = Nokogiri::HTML(response.body)
sprinkle(env, document, 'link', 'href')
sprinkle(env, document, 'script', 'src')
sprinkle(env, document, 'img', 'src')
response.body = document.to_html
end
 
[status, headers, response]
end
 
 
def sprinkle(env, document, selector, property)
document.search(selector).each do |node|
url = node[property]
if !url.empty? and url !~ /^\#/ and url !~ /^http\:\/\//
node[property] = domainify(url, env)
end
end
end
 
 
def domainify(path, env)
if path !~ /\//
path = absolutify(path)
end
full_url = nil
@@url_cache.transaction do
unless @@url_cache[path]
domain = @@domains.shift and @@domains.push(domain)
@@url_cache[path] = "http://#{ domain }#{ path }"
end
full_url = @@url_cache[path]
end
 
full_url
end
 
 
def absolutify(path, env)
path_prefix = env['REQUEST_PATH']
unless path_prefix =~ /\/$/
path_prefix.sub!(/\/[^\/]+$/, '')
end
 
"#{ tmp_path }/#{ path }"
end
 
end
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.