serviceworker-rails 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +4 -0
- data/Guardfile +42 -0
- data/README.md +34 -1
- data/Rakefile +5 -0
- data/bin/_guard-core +16 -0
- data/bin/guard +16 -0
- data/lib/serviceworker.rb +4 -15
- data/lib/serviceworker/middleware.rb +24 -36
- data/lib/serviceworker/rails.rb +4 -4
- data/lib/serviceworker/rails/handler.rb +33 -0
- data/lib/serviceworker/rails/version.rb +1 -1
- data/lib/serviceworker/railtie.rb +9 -10
- data/lib/serviceworker/route.rb +49 -0
- data/lib/serviceworker/router.rb +46 -0
- data/serviceworker-rails.gemspec +1 -1
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e15c642851a30d7cf973bc826cdd953de5248df2
|
4
|
+
data.tar.gz: ad30587132acd6fbf1052370d5dafa12f5d24edb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c695e3493724c49d99b7f8b72174057abd43ca4b73e6782706c80843efeca64c54512a535490f31a171b2f4e19175233b9a81f413fe5158d92b0e0ddaa3ef911
|
7
|
+
data.tar.gz: 2e4a8f6c092de36eb47fcaab1d0fb30bd21fa1244e8aa9b14dacf4757bcc87e5f0d7a9778c14d9af722b2002e1732188c5b5108a6f245fb2b208beb0d37c0048
|
data/Gemfile
CHANGED
data/Guardfile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
## Uncomment and set this to only include directories you want to watch
|
5
|
+
# directories %w(app lib config test spec features) \
|
6
|
+
# .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
|
7
|
+
|
8
|
+
## Note: if you are using the `directories` clause above and you are not
|
9
|
+
## watching the project directory ('.'), then you will want to move
|
10
|
+
## the Guardfile to a watched dir and symlink it back, e.g.
|
11
|
+
#
|
12
|
+
# $ mkdir config
|
13
|
+
# $ mv Guardfile config/
|
14
|
+
# $ ln -s config/Guardfile .
|
15
|
+
#
|
16
|
+
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
17
|
+
|
18
|
+
guard :minitest do
|
19
|
+
# with Minitest::Unit
|
20
|
+
watch(%r{^test/(.*)\/?(.*)_test\.rb$})
|
21
|
+
watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}#{m[2]}_test.rb" }
|
22
|
+
watch(%r{^test/test_helper\.rb$}) { 'test' }
|
23
|
+
|
24
|
+
# with Minitest::Spec
|
25
|
+
# watch(%r{^spec/(.*)_spec\.rb$})
|
26
|
+
# watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
27
|
+
# watch(%r{^spec/spec_helper\.rb$}) { 'spec' }
|
28
|
+
|
29
|
+
# Rails 4
|
30
|
+
# watch(%r{^app/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
|
31
|
+
# watch(%r{^app/controllers/application_controller\.rb$}) { 'test/controllers' }
|
32
|
+
# watch(%r{^app/controllers/(.+)_controller\.rb$}) { |m| "test/integration/#{m[1]}_test.rb" }
|
33
|
+
# watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" }
|
34
|
+
# watch(%r{^lib/(.+)\.rb$}) { |m| "test/lib/#{m[1]}_test.rb" }
|
35
|
+
# watch(%r{^test/.+_test\.rb$})
|
36
|
+
# watch(%r{^test/test_helper\.rb$}) { 'test' }
|
37
|
+
|
38
|
+
# Rails < 4
|
39
|
+
# watch(%r{^app/controllers/(.*)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" }
|
40
|
+
# watch(%r{^app/helpers/(.*)\.rb$}) { |m| "test/helpers/#{m[1]}_test.rb" }
|
41
|
+
# watch(%r{^app/models/(.*)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" }
|
42
|
+
end
|
data/README.md
CHANGED
@@ -26,7 +26,40 @@ Or install it yourself as:
|
|
26
26
|
|
27
27
|
## Usage
|
28
28
|
|
29
|
-
|
29
|
+
To use `serviceworker-rails` in a Rails app, install the gem as above. When
|
30
|
+
`serviceworker-rails` is required, it will insert a middleware into the Rails
|
31
|
+
middleware stack. You'll want to configure it by mapping serviceworker routes to
|
32
|
+
Sprockets JavaScript assets, like the example below, in `application.rb`.
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
# application.rb
|
36
|
+
|
37
|
+
config.serviceworker.routes.draw do
|
38
|
+
get "/basic-serviceworker.js"
|
39
|
+
|
40
|
+
get "/proxied-serviceworker.js"
|
41
|
+
asset: "nested/asset/serviceworker.js"
|
42
|
+
|
43
|
+
get "/nested/serviceworker.js",
|
44
|
+
asset: "another/serviceworker.js"
|
45
|
+
|
46
|
+
get "/header-serviceworker.js",
|
47
|
+
asset: "another/serviceworker.js",
|
48
|
+
headers: { "X-Resource-Header" => "A resource" }
|
49
|
+
|
50
|
+
get "/*/serviceworker.js",
|
51
|
+
asset: "serviceworker.js"
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
`Serviceworker-Rails` with insert a `Cache-Control` header to instruct browsers
|
56
|
+
not to cache your serviceworkers by default. You can customize the headers for all service worker routes if you'd like,
|
57
|
+
such as adding the experimental [`Service-Worker-Allowed`](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-allowed) header to set the allowed scope.
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
config.serviceworker.headers["Service-Worker-Allowed"] = "/"
|
61
|
+
config.serviceworker.headers["X-Custom-Header"] = "foobar"
|
62
|
+
```
|
30
63
|
|
31
64
|
## Development
|
32
65
|
|
data/Rakefile
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rake/testtask"
|
3
3
|
|
4
|
+
APP_RAKEFILE = File.expand_path("../test/sample/Rakefile", __FILE__)
|
5
|
+
load "rails/tasks/engine.rake"
|
6
|
+
|
7
|
+
Bundler::GemHelper.install_tasks
|
8
|
+
|
4
9
|
Rake::TestTask.new(:test) do |t|
|
5
10
|
t.libs << "test"
|
6
11
|
t.libs << "lib"
|
data/bin/_guard-core
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application '_guard-core' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require "pathname"
|
10
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require "rubygems"
|
14
|
+
require "bundler/setup"
|
15
|
+
|
16
|
+
load Gem.bin_path("guard", "_guard-core")
|
data/bin/guard
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'guard' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require "pathname"
|
10
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require "rubygems"
|
14
|
+
require "bundler/setup"
|
15
|
+
|
16
|
+
load Gem.bin_path("guard", "guard")
|
data/lib/serviceworker.rb
CHANGED
@@ -1,19 +1,8 @@
|
|
1
1
|
module ServiceWorker
|
2
|
-
|
3
|
-
|
4
|
-
# to . If you are using ServiceWorker.rb with Rails, you do not need to set
|
5
|
-
# this attribute manually.
|
6
|
-
#
|
7
|
-
# @return [String]
|
8
|
-
attr_accessor :root
|
9
|
-
|
10
|
-
# The logger to use when logging exception details and backtraces. If you
|
11
|
-
# are using Better Errors with Rails, you do not need to set this attribute
|
12
|
-
# manually. If this attribute is `nil`, nothing will be logged.
|
13
|
-
#
|
14
|
-
# @return [Logger, nil]
|
15
|
-
attr_accessor :logger
|
16
|
-
end
|
2
|
+
Error = Class.new(StandardError)
|
3
|
+
RouteError = Class.new(Error)
|
17
4
|
end
|
18
5
|
|
6
|
+
require "serviceworker/route"
|
7
|
+
require "serviceworker/router"
|
19
8
|
require "serviceworker/middleware"
|
@@ -3,64 +3,52 @@ module ServiceWorker
|
|
3
3
|
def initialize(app, opts = {})
|
4
4
|
@app = app
|
5
5
|
@opts = opts
|
6
|
-
|
7
|
-
@
|
6
|
+
@headers = opts.fetch(:headers, {}).merge(default_headers)
|
7
|
+
@router = opts.fetch(:routes, ServiceWorker::Router.new)
|
8
8
|
end
|
9
9
|
|
10
10
|
def call(env)
|
11
|
-
case env[
|
12
|
-
when
|
13
|
-
path = env[
|
11
|
+
case env["REQUEST_METHOD"]
|
12
|
+
when "GET", "HEAD"
|
13
|
+
path = env["PATH_INFO"].chomp("/")
|
14
14
|
info("responding to #{path}")
|
15
|
-
|
15
|
+
route = @router.match_route(path)
|
16
|
+
return respond_to_route(route, env) if route
|
16
17
|
end
|
17
18
|
|
18
19
|
@app.call(env)
|
19
20
|
end
|
20
21
|
|
21
|
-
def match?(path)
|
22
|
-
path == '/serviceworker.js'
|
23
|
-
end
|
24
|
-
|
25
22
|
private
|
26
23
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
[status, headers, body]
|
24
|
+
def default_headers
|
25
|
+
{
|
26
|
+
"Cache-Control" => "private, max-age=0, no-cache"
|
27
|
+
}
|
33
28
|
end
|
34
29
|
|
35
|
-
def
|
36
|
-
|
37
|
-
info "compiling #{path_info} from Sprockets"
|
38
|
-
sprockets_server.call(env)
|
39
|
-
else
|
40
|
-
file_path = asset_path(path_info)
|
41
|
-
info "Proxing #{path_info} from #{file_path}"
|
42
|
-
file_server.call(env.merge('PATH_INFO' => file_path))
|
43
|
-
end
|
44
|
-
end
|
30
|
+
def respond_to_route(route, env)
|
31
|
+
status, headers, body = process_handler(route, env)
|
45
32
|
|
46
|
-
|
47
|
-
@logger.info "[#{self.class}] - #{msg}"
|
33
|
+
[status, headers.merge(@headers).merge(route.headers), body]
|
48
34
|
end
|
49
35
|
|
50
|
-
def
|
51
|
-
|
36
|
+
def process_handler(route, env)
|
37
|
+
handler.call(env.merge("serviceworker.asset_name" => route.asset_name))
|
52
38
|
end
|
53
39
|
|
54
|
-
def
|
55
|
-
|
40
|
+
def info(msg)
|
41
|
+
logger.info "[#{self.class}] - #{msg}"
|
56
42
|
end
|
57
43
|
|
58
|
-
|
59
|
-
|
44
|
+
# TODO
|
45
|
+
# provide non-rails handler as default
|
46
|
+
def handler
|
47
|
+
@handler ||= @opts.fetch(:handler)
|
60
48
|
end
|
61
49
|
|
62
|
-
def
|
63
|
-
|
50
|
+
def logger
|
51
|
+
@logger ||= @opts.fetch(:logger, Logger.new(STDOUT))
|
64
52
|
end
|
65
53
|
end
|
66
54
|
end
|
data/lib/serviceworker/rails.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
module ServiceWorker
|
2
|
+
module Rails
|
3
|
+
class Handler
|
4
|
+
def call(env)
|
5
|
+
path_info = env.fetch("serviceworker.asset_name")
|
6
|
+
|
7
|
+
if config.compile
|
8
|
+
sprockets_server.call(env.merge("PATH_INFO" => path_info))
|
9
|
+
else
|
10
|
+
file_server.call(env.merge("PATH_INFO" => asset_path(path_info)))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def sprockets_server
|
17
|
+
::Rails.application.assets
|
18
|
+
end
|
19
|
+
|
20
|
+
def file_server
|
21
|
+
@file_server ||= ::Rack::File.new(::Rails.root.join("public"))
|
22
|
+
end
|
23
|
+
|
24
|
+
def config
|
25
|
+
::Rails.configuration.assets
|
26
|
+
end
|
27
|
+
|
28
|
+
def asset_path(path)
|
29
|
+
::ActionController::Base.helpers.asset_path(path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,20 +1,19 @@
|
|
1
1
|
require "rails"
|
2
2
|
require "rails/railtie"
|
3
|
+
require "serviceworker"
|
3
4
|
|
4
5
|
module ServiceWorker
|
5
6
|
class Railtie < ::Rails::Railtie
|
7
|
+
config.serviceworker = ActiveSupport::OrderedOptions.new
|
8
|
+
config.serviceworker.headers = {}
|
9
|
+
config.serviceworker.routes = ServiceWorker::Router.new
|
10
|
+
config.serviceworker.handler = ServiceWorker::Rails::Handler.new
|
11
|
+
|
6
12
|
initializer "serviceworker-rails.configure_rails_initialization" do
|
7
|
-
|
8
|
-
|
9
|
-
ServiceWorker.root = ::Rails.root.to_s
|
10
|
-
end
|
13
|
+
config.serviceworker.logger ||= ::Rails.logger
|
14
|
+
config.serviceworker.routes.draw_default unless config.serviceworker.routes.any?
|
11
15
|
|
12
|
-
|
13
|
-
if defined? ::Rack::SendFile
|
14
|
-
app.middleware.insert_after ::Rack::Sendfile, ServiceWorker::Middleware
|
15
|
-
else
|
16
|
-
app.middleware.use ServiceWorker::Middleware
|
17
|
-
end
|
16
|
+
app.middleware.use ServiceWorker::Middleware, config.serviceworker
|
18
17
|
end
|
19
18
|
|
20
19
|
def app
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module ServiceWorker
|
2
|
+
class Route
|
3
|
+
attr_reader :path, :options
|
4
|
+
|
5
|
+
def initialize(path, options = {})
|
6
|
+
@path = path
|
7
|
+
@options = options
|
8
|
+
|
9
|
+
@pattern = compile(path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def match?(path)
|
13
|
+
@pattern =~ path
|
14
|
+
end
|
15
|
+
|
16
|
+
def asset_name
|
17
|
+
@options.fetch(:asset, @path.gsub(%r{^/}, ""))
|
18
|
+
rescue NoMethodError
|
19
|
+
raise RouteError, "Cannot determine asset name from #{path.inspect}. Please specify the :asset option for this path."
|
20
|
+
end
|
21
|
+
|
22
|
+
def headers
|
23
|
+
@options.fetch(:headers, {})
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def compile(path)
|
29
|
+
if path.respond_to?(:to_str)
|
30
|
+
special_chars = %w[. + ( )]
|
31
|
+
pattern = path.to_str.gsub(/([\*#{special_chars.join}])/) do |match|
|
32
|
+
case match
|
33
|
+
when "*"
|
34
|
+
"(.*?)"
|
35
|
+
when *special_chars
|
36
|
+
Regexp.escape(match)
|
37
|
+
else
|
38
|
+
"([^/?&#]+)"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
/^#{pattern}$/
|
42
|
+
elsif path.respond_to?(:match)
|
43
|
+
path
|
44
|
+
else
|
45
|
+
raise TypeError, path
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ServiceWorker
|
2
|
+
class Router
|
3
|
+
def self.default
|
4
|
+
new.draw_default
|
5
|
+
end
|
6
|
+
|
7
|
+
attr_reader :routes
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@routes = []
|
11
|
+
|
12
|
+
draw(&Proc.new) if block_given?
|
13
|
+
end
|
14
|
+
|
15
|
+
def draw(&block)
|
16
|
+
return self unless block_given?
|
17
|
+
|
18
|
+
if block.arity == 1
|
19
|
+
block.call(self)
|
20
|
+
else
|
21
|
+
instance_eval(&block)
|
22
|
+
end
|
23
|
+
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def draw_default
|
28
|
+
draw { get "/serviceworker.js" }
|
29
|
+
end
|
30
|
+
|
31
|
+
def get(path, options = {})
|
32
|
+
Route.new(path, options).tap do |route|
|
33
|
+
@routes << route
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def any?
|
38
|
+
@routes.any?
|
39
|
+
end
|
40
|
+
|
41
|
+
def match_route(path)
|
42
|
+
@routes.detect { |r| r.match?(path) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/serviceworker-rails.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["rosskaff@gmail.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{ServiceWorker for Rails 3+}
|
13
|
-
spec.description = %q{Integrates ServiceWorker
|
13
|
+
spec.description = %q{Integrates ServiceWorker into the Rails asset pipeline.}
|
14
14
|
spec.homepage = "https://github.com/rossta/serviceworker-rails"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: serviceworker-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ross Kaffenberger
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-04-
|
11
|
+
date: 2016-04-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -94,7 +94,7 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
-
description: Integrates ServiceWorker
|
97
|
+
description: Integrates ServiceWorker into the Rails asset pipeline.
|
98
98
|
email:
|
99
99
|
- rosskaff@gmail.com
|
100
100
|
executables: []
|
@@ -105,10 +105,13 @@ files:
|
|
105
105
|
- ".travis.yml"
|
106
106
|
- CODE_OF_CONDUCT.md
|
107
107
|
- Gemfile
|
108
|
+
- Guardfile
|
108
109
|
- LICENSE.txt
|
109
110
|
- README.md
|
110
111
|
- Rakefile
|
112
|
+
- bin/_guard-core
|
111
113
|
- bin/console
|
114
|
+
- bin/guard
|
112
115
|
- bin/rake
|
113
116
|
- bin/rspec
|
114
117
|
- bin/setup
|
@@ -116,8 +119,11 @@ files:
|
|
116
119
|
- lib/serviceworker.rb
|
117
120
|
- lib/serviceworker/middleware.rb
|
118
121
|
- lib/serviceworker/rails.rb
|
122
|
+
- lib/serviceworker/rails/handler.rb
|
119
123
|
- lib/serviceworker/rails/version.rb
|
120
124
|
- lib/serviceworker/railtie.rb
|
125
|
+
- lib/serviceworker/route.rb
|
126
|
+
- lib/serviceworker/router.rb
|
121
127
|
- serviceworker-rails.gemspec
|
122
128
|
homepage: https://github.com/rossta/serviceworker-rails
|
123
129
|
licenses:
|