serviceworker-rails 0.1.0 → 0.2.0
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.
- 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:
|