rack-steady_etag 0.2.0 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +12 -2
- data/lib/rack/steady_etag/version.rb +1 -1
- data/lib/rack/steady_etag.rb +27 -18
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3047cb500ace97518e12a5667bad5602d27b493f24d6a8a6c8236372fe7ca36
|
4
|
+
data.tar.gz: d9c3afe27e063227577e1921f6f4ce4e170f7f5627be0126096f1ed846ad7d1e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b86c5ec23d0d27170406530421acea4a54be83caf4c0513de01004136e92d2842aa771927f9ab8074bd918b83f3f10efc651b3e815dc8c5c2036769767c28077
|
7
|
+
data.tar.gz: b28cddf4577f20d1c0c75cdcf7c58d9ce5765f2148ab6fde4b9c0533725d09aa4c596b1624cab70c4e36a5b909e67153fd14ff95a272e9ef8fa0ee5ac81800c8
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -20,17 +20,27 @@ By default Rails uses [`Rack::ETag`](https://rdoc.info/github/rack/rack/Rack/ETa
|
|
20
20
|
You can add your own patterns:
|
21
21
|
|
22
22
|
```ruby
|
23
|
-
Rack::SteadyETag::
|
23
|
+
Rack::SteadyETag::STRIP_PATTERNS << /<meta name="XSRF-TOKEN" value="[^"]+">/
|
24
24
|
```
|
25
25
|
|
26
26
|
You can also push lambda for arbitrary transformations:
|
27
27
|
|
28
28
|
```ruby
|
29
|
-
Rack::SteadyETag::
|
29
|
+
Rack::SteadyETag::STRIP_PATTERNS << -> { |text| text.gsub(/<meta name="XSRF-TOKEN" value="[^"]+">/, '') }
|
30
30
|
```
|
31
31
|
|
32
32
|
Transformations are only applied for the `ETag` hash. The response body will not be changed.
|
33
33
|
|
34
|
+
## What responses are processed
|
35
|
+
|
36
|
+
This middleware will process responses that match all of the following:
|
37
|
+
|
38
|
+
- Responses with a HTTP status of 200 or 201
|
39
|
+
- Responses with a `Content-Type` of `text/html` or `application/xhtml+xml`
|
40
|
+
- Responses with a body.
|
41
|
+
|
42
|
+
This middleware can also add a default `Cache-Control` header for responses it *didn't* process. This is passed as an argument during middleware initialization (see *Installation* below).
|
43
|
+
|
34
44
|
## Covered edge cases
|
35
45
|
|
36
46
|
- Different `ETags` are generated when the same content is accessed with different Rack sessions.
|
data/lib/rack/steady_etag.rb
CHANGED
@@ -19,20 +19,25 @@ module Rack
|
|
19
19
|
# Yes, Rack::ETag sets a default Cache-Control for responses that it can digest.
|
20
20
|
DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate"
|
21
21
|
|
22
|
-
|
22
|
+
STRIP_PATTERNS = [
|
23
23
|
/<meta\b[^>]*\bname=(["'])csrf-token\1[^>]+>/i,
|
24
24
|
/<meta\b[^>]*\bname=(["'])csp-nonce\1[^>]+>/i,
|
25
25
|
/<input\b[^>]*\bname=(["'])authenticity_token\1[^>]+>/i,
|
26
26
|
lambda { |string| string.gsub(/(<script\b[^>]*)\bnonce=(["'])[^"']+\2+/i, '\1') }
|
27
27
|
]
|
28
28
|
|
29
|
+
STRIP_CONTENT_TYPES = %w[
|
30
|
+
text/html
|
31
|
+
application/xhtml+xml
|
32
|
+
]
|
33
|
+
|
29
34
|
def initialize(app, no_digest_cache_control = nil, digest_cache_control = DEFAULT_CACHE_CONTROL)
|
30
35
|
@app = app
|
31
36
|
|
32
37
|
@digest_cache_control = digest_cache_control
|
33
38
|
|
34
|
-
# Rails sets a default `Cache-Control: no-cache` for responses that
|
35
|
-
#
|
39
|
+
# Rails sets a default `Cache-Control: no-cache` for responses that we cannot digest.
|
40
|
+
# See https://github.com/rails/rails/blob/d96609505511a76c618dc3adfa3ca4679317d008/railties/lib/rails/application/default_middleware_stack.rb#L81
|
36
41
|
@no_digest_cache_control = no_digest_cache_control
|
37
42
|
end
|
38
43
|
|
@@ -94,20 +99,14 @@ module Rack
|
|
94
99
|
parts = []
|
95
100
|
digest = nil
|
96
101
|
|
102
|
+
strippable_response = STRIP_CONTENT_TYPES.include?(headers['Content-Type'])
|
103
|
+
|
97
104
|
body.each do |part|
|
98
105
|
parts << part
|
99
106
|
|
100
107
|
if part.present?
|
101
|
-
|
102
|
-
|
103
|
-
unless digest
|
104
|
-
digest = Digest::SHA256.new
|
105
|
-
|
106
|
-
if session && (session_id = session['session_id'])
|
107
|
-
digest << session_id.to_s
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
108
|
+
digest ||= initialize_digest(session)
|
109
|
+
part = strip_patterns(part) if strippable_response
|
111
110
|
digest << part
|
112
111
|
end
|
113
112
|
end
|
@@ -119,12 +118,22 @@ module Rack
|
|
119
118
|
[digest, parts]
|
120
119
|
end
|
121
120
|
|
122
|
-
def
|
123
|
-
|
124
|
-
|
125
|
-
|
121
|
+
def initialize_digest(session)
|
122
|
+
digest = Digest::SHA256.new
|
123
|
+
|
124
|
+
if session && (session_id = session['session_id'])
|
125
|
+
digest << session_id.to_s
|
126
|
+
end
|
127
|
+
|
128
|
+
digest
|
129
|
+
end
|
130
|
+
|
131
|
+
def strip_patterns(html)
|
132
|
+
STRIP_PATTERNS.each do |pattern|
|
133
|
+
if pattern.respond_to?(:call)
|
134
|
+
html = pattern.call(html)
|
126
135
|
else
|
127
|
-
html = html.gsub(
|
136
|
+
html = html.gsub(pattern, '')
|
128
137
|
end
|
129
138
|
end
|
130
139
|
html
|