static_signature 0.0.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.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ *.rvmrc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in static_signature.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Brendon Murphy
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,60 @@
1
+ # StaticSignature
2
+
3
+ Rack Middleware for adding query string cache busting signatures on
4
+ script and style assets. This is accomplished by parsing html responses
5
+ and appending an md5 hexdigest of file contents to the querystring.
6
+
7
+ In other words it turns this:
8
+ ```html
9
+ <link href="/stylesheets/screen.css" rel="stylesheet">
10
+ ```
11
+
12
+ into this:
13
+ ```html
14
+ <link href="/stylesheets/screen.css?4a75c99cdc76e7e0f3f3a0d6a44338a4" rel="stylesheet">
15
+ ```
16
+
17
+ This is intended to be a very limited implementation and makes a few
18
+ assumptions:
19
+
20
+ * You are OK with Nokogiri parsing and modifying all text/html responses
21
+ * The markup all uses simple urls that don't already have query params or
22
+ such appended already
23
+ * Query params style cachebusting gotchas aren't going to pose a big problem
24
+ for you
25
+
26
+ If you need a more feature rich implementation, Sprockets/AssetPipeline would
27
+ better fit the bill. This is intended for getting small, sinatra-esque apps
28
+ up quickly where the gorilla isn't needed yet.
29
+
30
+ ## Installation
31
+
32
+ Add this line to your application's Gemfile:
33
+
34
+ gem 'static_signature'
35
+
36
+ And then execute:
37
+
38
+ $ bundle
39
+
40
+ Or install it yourself as:
41
+
42
+ $ gem install static_signature
43
+
44
+ ## Usage
45
+
46
+ Enable the middleware providing the path to your static assets directory:
47
+
48
+ ```ruby
49
+ use StaticSignature::Middleware, :static_dir => File.join(File.dirname(__FILE__), "public")
50
+ ```
51
+
52
+ Note the `static_dir` option is mandatory and must be an absolute path.
53
+
54
+ ## Contributing
55
+
56
+ 1. Fork it
57
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
58
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
59
+ 4. Push to the branch (`git push origin my-new-feature`)
60
+ 5. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,56 @@
1
+ require "static_signature/version"
2
+ require "thread"
3
+ require "nokogiri"
4
+
5
+ module StaticSignature
6
+ class Middleware
7
+ def initialize(app, options = {})
8
+ @app = app
9
+ @static_dir = options.fetch(:static_dir)
10
+ @mutex = Mutex.new
11
+ end
12
+
13
+ def call(env)
14
+ dup._call(env)
15
+ end
16
+
17
+ def _call(env)
18
+ status, headers, response = @app.call(env)
19
+
20
+ if headers["Content-Type"] !~ /text\/html/
21
+ [status, headers, response]
22
+ else
23
+ body = ""
24
+ response.each do |part|
25
+ body << part
26
+ end
27
+ doc = Nokogiri::HTML(body)
28
+ bust_tag(doc, "link", "href")
29
+ bust_tag(doc, "script", "src")
30
+ body = doc.to_html
31
+ headers["Content-Length"] = body.bytesize.to_s
32
+ [status, headers, [body]]
33
+ end
34
+ end
35
+
36
+ def bust_tag(doc, tag_name, attribute)
37
+ doc.search(tag_name).each do |node|
38
+ if node[attribute] && ! node[attribute].include?("//")
39
+ node[attribute] += "?#{asset_signature(node[attribute])}"
40
+ end
41
+ end
42
+ end
43
+
44
+ def asset_signature(path)
45
+ full_path = File.join(@static_dir, path)
46
+
47
+ @mutex.synchronize {
48
+ signature_cache[path] ||= Digest::MD5.hexdigest(File.read(full_path))
49
+ }
50
+ end
51
+
52
+ def signature_cache
53
+ Thread.current[:_signature_cache] ||= {}
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,3 @@
1
+ module StaticSignature
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/static_signature/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Brendon Murphy"]
6
+ gem.email = ["xternal1+github@gmail.com"]
7
+ gem.description = %q{Rack Middleware for adding query string cache busting signatures on
8
+ script and style assets}
9
+ gem.summary = gem.description
10
+ gem.homepage = ""
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.name = "static_signature"
16
+ gem.require_paths = ["lib"]
17
+ gem.version = StaticSignature::VERSION
18
+
19
+ gem.add_dependency("nokogiri")
20
+ gem.add_development_dependency("rack-test")
21
+ end
@@ -0,0 +1,3 @@
1
+ body {
2
+ color: black;
3
+ }
@@ -0,0 +1 @@
1
+ alert("test");
@@ -0,0 +1,61 @@
1
+ require_relative "test_helper"
2
+
3
+ class MiddlewareTest < MiniTest::Unit::TestCase
4
+ include Rack::Test::Methods
5
+
6
+ # Read first so we don't exhaust DATA
7
+ # after a single test
8
+ TEST_HTML = DATA.read.freeze
9
+
10
+ def app
11
+ Rack::Builder.new do
12
+ use StaticSignature::Middleware, :static_dir => File.join(File.dirname(__FILE__), "data")
13
+ run lambda { |env| [200, {'Content-Type' => "text/html"}, [TEST_HTML]]}
14
+ end
15
+ end
16
+
17
+ def response_doc
18
+ Nokogiri::HTML(last_response.body)
19
+ end
20
+
21
+ def test_link_tag_busting
22
+ get "/"
23
+ node = response_doc.search("link").first
24
+ assert_equal "/css/app.css?b7a03f662ff6716c8a95cad9299de15e", node["href"]
25
+ end
26
+
27
+ def test_script_tag_busting
28
+ get "/"
29
+ node = response_doc.search("script").first
30
+ assert_equal "/js/app.js?0677e7d10a89eb91d1292cbe35036a15", node["src"]
31
+ end
32
+
33
+ def test_skip_protocol_busting
34
+ get "/"
35
+ assert_match /asset\.js\Z/, response_doc.search("script")[1]["src"]
36
+ assert_match /vendor\.js\Z/, response_doc.search("script")[2]["src"]
37
+ end
38
+
39
+ def test_end_tags_intact
40
+ get "/"
41
+ assert_match %r{</body>}, last_response.body
42
+ assert_match %r{</html>}, last_response.body
43
+ end
44
+ end
45
+
46
+ __END__
47
+
48
+ <!DOCTYPE html>
49
+ <html>
50
+ <head>
51
+ <title>Test HTML</title>
52
+ <link href="/css/app.css" rel="stylesheet" media="screen">
53
+ </head
54
+ <body>
55
+ <h1>Hello, world!</h1>
56
+ <script src="/js/app.js"></script>
57
+ <script src="http://www.example.com/js/asset.js"></script>
58
+ <script src="//www.example.com/js/vendor.js"></script>
59
+ </body>
60
+ </html>
61
+
@@ -0,0 +1,6 @@
1
+ require "minitest/unit"
2
+ require "minitest/autorun"
3
+ require "rack/test"
4
+ require "nokogiri"
5
+
6
+ require_relative "../lib/static_signature"
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: static_signature
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Brendon Murphy
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: &2151894720 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2151894720
25
+ - !ruby/object:Gem::Dependency
26
+ name: rack-test
27
+ requirement: &2151894160 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2151894160
36
+ description: ! 'Rack Middleware for adding query string cache busting signatures on
37
+
38
+ script and style assets'
39
+ email:
40
+ - xternal1+github@gmail.com
41
+ executables: []
42
+ extensions: []
43
+ extra_rdoc_files: []
44
+ files:
45
+ - .gitignore
46
+ - Gemfile
47
+ - LICENSE
48
+ - README.md
49
+ - Rakefile
50
+ - lib/static_signature.rb
51
+ - lib/static_signature/version.rb
52
+ - static_signature.gemspec
53
+ - test/data/css/app.css
54
+ - test/data/js/app.js
55
+ - test/middleware_test.rb
56
+ - test/test_helper.rb
57
+ homepage: ''
58
+ licenses: []
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 1.8.15
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: Rack Middleware for adding query string cache busting signatures on script
81
+ and style assets
82
+ test_files:
83
+ - test/data/css/app.css
84
+ - test/data/js/app.js
85
+ - test/middleware_test.rb
86
+ - test/test_helper.rb