detection and use of local livereload if available
This commit is contained in:
parent
38a3396cf2
commit
92479fdaff
11
README.md
11
README.md
@ -41,11 +41,20 @@ use Rack::LiveReload, :min_delay => 500, ...
|
||||
|
||||
## How it works
|
||||
|
||||
The necessary `script` tag to bring in a vendored copy of [livereload.js](https://github.com/livereload/livereload-js) is
|
||||
The necessary `script` tag to bring in a copy of [livereload.js](https://github.com/livereload/livereload-js) is
|
||||
injected right before the closing `head` tag in any `text/html` pages that come through. The `script` tag is built in
|
||||
such a way that the `HTTP_HOST` is used as the LiveReload host, so you can connect from external machines (say, to
|
||||
`mycomputer:3000` instead of `localhost:3000`) and as long as the LiveReload port is accessible from the external machine,
|
||||
you'll connect and be LiveReloading away!
|
||||
|
||||
### Which LiveReload script does it use?
|
||||
|
||||
* If you've got a LiveReload watcher running on the same machine as the app that responds
|
||||
to `http://localhost:35729/livereload.js`, that gets used, with the hostname being changed when
|
||||
injected into the HTML page.
|
||||
* If you don't, the copy vendored with rack-livereload is used.
|
||||
* You can force the use of either one (and save on the cost of checking to see if that file
|
||||
is available) with the middleware option `:source => :vendored` or `:source => :livereload`.
|
||||
|
||||
As usual, super-alpha!
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
module Rack
|
||||
class LiveReload
|
||||
LIVERELOAD_JS_PATH = '/__rack/livereload.js'
|
||||
LIVERELOAD_LOCAL_URI = 'http://localhost:35729/livereload.js'
|
||||
|
||||
attr_reader :app
|
||||
|
||||
@ -9,6 +10,31 @@ module Rack
|
||||
@options = options
|
||||
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
|
||||
@use_vendored = true
|
||||
end
|
||||
end
|
||||
|
||||
@use_vendored
|
||||
end
|
||||
|
||||
def call(env)
|
||||
if env['PATH_INFO'] == LIVERELOAD_JS_PATH
|
||||
deliver_file(::File.expand_path('../../../js/livereload.js', __FILE__))
|
||||
@ -21,12 +47,14 @@ module Rack
|
||||
|
||||
body.each do |line|
|
||||
if !headers['X-Rack-LiveReload'] && line['</head>']
|
||||
src = LIVERELOAD_JS_PATH.dup
|
||||
if @options[:host]
|
||||
src << "?host=#{@options[:host]}"
|
||||
host_to_use = @options[:host] || env['HTTP_HOST'].gsub(%r{:.*}, '')
|
||||
|
||||
if use_vendored?
|
||||
src = LIVERELOAD_JS_PATH.dup + "?host=#{host_to_use}"
|
||||
else
|
||||
src << "?host=#{env['HTTP_HOST'].gsub(%r{:.*}, '')}" if env['HTTP_HOST']
|
||||
src = LIVERELOAD_LOCAL_URI.dup.gsub('localhost', host_to_use) + '?'
|
||||
end
|
||||
|
||||
src << "&mindelay=#{@options[:min_delay]}" if @options[:min_delay]
|
||||
src << "&maxdelay=#{@options[:max_delay]}" if @options[:max_delay]
|
||||
src << "&port=#{@options[:port]}" if @options[:port]
|
||||
|
@ -28,6 +28,7 @@ Gem::Specification.new do |s|
|
||||
s.add_development_dependency "mocha"
|
||||
s.add_development_dependency "guard"
|
||||
s.add_development_dependency "guard-rspec"
|
||||
s.add_development_dependency "webmock"
|
||||
|
||||
s.add_runtime_dependency "rack"
|
||||
end
|
||||
|
@ -1,7 +1,7 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Rack::LiveReload do
|
||||
let(:middleware) { described_class.new(app) }
|
||||
let(:middleware) { described_class.new(app, options) }
|
||||
let(:app) { stub }
|
||||
|
||||
subject { middleware }
|
||||
@ -9,6 +9,37 @@ describe Rack::LiveReload do
|
||||
its(:app) { should == app }
|
||||
|
||||
let(:env) { {} }
|
||||
let(:options) { {} }
|
||||
|
||||
describe described_class::LIVERELOAD_LOCAL_URI do
|
||||
context 'does not exist' do
|
||||
before do
|
||||
stub_request(:any, 'localhost:35729/livereload.js').to_timeout
|
||||
end
|
||||
|
||||
it { should use_vendored }
|
||||
end
|
||||
|
||||
context 'exists' do
|
||||
before do
|
||||
stub_request(:any, 'localhost:35729/livereload.js')
|
||||
end
|
||||
|
||||
it { should_not use_vendored }
|
||||
end
|
||||
|
||||
context 'specify vendored' do
|
||||
let(:options) { { :source => :vendored } }
|
||||
|
||||
it { should use_vendored }
|
||||
end
|
||||
|
||||
context 'specify LR' do
|
||||
let(:options) { { :source => :livereload } }
|
||||
|
||||
it { should_not use_vendored }
|
||||
end
|
||||
end
|
||||
|
||||
context 'not text/html' do
|
||||
let(:ret) { [ 200, { 'Content-Type' => 'image/png' }, [ '<head></head>' ] ] }
|
||||
@ -25,6 +56,7 @@ describe Rack::LiveReload do
|
||||
context 'text/html' do
|
||||
before do
|
||||
app.stubs(:call).with(env).returns([ 200, { 'Content-Type' => 'text/html', 'Content-Length' => 0 }, [ '<head></head>' ] ])
|
||||
middleware.stubs(:use_vendored?).returns(true)
|
||||
end
|
||||
|
||||
let(:host) { 'host' }
|
||||
@ -34,7 +66,8 @@ describe Rack::LiveReload do
|
||||
let(:body) { ret.last.join }
|
||||
let(:length) { ret[1]['Content-Length'] }
|
||||
|
||||
it 'should add the livereload js script tag' do
|
||||
context 'vendored' do
|
||||
it 'should add the vendored livereload js script tag' do
|
||||
body.should include("script")
|
||||
body.should include(described_class::LIVERELOAD_JS_PATH)
|
||||
|
||||
@ -42,6 +75,18 @@ describe Rack::LiveReload do
|
||||
|
||||
described_class::LIVERELOAD_JS_PATH.should_not include(host)
|
||||
end
|
||||
end
|
||||
|
||||
context 'not vendored' do
|
||||
before do
|
||||
middleware.stubs(:use_vendored?).returns(false)
|
||||
end
|
||||
|
||||
it 'should add the LR livereload js script tag' do
|
||||
body.should include("script")
|
||||
body.should include(described_class::LIVERELOAD_LOCAL_URI.gsub('localhost', 'host'))
|
||||
end
|
||||
end
|
||||
|
||||
context 'set options' do
|
||||
let(:middleware) { described_class.new(app, :host => new_host, :port => port, :min_delay => min_delay, :max_delay => max_delay) }
|
||||
|
@ -1,7 +1,16 @@
|
||||
require 'mocha'
|
||||
require 'webmock/rspec'
|
||||
|
||||
require 'rack-livereload'
|
||||
|
||||
RSpec.configure do |c|
|
||||
c.mock_with :mocha
|
||||
end
|
||||
|
||||
module RSpec::Matchers
|
||||
define :use_vendored do
|
||||
match do |subject|
|
||||
subject.use_vendored?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user