rack-etag 1.0.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 +7 -0
- data/lib/rack-etag.rb +3 -0
- data/lib/rack/etag.rb +70 -0
- data/lib/rack/etag/version.rb +5 -0
- data/spec/lib/rack/etag.rb +24 -0
- data/spec/lib/rack/etag/version_spec.rb +7 -0
- data/spec/spec_helper.rb +6 -0
- metadata +138 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4aa54891c355e2dea74d0459816d642d0995d4e7
|
4
|
+
data.tar.gz: e912c52ccbf508a8117b10a7412e9e80499b3317
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8779b919edb649f0a09fd9b2d47bb2bba5595ef3bbbee77365da3e9e7a7bfd5b574d394f9f1447a840a00b6af9ffbfb0bab3c332ed33c339f5b776fe8467e1e7
|
7
|
+
data.tar.gz: 567b4e0b94afea0900bb6857d04cfaa35a67765c06bbeb9ffdc7507cf78ed4d844cc787b22d7ea2f511e76e738849f6d216987e1a50e000c16f0f5728fa058aa
|
data/lib/rack-etag.rb
ADDED
data/lib/rack/etag.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
module Rack
|
2
|
+
# Automatically sets the ETag header on all String bodies.
|
3
|
+
#
|
4
|
+
# The ETag header is skipped if ETag or Last-Modified headers are sent or if
|
5
|
+
# a sendfile body (body.responds_to :to_path) is given (since such cases
|
6
|
+
# should be handled by apache/nginx).
|
7
|
+
#
|
8
|
+
# On initialization, you can pass two parameters: a Cache-Control directive
|
9
|
+
# used when Etag is absent and a directive when it is present. The first
|
10
|
+
# defaults to nil, while the second defaults to "max-age=0, private, must-revalidate"
|
11
|
+
module ETag
|
12
|
+
require_relative "etag/version"
|
13
|
+
DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate".freeze
|
14
|
+
|
15
|
+
def initialize(app, no_cache_control = nil, cache_control = DEFAULT_CACHE_CONTROL)
|
16
|
+
@app = app
|
17
|
+
@cache_control = cache_control
|
18
|
+
@no_cache_control = no_cache_control
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(env)
|
22
|
+
status, headers, body = @app.call(env)
|
23
|
+
|
24
|
+
if etag_status?(status) && etag_body?(body) && !skip_caching?(headers)
|
25
|
+
original_body = body
|
26
|
+
digest, new_body = digest_body(body)
|
27
|
+
body = Rack::BodyProxy.new(new_body) do
|
28
|
+
original_body.close if original_body.respond_to?(:close)
|
29
|
+
end
|
30
|
+
headers["ETag"] = %|W/"#{digest}"| if digest
|
31
|
+
end
|
32
|
+
|
33
|
+
unless headers["Cache-Control"]
|
34
|
+
if digest
|
35
|
+
headers["Cache-Control"] = @cache_control if @cache_control
|
36
|
+
else
|
37
|
+
headers["Cache-Control"] = @no_cache_control if @no_cache_control
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
[status, headers, body]
|
42
|
+
end
|
43
|
+
|
44
|
+
private def etag_status?(status)
|
45
|
+
status == 200 || status == 201
|
46
|
+
end
|
47
|
+
|
48
|
+
private def etag_body?(body)
|
49
|
+
!body.respond_to?(:to_path)
|
50
|
+
end
|
51
|
+
|
52
|
+
private def skip_caching?(headers)
|
53
|
+
(headers["Cache-Control"] && headers["Cache-Control"].include?("no-cache")) || headers.key?("ETag") || headers.key?("Last-Modified")
|
54
|
+
end
|
55
|
+
|
56
|
+
private def digest_body(body)
|
57
|
+
parts = []
|
58
|
+
digest = nil
|
59
|
+
|
60
|
+
body.each do |part|
|
61
|
+
parts << part
|
62
|
+
unless part.empty?
|
63
|
+
(digest ||= Digest::MD5.new) << part
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
[digest && digest.hexdigest, parts]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rack::ETag do
|
4
|
+
let(:application) { instance_double("Application") }
|
5
|
+
let(:middleware) { described_class.new(application) }
|
6
|
+
let(:verb) { "GET" }
|
7
|
+
let(:status) { 200 }
|
8
|
+
let(:headers) do
|
9
|
+
{
|
10
|
+
"REQUEST_METHOD" => verb,
|
11
|
+
"Content-Type" => "text/plain",
|
12
|
+
"Content-Length" => "0"
|
13
|
+
}
|
14
|
+
end
|
15
|
+
let(:body) { "" }
|
16
|
+
|
17
|
+
before(:each) do
|
18
|
+
allow(application).to receive(:call).and_return([status, headers, body])
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#call" do
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-etag
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kurtis Rainbolt-Greene
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.1'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.9'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.9'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry-doc
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.6'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.6'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: codeclimate-test-reporter
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.4'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.4'
|
97
|
+
description: Writes ETag to responses
|
98
|
+
email:
|
99
|
+
- me@kurtisrainboltgreene.name
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- lib/rack-etag.rb
|
105
|
+
- lib/rack/etag.rb
|
106
|
+
- lib/rack/etag/version.rb
|
107
|
+
- spec/lib/rack/etag.rb
|
108
|
+
- spec/lib/rack/etag/version_spec.rb
|
109
|
+
- spec/spec_helper.rb
|
110
|
+
homepage: http://krainboltgreene.github.io/rack-etag
|
111
|
+
licenses:
|
112
|
+
- MIT
|
113
|
+
metadata: {}
|
114
|
+
post_install_message:
|
115
|
+
rdoc_options: []
|
116
|
+
require_paths:
|
117
|
+
- lib
|
118
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
requirements: []
|
129
|
+
rubyforge_project:
|
130
|
+
rubygems_version: 2.2.2
|
131
|
+
signing_key:
|
132
|
+
specification_version: 4
|
133
|
+
summary: Writes ETag to responses
|
134
|
+
test_files:
|
135
|
+
- spec/lib/rack/etag/version_spec.rb
|
136
|
+
- spec/lib/rack/etag.rb
|
137
|
+
- spec/spec_helper.rb
|
138
|
+
has_rdoc:
|