Created
October 29, 2009 08:38
-
-
Save chriskottom/221275 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment