marcinbunsch-quick_serve 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -1,12 +1,36 @@
1
- = quick_serve
1
+ == quick_serve
2
2
 
3
3
  quick_serve is a super-simple way of serving static files for development. It was made mainly for javascript development, but might have other uses.
4
4
 
5
- = usage
5
+ = General usage
6
6
 
7
- Type 'qs' or 'quick_serve'
7
+ Type 'qs' or 'quick_serve'. By default it will use port 5000, but if you run 'qs -p 4000' it will use 4000 (or any other you specify)
8
8
 
9
- By default it will use port 3000, but if you run 'qs 4000' it will use 4000 (or any other you specify)
9
+ *Options:*
10
+ * *-p PORT, --port PORT* Specify port (default: 5000)
11
+ * *--dir DIRECTORY* Specify directory to act as docroot (default: current directory)
12
+ * *--host HOST* Specify host (default: 0.0.0.0)
13
+ * *-s URL, --snapshot URL* Specify url for snapshot
14
+ * *-q* quit deamon (if present)
15
+ * *-d, --deamon* Run as a deamon process
16
+
17
+ = Snapshot mode usage
18
+
19
+ When evoked with -s trailed with an url, quick_serve will fetch the url and serve it regardless of the path you call. It's useful for testing js/css as it serves the snapshot from memory, minimizing cpu/memory usage leaving the browser with reloading js/css.
20
+
21
+ = Rails usage
22
+
23
+ quick_serve has a Rails adapter which can be called by adding this in environment.rb:
24
+
25
+ require 'quick_serve'
26
+
27
+ It's aimed at giving you a boost of speed on resource hungry pages when you're working on js/css.
28
+ It will store all generated pages requested with GET and having no flash on it and free the snapshot collection when:
29
+
30
+ * Any object is saved or destroyed in ActiveRecord
31
+ * Any file is changed in the app/ directory
32
+
33
+ Keep in mind, it will run only in development mode.
10
34
 
11
35
  == Note on Patches/Pull Requests
12
36
 
data/Rakefile CHANGED
@@ -13,7 +13,8 @@ begin
13
13
  gem.bindir = 'bin'
14
14
  gem.executables = ['quick_serve', 'qs']
15
15
  gem.default_executable = 'qs'
16
-
16
+ gem.files = []
17
+ gem.files = FileList['*', '{bin,lib,images,spec}/**/*']
17
18
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
18
19
  end
19
20
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.1
data/bin/qs CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'rubygems'
3
3
  require 'quick_serve'
4
- QuickServe.new.start
4
+ QuickServe::Server.new.start
data/bin/quick_serve CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'rubygems'
3
3
  require 'quick_serve'
4
- QuickServe.new.start
4
+ QuickServe::Server.new.start
@@ -0,0 +1,27 @@
1
+ # Here we hack mongrel do jump in front of the handler
2
+ module Mongrel
3
+ module Rails
4
+ class RailsHandler
5
+
6
+ alias_method :original_process, :process
7
+
8
+ def process(request, response)
9
+ # only serve GET
10
+ return original_process(request, response) if request.params['REQUEST_METHOD'] != 'GET'
11
+ url = 'http://' + request.params["HTTP_HOST"] + request.params["REQUEST_URI"]
12
+ snapshot = QuickServe::Rails::Snapshot.fetch(url)
13
+ if snapshot
14
+ response.start do |head,out|
15
+ puts "quick_serve: served snapshot of #{url}"
16
+ head["Content-Type"] = "text/html"
17
+ out << snapshot
18
+ end
19
+ else
20
+ original_process(request, response)
21
+ end
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ module ActionController
2
+ class Base
3
+ after_filter :store_snapshot
4
+ def store_snapshot
5
+ puts "quick_serve: stored snapshot as #{request.url}"
6
+ # do not store redirects or pages with flash
7
+ QuickServe::Rails::Snapshot.store(request.url, response.body) if !response.redirected_to and flash == {}
8
+ end
9
+ end
10
+ end
11
+
12
+ module ActiveRecord
13
+ class Base
14
+
15
+ after_save :free_snapshots
16
+ after_destroy :free_snapshots
17
+
18
+ def free_snapshots
19
+ QuickServe::Rails::Snapshot.reset
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,81 @@
1
+ require 'find'
2
+ #
3
+ # QuickServe::Listener
4
+ #
5
+ # The generic Listener, which polls the files after a specific interval
6
+ #
7
+ module QuickServe
8
+ module Rails
9
+ class Listener
10
+ attr_accessor :files, :interval
11
+
12
+ # constructor
13
+ def initialize
14
+ self.interval = 2 # decrease the CPU load by increasing the interval
15
+ end
16
+
17
+ # find files and start the listener
18
+ def start
19
+ puts "** quick_serve: scanning for files... "
20
+ # build a file collection
21
+ find_files
22
+ puts "** quick_serve: watching #{files.size} files for changes... "
23
+ wait
24
+ end
25
+
26
+ # wait for a specified interval and check files for changes
27
+ # source: ZenTest/autotest.rb
28
+ def wait
29
+ Kernel.sleep self.interval until check_files
30
+ end
31
+
32
+ # check files to find these that have changed
33
+ def check_files
34
+ updated = []
35
+ files.each do |filename, mtime|
36
+ begin
37
+ current_mtime = File.stat(filename).mtime
38
+ rescue Errno::ENOENT
39
+ # file was not found and was probably deleted
40
+ # remove the file from the file list
41
+ files.delete(filename)
42
+ next
43
+ end
44
+ if current_mtime != mtime
45
+ updated << filename
46
+ # update the mtime in file registry so we it's only send once
47
+ files[filename] = current_mtime
48
+ # puts ">> Spotted change in #{filename}"
49
+ end
50
+ end
51
+ QuickServe::Rails::Snapshot.reset if updated != []
52
+ false
53
+ end
54
+
55
+ ##
56
+ # Find the files to process, ignoring temporary files, source
57
+ # configuration management files, etc., and return a Hash mapping
58
+ # filename to modification time.
59
+ # source: ZenTest/autotest.rb
60
+ def find_files
61
+ result = {}
62
+ targets = ['app'] # start simple
63
+ targets.each do |target|
64
+ order = []
65
+ Find.find(target) do |f|
66
+ next if test ?d, f
67
+ next if f =~ /(swp|~|rej|orig)$/ # temporary/patch files
68
+ next if f =~ /(\.svn|\.git)$/ # subversion/git
69
+ next if f =~ /\/\.?#/ # Emacs autosave/cvs merge files
70
+ filename = f.sub(/^\.\//, '')
71
+
72
+ result[filename] = File.stat(filename).mtime rescue next
73
+ end
74
+ end
75
+
76
+ self.files = result
77
+ end
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,28 @@
1
+ # Storage for snapshots of pages generated by rails
2
+ module QuickServe
3
+ module Rails
4
+ class Snapshot
5
+ @@snapshots = {}
6
+
7
+ # return collection
8
+ def self.dump
9
+ @@snapshots
10
+ end
11
+
12
+ # remove all snapshots
13
+ def self.reset
14
+ @@snapshots = {}
15
+ end
16
+
17
+ # store a snapshot under specified key
18
+ def self.store(key, snapshot)
19
+ @@snapshots[key] = snapshot
20
+ end
21
+
22
+ # fetch a snapshot stored under specified key
23
+ def self.fetch(key)
24
+ @@snapshots[key]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,6 @@
1
+ require 'quick_serve/rails/snapshot'
2
+ require 'quick_serve/rails/listener'
3
+ require 'quick_serve/rails/ext/mongrel'
4
+ require 'quick_serve/rails/ext/rails'
5
+ puts "** quick_serve: attaching rails snapshot handler"
6
+ Thread.new { QuickServe::Rails::Listener.new.start }
@@ -0,0 +1,92 @@
1
+ module QuickServe
2
+ class Server
3
+
4
+ def initialize
5
+ @options = { :dir => '.', :port => 5000, :host => '0.0.0.0', :deamon => false, :url => nil }
6
+ parse
7
+ end
8
+
9
+ def start
10
+ if @options[:url]
11
+ puts "quick_serve: running in snapshot mode using #{@options[:url]} as source"
12
+ else
13
+ puts "quick_serve: mongrel running on port #{@options[:port]} with current directory as docroot"
14
+ end
15
+ begin
16
+ if @options[:deamon]
17
+ pid = fork do
18
+ $stderr, $stdout = StringIO.new, StringIO.new
19
+ serve
20
+ end
21
+ File.open(pidfile, 'w') {|f| f.write(pid) }
22
+ else
23
+ serve
24
+ end
25
+ rescue Errno::EADDRINUSE
26
+ puts "quick_serve: port #{@options[:port]} is used by another process. Please specify other port using the -p option"
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def serve
33
+ options = @options
34
+ config = Mongrel::Configurator.new :host => options[:host], :port => options[:port] do
35
+ listener do
36
+ if options[:url]
37
+ require 'quick_serve/snapshot/handler'
38
+ uri "/", :handler => QuickServe::Snapshot::Handler.new(options[:url])
39
+ else
40
+ uri "/", :handler => Mongrel::DirHandler.new(options[:dir])
41
+ end
42
+ end
43
+ trap("INT") { stop }
44
+ run
45
+ end
46
+ config.join
47
+ end
48
+
49
+ def parse
50
+ require 'optparse'
51
+ OptionParser.new do |opts|
52
+ opts.banner = "Usage: qs [options]"
53
+
54
+ opts.on("-p PORT", "--port PORT", "Specify port (default: 5000)") { |value| @options[:port] = value; }
55
+ opts.on("--dir DIRECTORY", "Specify directory to act as docroot (default: current directory)") { |value| @options[:dir] = value; }
56
+ opts.on("--host HOST", "Specify host (default: 0.0.0.0)") { |value| @options[:host] = value; }
57
+ opts.on("-s URL", "--snapshot URL", "Specify url for snapshot") { |value| @options[:url] = value; }
58
+ opts.on("-q", "quit deamon (if present)") { quit }
59
+ opts.on("-d", "--deamon", "Run as a deamon process") { @options[:deamon] = true; }
60
+ opts.on_tail("-h", "--help", "Show this message") do
61
+ puts opts
62
+ exit
63
+ end
64
+ end.parse!
65
+ end
66
+
67
+ def quit
68
+
69
+ print "Stopping quick serve... "
70
+ die(" pid file not found") if !File.exists?(pidfile)
71
+ pid = File.read(pidfile)
72
+ begin
73
+ if Process.kill("INT", pid.to_i) == 1
74
+ puts ' ok'
75
+ File.delete(pidfile) if File.exist?(pidfile)
76
+ end
77
+ rescue Errno::ESRCH
78
+ puts ' not found'
79
+ end
80
+ exit
81
+ end
82
+
83
+ def pidfile
84
+ File.join(@options[:dir], "qs.#{@options[:port]}.pid")
85
+ end
86
+
87
+ def die(msg)
88
+ puts msg
89
+ exit(1)
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,31 @@
1
+ module QuickServe
2
+ module Snapshot
3
+ class Handler < Mongrel::HttpHandler
4
+
5
+ def initialize(url)
6
+ @url = url
7
+ @https = (url.match('https:') ? true : false)
8
+ @host = url.gsub(/(http)(s*)(\:\/\/)/, '').split('/').first
9
+ @snapshot = nil
10
+ fetch
11
+ super()
12
+ end
13
+
14
+ def fetch
15
+ require 'open-uri'
16
+ @snapshot = open(@url).read
17
+ host_root = (@https ? 'https://' : 'http://') + @host + '/'
18
+ @snapshot.gsub!(/(href=|src=)(['"])(\/)/, "\\1\\2#{host_root}\\4")
19
+ end
20
+
21
+ def process(request, response)
22
+ response.start do |head,out|
23
+ puts "quick_serve: served snapshot of #{@url}"
24
+ head["Content-Type"] = "text/html"
25
+ out << @snapshot
26
+ end
27
+ end
28
+
29
+ end
30
+ end
31
+ end
data/lib/quick_serve.rb CHANGED
@@ -1,92 +1,17 @@
1
- begin
2
- require 'mongrel'
3
- rescue LoadError
4
- puts "quick_serve requires mongrel. Install it with: gem install mongrel"
5
- exit(1)
6
- end
7
-
8
- class QuickServe
9
-
10
- def initialize
11
- @options = { :dir => '.', :port => 3000, :host => '0.0.0.0', :deamon => false }
12
- parse
1
+ if defined?(RAILS_ENV)
2
+ if RAILS_ENV == 'development'
3
+ require 'quick_serve/rails'
4
+ else
5
+ puts "** quick_serve: quick_serve rails adapter can run only in development environment"
13
6
  end
14
-
15
-
16
- def start
17
- puts "quick_serve: Mongrel running on port #{@options[:port]} current directory as docroot"
18
- begin
19
- if @options[:deamon]
20
- pid = fork do
21
- captured_stdout = StringIO.new
22
- old_stdout, $stdout = $stdout, captured_stdout
23
- captured_stderr = StringIO.new
24
- old_stderr, $stdout = $stdout, captured_stderr
25
- serve
26
- end
27
- File.open(pidfile, 'w') {|f| f.write(pid) }
28
- else
29
- serve
30
- end
31
- rescue Errno::EADDRINUSE
32
- puts "quick_serve: Port #{@options[:port]} is used by another process. Please specify other port using the -p option"
33
- end
7
+ else
8
+ begin
9
+ require 'mongrel'
10
+ rescue LoadError
11
+ puts "quick_serve requires mongrel. Install it with: gem install mongrel"
12
+ exit(1)
34
13
  end
35
-
36
- private
37
14
 
38
- def serve
39
- options = @options
40
- config = Mongrel::Configurator.new :host => options[:host], :port => options[:port] do
41
- listener do
42
- uri "/", :handler => Mongrel::DirHandler.new(options[:dir])
43
- end
44
- trap("INT") { stop }
45
- run
46
- end
47
- config.join
48
- end
49
-
50
- def parse
51
- require 'optparse'
52
- OptionParser.new do |opts|
53
- opts.banner = "Usage: qs [options]"
54
-
55
- opts.on("-p PORT", "--port PORT", "Specify port") { |value| @options[:port] = value; }
56
- opts.on("--dir DIRECTORY", "Specify directory to act as docroot") { |value| @options[:dir] = value; }
57
- opts.on("--host HOST", "Specify host") { |value| @options[:host] = value; }
58
- # opts.on("quit", "quit deamon (if present)") { quit }
59
- opts.on("-q", "quit deamon (if present)") { quit }
60
- opts.on("-d", "--deamon", "Run as a deamon process") { @options[:deamon] = true; }
61
- opts.on_tail("-h", "--help", "Show this message") do
62
- puts opts
63
- exit
64
- end
65
- end.parse!
66
- end
67
-
68
- def quit
69
-
70
- print "Stopping quick serve... "
71
- die(" pid file not found") if !File.exists?(pidfile)
72
- pid = File.read(pidfile)
73
- begin
74
- if Process.kill("INT", pid.to_i) == 1
75
- puts ' ok'
76
- File.delete(pidfile) if File.exist?(pidfile)
77
- end
78
- rescue Errno::ESRCH
79
- puts ' not found'
80
- end
81
- exit
82
- end
83
-
84
- def pidfile
85
- File.join(@options[:dir], "qs.#{@options[:port]}.pid")
86
- end
87
-
88
- def die(msg)
89
- puts msg
90
- exit(1)
91
- end
92
- end
15
+ require 'quick_serve/server'
16
+ require 'quick_serve/snapshot_handler'
17
+ end
data/quick_serve.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{quick_serve}
5
- s.version = "0.2.0"
5
+ s.version = "0.3.1"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Marcin Bunsch"]
9
- s.date = %q{2009-09-12}
9
+ s.date = %q{2009-09-13}
10
10
  s.default_executable = %q{qs}
11
11
  s.description = %q{}
12
12
  s.email = %q{marcin@applicake.com}
@@ -16,17 +16,21 @@ Gem::Specification.new do |s|
16
16
  "README.rdoc"
17
17
  ]
18
18
  s.files = [
19
- ".document",
20
- ".gitignore",
21
- "LICENSE",
19
+ "LICENSE",
22
20
  "README.rdoc",
23
21
  "Rakefile",
24
22
  "VERSION",
25
23
  "bin/qs",
26
24
  "bin/quick_serve",
27
25
  "lib/quick_serve.rb",
28
- "quick_serve.gemspec",
29
- "test/test_helper.rb"
26
+ "lib/quick_serve/rails.rb",
27
+ "lib/quick_serve/rails/ext/mongrel.rb",
28
+ "lib/quick_serve/rails/ext/rails.rb",
29
+ "lib/quick_serve/rails/listener.rb",
30
+ "lib/quick_serve/rails/snapshot.rb",
31
+ "lib/quick_serve/server.rb",
32
+ "lib/quick_serve/snapshot/handler.rb",
33
+ "quick_serve.gemspec"
30
34
  ]
31
35
  s.homepage = %q{http://github.com/marcinbunsch/quick_serve}
32
36
  s.rdoc_options = ["--charset=UTF-8"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marcinbunsch-quick_serve
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcin Bunsch
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-09-12 00:00:00 -07:00
12
+ date: 2009-09-13 00:00:00 -07:00
13
13
  default_executable: qs
14
14
  dependencies: []
15
15
 
@@ -24,8 +24,6 @@ extra_rdoc_files:
24
24
  - LICENSE
25
25
  - README.rdoc
26
26
  files:
27
- - .document
28
- - .gitignore
29
27
  - LICENSE
30
28
  - README.rdoc
31
29
  - Rakefile
@@ -33,8 +31,14 @@ files:
33
31
  - bin/qs
34
32
  - bin/quick_serve
35
33
  - lib/quick_serve.rb
34
+ - lib/quick_serve/rails.rb
35
+ - lib/quick_serve/rails/ext/mongrel.rb
36
+ - lib/quick_serve/rails/ext/rails.rb
37
+ - lib/quick_serve/rails/listener.rb
38
+ - lib/quick_serve/rails/snapshot.rb
39
+ - lib/quick_serve/server.rb
40
+ - lib/quick_serve/snapshot/handler.rb
36
41
  - quick_serve.gemspec
37
- - test/test_helper.rb
38
42
  has_rdoc: false
39
43
  homepage: http://github.com/marcinbunsch/quick_serve
40
44
  licenses:
data/.document DELETED
@@ -1,5 +0,0 @@
1
- README.rdoc
2
- lib/**/*.rb
3
- bin/*
4
- features/**/*.feature
5
- LICENSE
data/.gitignore DELETED
@@ -1,5 +0,0 @@
1
- *.sw?
2
- .DS_Store
3
- coverage
4
- rdoc
5
- pkg