require 'erb' module Rack class LiveReload LIVERELOAD_JS_PATH = '/__rack/livereload.js' HEAD_TAG_REGEX = /|/ BAD_USER_AGENTS = [ %r{MSIE} ] def livereload_local_uri "http://localhost:#{@port}/livereload.js" end attr_reader :app def initialize(app, options = {}) @app, @options = app, options @port = @options[:live_reload_port] || 35729 end def use_vendored? return @use_vendored if @use_vendored if @options[:source] @use_vendored = (@options[:source] == :vendored) else require 'net/http' require 'uri' uri = URI.parse(livereload_local_uri) http = Net::HTTP.new(uri.host, uri.port) http.read_timeout = 1 begin http.send_request('GET', uri.path) @use_vendored = false rescue Timeout::Error, Errno::ECONNREFUSED, EOFError @use_vendored = true rescue => e $stderr.puts e.inspect raise e end end @use_vendored end def call(env) dup._call(env) end def _call(env) _, path, file = (env['PATH_INFO'] || '').split('/') if path == '__rack' && ::File.file?(target = ::File.expand_path("../../../js/#{file}", __FILE__)) deliver_file(target) else status, headers, body = result = @app.call(env) return result if headers['Content-Type'] and headers['Content-Type']['text/event-stream'] body.close if body.respond_to?(:close) new_body = [] ; body.each { |line| new_body << line.to_s } if !ignored?(env['PATH_INFO']) and !bad_browser?(env['HTTP_USER_AGENT']) if headers['Content-Type'] and status == 200 and headers['Content-Type'][%r{text/html}] content_length = 0 new_body.each do |line| if !headers['X-Rack-LiveReload'] && line[' type, 'Content-Length' => ::File.size(file).to_s }, [ ::File.read(file) ] ] end def force_swf? @options[:force_swf] end def with_swf? !@options[:no_swf] end end end