rack-contrib 2.0.0 → 2.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.
Potentially problematic release.
This version of rack-contrib might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/README.md +6 -9
- data/lib/rack/contrib.rb +1 -0
- data/lib/rack/contrib/csshttprequest.rb +1 -1
- data/lib/rack/contrib/json_body_parser.rb +83 -0
- data/lib/rack/contrib/jsonp.rb +1 -1
- data/lib/rack/contrib/locale.rb +62 -30
- data/lib/rack/contrib/mailexceptions.rb +1 -1
- data/lib/rack/contrib/not_found.rb +1 -1
- data/lib/rack/contrib/post_body_content_type_parser.rb +47 -4
- data/lib/rack/contrib/profiler.rb +4 -1
- data/lib/rack/contrib/response_cache.rb +16 -6
- data/lib/rack/contrib/static_cache.rb +7 -5
- metadata +29 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ca58db2b7968ad4691e8bec79eea2088dabc3da5d309358f7df76d668324d824
|
4
|
+
data.tar.gz: 51816bb6b59a598fea16eb100cc783b3c0ff58eb37aa3585bb8d65141f2aae4f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7442b5ad170ae2946f017d8ccd007d02455b7939fe42239378505b61983cd9a1f090549e87b07e08323a7cf99d04f026e8df0f326e34be166508187cca3735e7
|
7
|
+
data.tar.gz: 99985100672c65c9ee559a37281f5dddea4fcdc8481ddffd75c2f6e697197a1070339c5b70733d736f8ba33078d5f699f00097cd6ec96266c8f07edb008b727b
|
data/README.md
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
This package includes a variety of add-on components for Rack, a Ruby web server
|
4
4
|
interface:
|
5
5
|
|
6
|
-
* `Rack::AcceptFormat` - Adds a format extension at the end of the URI when there is none, corresponding to the mime-type given in the Accept HTTP header.
|
7
6
|
* `Rack::Access` - Limits access based on IP address
|
8
7
|
* `Rack::Backstage` - Returns content of specified file if it exists, which makes it convenient for putting up maintenance pages.
|
9
8
|
* `Rack::BounceFavicon` - Returns a 404 for requests to `/favicon.ico`
|
@@ -14,6 +13,7 @@ interface:
|
|
14
13
|
* `Rack::Deflect` - Helps protect against DoS attacks.
|
15
14
|
* `Rack::Evil` - Lets the rack application return a response to the client from any place.
|
16
15
|
* `Rack::HostMeta` - Configures `/host-meta` using a block
|
16
|
+
* `Rack::JSONBodyParser` - Adds JSON request bodies to the Rack parameters hash.
|
17
17
|
* `Rack::JSONP` - Adds JSON-P support by stripping out the callback param and padding the response with the appropriate callback format.
|
18
18
|
* `Rack::LazyConditionalGet` - Caches a global `Last-Modified` date and updates it each time there is a request that is not `GET` or `HEAD`.
|
19
19
|
* `Rack::LighttpdScriptNameFix` - Fixes how lighttpd sets the `SCRIPT_NAME` and `PATH_INFO` variables in certain configurations.
|
@@ -21,14 +21,13 @@ interface:
|
|
21
21
|
* `Rack::MailExceptions` - Rescues exceptions raised from the app and sends a useful email with the exception, stacktrace, and contents of the environment.
|
22
22
|
* `Rack::NestedParams` - parses form params with subscripts (e.g., * "`post[title]=Hello`") into a nested/recursive Hash structure (based on Rails' implementation).
|
23
23
|
* `Rack::NotFound` - A default 404 application.
|
24
|
-
* `Rack::PostBodyContentTypeParser` - Adds support for JSON request bodies. The Rack parameter hash is populated by deserializing the JSON data provided in the request body when the Content-Type is application/json
|
24
|
+
* `Rack::PostBodyContentTypeParser` - [Deprecated]: Adds support for JSON request bodies. The Rack parameter hash is populated by deserializing the JSON data provided in the request body when the Content-Type is application/json
|
25
25
|
* `Rack::Printout` - Prints the environment and the response per request
|
26
26
|
* `Rack::ProcTitle` - Displays request information in process title (`$0`) for monitoring/inspection with ps(1).
|
27
27
|
* `Rack::Profiler` - Uses ruby-prof to measure request time.
|
28
28
|
* `Rack::RelativeRedirect` - Transforms relative paths in redirects to absolute URLs.
|
29
|
-
* `Rack::ResponseCache` - Caches responses to requests without query strings to Disk or a user
|
29
|
+
* `Rack::ResponseCache` - Caches responses to requests without query strings to Disk or a user provided Ruby object. Similar to Rails' page caching.
|
30
30
|
* `Rack::ResponseHeaders` - Manipulates response headers object at runtime
|
31
|
-
* `Rack::Sendfile` - Enables `X-Sendfile` support for bodies that can be served from file.
|
32
31
|
* `Rack::Signals` - Installs signal handlers that are safely processed after a request
|
33
32
|
* `Rack::SimpleEndpoint` - Creates simple endpoints with routing rules, similar to Sinatra actions
|
34
33
|
* `Rack::StaticCache` - Modifies the response headers to facilitiate client and proxy caching for static files that minimizes http requests and improves overall load times for second time visitors.
|
@@ -104,8 +103,6 @@ guidelines in CONTRIBUTING.md.
|
|
104
103
|
|
105
104
|
### Links
|
106
105
|
|
107
|
-
* rack-contrib on GitHub:: <
|
108
|
-
* Rack:: <
|
109
|
-
* Rack On GitHub:: <
|
110
|
-
* rack-devel mailing list:: <http://groups.google.com/group/rack-devel>
|
111
|
-
* [](https://gitter.im/rack/rack-contrib?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
106
|
+
* rack-contrib on GitHub:: <https://github.com/rack/rack-contrib>
|
107
|
+
* Rack:: <https://rack.github.io/>
|
108
|
+
* Rack On GitHub:: <https://github.com/rack/rack>
|
data/lib/rack/contrib.rb
CHANGED
@@ -24,6 +24,7 @@ module Rack
|
|
24
24
|
autoload :HostMeta, "rack/contrib/host_meta"
|
25
25
|
autoload :GarbageCollector, "rack/contrib/garbagecollector"
|
26
26
|
autoload :JSONP, "rack/contrib/jsonp"
|
27
|
+
autoload :JSONBodyParser, "rack/contrib/json_body_parser"
|
27
28
|
autoload :LazyConditionalGet, "rack/contrib/lazy_conditional_get"
|
28
29
|
autoload :LighttpdScriptNameFix, "rack/contrib/lighttpd_script_name_fix"
|
29
30
|
autoload :Locale, "rack/contrib/locale"
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Rack
|
6
|
+
# A Rack middleware that makes JSON-encoded request bodies available in the
|
7
|
+
# request.params hash. By default it parses POST, PATCH, and PUT requests
|
8
|
+
# whose media type is <tt>application/json</tt>. You can configure it to match
|
9
|
+
# any verb or media type via the <tt>:verbs</tt> and <tt>:media</tt> options.
|
10
|
+
#
|
11
|
+
#
|
12
|
+
# == Examples:
|
13
|
+
#
|
14
|
+
# === Parse POST and GET requests only
|
15
|
+
# use Rack::JSONBodyParser, verbs: ['POST', 'GET']
|
16
|
+
#
|
17
|
+
# === Parse POST|PATCH|PUT requests whose Content-Type matches 'json'
|
18
|
+
# use Rack::JSONBodyParser, media: /json/
|
19
|
+
#
|
20
|
+
# === Parse POST requests whose Content-Type is 'application/json' or 'application/vnd+json'
|
21
|
+
# use Rack::JSONBodyParser, verbs: ['POST'], media: ['application/json', 'application/vnd.api+json']
|
22
|
+
#
|
23
|
+
class JSONBodyParser
|
24
|
+
CONTENT_TYPE_MATCHERS = {
|
25
|
+
String => lambda { |option, header|
|
26
|
+
Rack::MediaType.type(header) == option
|
27
|
+
},
|
28
|
+
Array => lambda { |options, header|
|
29
|
+
media_type = Rack::MediaType.type(header)
|
30
|
+
options.any? { |opt| media_type == opt }
|
31
|
+
},
|
32
|
+
Regexp => lambda {
|
33
|
+
if //.respond_to?(:match?)
|
34
|
+
# Use Ruby's fast regex matcher when available
|
35
|
+
->(option, header) { option.match? header }
|
36
|
+
else
|
37
|
+
# Fall back to the slower matcher for rubies older than 2.4
|
38
|
+
->(option, header) { option.match header }
|
39
|
+
end
|
40
|
+
}.call(),
|
41
|
+
}.freeze
|
42
|
+
|
43
|
+
DEFAULT_PARSER = ->(body) { JSON.parse(body, create_additions: false) }
|
44
|
+
|
45
|
+
def initialize(
|
46
|
+
app,
|
47
|
+
verbs: %w[POST PATCH PUT],
|
48
|
+
media: 'application/json',
|
49
|
+
&block
|
50
|
+
)
|
51
|
+
@app = app
|
52
|
+
@verbs, @media = verbs, media
|
53
|
+
@matcher = CONTENT_TYPE_MATCHERS.fetch(@media.class)
|
54
|
+
@parser = block || DEFAULT_PARSER
|
55
|
+
end
|
56
|
+
|
57
|
+
def call(env)
|
58
|
+
if @verbs.include?(env[Rack::REQUEST_METHOD]) &&
|
59
|
+
@matcher.call(@media, env['CONTENT_TYPE'])
|
60
|
+
|
61
|
+
update_form_hash_with_json_body(env)
|
62
|
+
end
|
63
|
+
@app.call(env)
|
64
|
+
rescue JSON::ParserError
|
65
|
+
body = { error: 'Failed to parse body as JSON' }.to_json
|
66
|
+
header = { 'Content-Type' => 'application/json' }
|
67
|
+
Rack::Response.new(body, 400, header).finish
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def update_form_hash_with_json_body(env)
|
73
|
+
body = env[Rack::RACK_INPUT]
|
74
|
+
return unless (body_content = body.read) && !body_content.empty?
|
75
|
+
|
76
|
+
body.rewind # somebody might try to read this stream
|
77
|
+
env.update(
|
78
|
+
Rack::RACK_REQUEST_FORM_HASH => @parser.call(body_content),
|
79
|
+
Rack::RACK_REQUEST_FORM_INPUT => body
|
80
|
+
)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/rack/contrib/jsonp.rb
CHANGED
@@ -106,7 +106,7 @@ module Rack
|
|
106
106
|
end
|
107
107
|
|
108
108
|
def bad_request(body = "Bad Request")
|
109
|
-
[ 400, { 'Content-Type' => 'text/plain', 'Content-Length' => body.
|
109
|
+
[ 400, { 'Content-Type' => 'text/plain', 'Content-Length' => body.bytesize.to_s }, [body] ]
|
110
110
|
end
|
111
111
|
|
112
112
|
end
|
data/lib/rack/contrib/locale.rb
CHANGED
@@ -7,43 +7,75 @@ module Rack
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def call(env)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
locale_to_restore = I18n.locale
|
11
|
+
|
12
|
+
locale = user_preferred_locale(env["HTTP_ACCEPT_LANGUAGE"])
|
13
|
+
locale ||= I18n.default_locale
|
14
|
+
|
15
|
+
env['rack.locale'] = I18n.locale = locale.to_s
|
16
|
+
status, headers, body = @app.call(env)
|
17
|
+
|
18
|
+
unless headers['Content-Language']
|
19
|
+
headers['Content-Language'] = locale.to_s
|
20
20
|
end
|
21
|
+
|
22
|
+
[status, headers, body]
|
23
|
+
ensure
|
24
|
+
I18n.locale = locale_to_restore
|
21
25
|
end
|
22
26
|
|
23
27
|
private
|
24
28
|
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
29
|
+
# Accept-Language header is covered mainly by RFC 7231
|
30
|
+
# https://tools.ietf.org/html/rfc7231
|
31
|
+
#
|
32
|
+
# Related sections:
|
33
|
+
#
|
34
|
+
# * https://tools.ietf.org/html/rfc7231#section-5.3.1
|
35
|
+
# * https://tools.ietf.org/html/rfc7231#section-5.3.5
|
36
|
+
# * https://tools.ietf.org/html/rfc4647#section-3.4
|
37
|
+
#
|
38
|
+
# There is an obsolete RFC 2616 (https://tools.ietf.org/html/rfc2616)
|
39
|
+
#
|
40
|
+
# Edge cases:
|
41
|
+
#
|
42
|
+
# * Value can be a comma separated list with optional whitespaces:
|
43
|
+
# Accept-Language: da, en-gb;q=0.8, en;q=0.7
|
44
|
+
#
|
45
|
+
# * Quality value can contain optional whitespaces as well:
|
46
|
+
# Accept-Language: ru-UA, ru; q=0.8, uk; q=0.6, en-US; q=0.4, en; q=0.2
|
47
|
+
#
|
48
|
+
# * Quality prefix 'q=' can be in upper case (Q=)
|
49
|
+
#
|
50
|
+
# * Ignore case when match locale with I18n available locales
|
51
|
+
#
|
52
|
+
def user_preferred_locale(header)
|
53
|
+
return if header.nil?
|
54
|
+
|
55
|
+
locales = header.gsub(/\s+/, '').split(",").map do |language_tag|
|
56
|
+
locale, quality = language_tag.split(/;q=/i)
|
57
|
+
quality = quality ? quality.to_f : 1.0
|
58
|
+
[locale, quality]
|
59
|
+
end.reject do |(locale, quality)|
|
60
|
+
locale == '*' || quality == 0
|
61
|
+
end.sort_by do |(_, quality)|
|
62
|
+
quality
|
63
|
+
end.map(&:first)
|
64
|
+
|
65
|
+
return if locales.empty?
|
66
|
+
|
67
|
+
if I18n.enforce_available_locales
|
68
|
+
locale = locales.reverse.find { |locale| I18n.available_locales.any? { |al| match?(al, locale) } }
|
69
|
+
if locale
|
70
|
+
I18n.available_locales.find { |al| match?(al, locale) }
|
42
71
|
end
|
43
|
-
|
72
|
+
else
|
73
|
+
locales.last
|
74
|
+
end
|
75
|
+
end
|
44
76
|
|
45
|
-
|
46
|
-
|
77
|
+
def match?(s1, s2)
|
78
|
+
s1.to_s.casecmp(s2.to_s) == 0
|
47
79
|
end
|
48
80
|
end
|
49
81
|
end
|
@@ -90,7 +90,7 @@ module Rack
|
|
90
90
|
mail.delivery_method :test
|
91
91
|
elsif config[:smtp]
|
92
92
|
smtp = config[:smtp]
|
93
|
-
# for backward
|
93
|
+
# for backward compatibility, replace the :server key with :address
|
94
94
|
address = smtp.delete :server
|
95
95
|
smtp[:address] = address if address
|
96
96
|
mail.delivery_method :smtp, smtp
|
@@ -6,10 +6,51 @@ end
|
|
6
6
|
|
7
7
|
module Rack
|
8
8
|
|
9
|
+
# <b>DEPRECATED:</b> <tt>JSONBodyParser</tt> is a drop-in replacement that is faster and more configurable.
|
10
|
+
#
|
9
11
|
# A Rack middleware for parsing POST/PUT body data when Content-Type is
|
10
12
|
# not one of the standard supported types, like <tt>application/json</tt>.
|
11
13
|
#
|
12
|
-
#
|
14
|
+
# === How to use the middleware
|
15
|
+
#
|
16
|
+
# Example of simple +config.ru+ file:
|
17
|
+
#
|
18
|
+
# require 'rack'
|
19
|
+
# require 'rack/contrib'
|
20
|
+
#
|
21
|
+
# use ::Rack::PostBodyContentTypeParser
|
22
|
+
#
|
23
|
+
# app = lambda do |env|
|
24
|
+
# request = Rack::Request.new(env)
|
25
|
+
# body = "Hello #{request.params['name']}"
|
26
|
+
# [200, {'Content-Type' => 'text/plain'}, [body]]
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# run app
|
30
|
+
#
|
31
|
+
# Example with passing block argument:
|
32
|
+
#
|
33
|
+
# use ::Rack::PostBodyContentTypeParser do |body|
|
34
|
+
# { 'params' => JSON.parse(body) }
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# Example with passing proc argument:
|
38
|
+
#
|
39
|
+
# parser = ->(body) { { 'params' => JSON.parse(body) } }
|
40
|
+
# use ::Rack::PostBodyContentTypeParser, &parser
|
41
|
+
#
|
42
|
+
#
|
43
|
+
# === Failed JSON parsing
|
44
|
+
#
|
45
|
+
# Returns "400 Bad request" response if invalid JSON document was sent:
|
46
|
+
#
|
47
|
+
# Raw HTTP response:
|
48
|
+
#
|
49
|
+
# HTTP/1.1 400 Bad Request
|
50
|
+
# Content-Type: text/plain
|
51
|
+
# Content-Length: 28
|
52
|
+
#
|
53
|
+
# failed to parse body as JSON
|
13
54
|
#
|
14
55
|
class PostBodyContentTypeParser
|
15
56
|
|
@@ -24,14 +65,16 @@ module Rack
|
|
24
65
|
#
|
25
66
|
APPLICATION_JSON = 'application/json'.freeze
|
26
67
|
|
27
|
-
def initialize(app)
|
68
|
+
def initialize(app, &block)
|
69
|
+
warn "[DEPRECATION] `PostBodyContentTypeParser` is deprecated. Use `JSONBodyParser` as a drop-in replacement."
|
28
70
|
@app = app
|
71
|
+
@block = block || Proc.new { |body| JSON.parse(body, :create_additions => false) }
|
29
72
|
end
|
30
73
|
|
31
74
|
def call(env)
|
32
75
|
if Rack::Request.new(env).media_type == APPLICATION_JSON && (body = env[POST_BODY].read).length != 0
|
33
76
|
env[POST_BODY].rewind # somebody might try to read this stream
|
34
|
-
env.update(FORM_HASH =>
|
77
|
+
env.update(FORM_HASH => @block.call(body), FORM_INPUT => env[POST_BODY])
|
35
78
|
end
|
36
79
|
@app.call(env)
|
37
80
|
rescue JSON::ParserError
|
@@ -39,7 +82,7 @@ module Rack
|
|
39
82
|
end
|
40
83
|
|
41
84
|
def bad_request(body = 'Bad Request')
|
42
|
-
[ 400, { 'Content-Type' => 'text/plain', 'Content-Length' => body.
|
85
|
+
[ 400, { 'Content-Type' => 'text/plain', 'Content-Length' => body.bytesize.to_s }, [body] ]
|
43
86
|
end
|
44
87
|
end
|
45
88
|
end
|
@@ -4,7 +4,10 @@ module Rack
|
|
4
4
|
# Set the profile=process_time query parameter to download a
|
5
5
|
# calltree profile of the request.
|
6
6
|
#
|
7
|
-
# Pass the :printer option to pick a different result format.
|
7
|
+
# Pass the :printer option to pick a different result format. Note that
|
8
|
+
# some printers (such as CallTreePrinter) have broken the
|
9
|
+
# `AbstractPrinter` API, and thus will not work. Bug reports to
|
10
|
+
# `ruby-prof`, please, not us.
|
8
11
|
#
|
9
12
|
# You can cause every request to be run multiple times by passing the
|
10
13
|
# `:times` option to the `use Rack::Profiler` call. You can also run a
|
@@ -3,9 +3,12 @@ require 'rack'
|
|
3
3
|
|
4
4
|
# Rack::ResponseCache is a Rack middleware that caches responses for successful
|
5
5
|
# GET requests with no query string to disk or any ruby object that has an
|
6
|
-
# []= method (so it works with memcached).
|
7
|
-
#
|
8
|
-
# be served
|
6
|
+
# []= method (so it works with memcached). As with Rails' page caching, this
|
7
|
+
# middleware only writes to the cache -- it never reads. The logic of whether a
|
8
|
+
# cached response should be served is left either to your web server, via
|
9
|
+
# something like the <tt>try_files</tt> directive in nginx, or to your
|
10
|
+
# cache-reading middleware of choice, mounted before Rack::ResponseCache in the
|
11
|
+
# stack.
|
9
12
|
class Rack::ResponseCache
|
10
13
|
# The default proc used if a block is not provided to .new
|
11
14
|
# It unescapes the PATH_INFO of the environment, and makes sure that it doesn't
|
@@ -15,7 +18,14 @@ class Rack::ResponseCache
|
|
15
18
|
# of the path to index.html.
|
16
19
|
DEFAULT_PATH_PROC = proc do |env, res|
|
17
20
|
path = Rack::Utils.unescape(env['PATH_INFO'])
|
18
|
-
|
21
|
+
headers = res[1]
|
22
|
+
# Content-Type is almost always at headers['Content-Type'], but to fully
|
23
|
+
# comply with HTTP RFC 7230, we fall back to a case-insensitive lookup
|
24
|
+
content_type = headers.fetch('Content-Type') do |titlecase_key|
|
25
|
+
_, val = headers.find { |key, _| key.casecmp(titlecase_key) == 0 }
|
26
|
+
val
|
27
|
+
end
|
28
|
+
if !path.include?('..') and match = /text\/((?:x|ht)ml|css)/o.match(content_type)
|
19
29
|
type = match[1]
|
20
30
|
path = "#{path}.#{type}" unless /\.#{type}\z/.match(path)
|
21
31
|
path = File.join(File.dirname(path), 'index.html') if type == 'html' and File.basename(path) == '.html'
|
@@ -23,7 +33,7 @@ class Rack::ResponseCache
|
|
23
33
|
end
|
24
34
|
end
|
25
35
|
|
26
|
-
# Initialize a new
|
36
|
+
# Initialize a new ResponseCache object with the given arguments. Arguments:
|
27
37
|
# * app : The next middleware in the chain. This is always called.
|
28
38
|
# * cache : The place to cache responses. If a string is provided, a disk
|
29
39
|
# cache is used, and all cached files will use this directory as the root directory.
|
@@ -42,7 +52,7 @@ class Rack::ResponseCache
|
|
42
52
|
# Call the next middleware with the environment. If the request was successful (response status 200),
|
43
53
|
# was a GET request, and had an empty query string, call the block set up in initialize to get the path.
|
44
54
|
# If the cache is a string, create any necessary middle directories, and cache the file in the appropriate
|
45
|
-
# subdirectory of cache. Otherwise, cache the body of the
|
55
|
+
# subdirectory of cache. Otherwise, cache the body of the response as the value with the path as the key.
|
46
56
|
def call(env)
|
47
57
|
res = @app.call(env)
|
48
58
|
if env['REQUEST_METHOD'] == 'GET' and env['QUERY_STRING'] == '' and res[0] == 200 and path = @path_proc.call(env, res)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
1
3
|
module Rack
|
2
4
|
|
3
5
|
#
|
@@ -16,7 +18,7 @@ module Rack
|
|
16
18
|
#
|
17
19
|
# Another way to bypass the cache is adding the version number in a field-value pair in the
|
18
20
|
# URL query string. As an example, http://yoursite.com/images/test.png?v=1.0.0
|
19
|
-
# In that case, set the option :versioning to false to avoid
|
21
|
+
# In that case, set the option :versioning to false to avoid unnecessary regexp calculations.
|
20
22
|
#
|
21
23
|
# It's better to keep the current version number in some config file and use it in every static
|
22
24
|
# content's URL. So each time we modify our static contents, we just have to change the version
|
@@ -40,7 +42,7 @@ module Rack
|
|
40
42
|
# default headers.
|
41
43
|
#
|
42
44
|
# use Rack::StaticCache, :urls => ["/images"], :duration => 2, :versioning => false
|
43
|
-
# will serve all requests
|
45
|
+
# will serve all requests beginning with /images under the current directory (default for the option :root
|
44
46
|
# is current directory). All the contents served will have cache expiration duration set to 2 years in headers
|
45
47
|
# (default for :duration is 1 year), and StaticCache will not compute any versioning logics (default for
|
46
48
|
# :versioning is true)
|
@@ -68,7 +70,6 @@ module Rack
|
|
68
70
|
@version_regex = options.fetch(:version_regex, /-[\d.]+([.][a-zA-Z][\w]+)?$/)
|
69
71
|
end
|
70
72
|
@duration_in_seconds = self.duration_in_seconds
|
71
|
-
@duration_in_words = self.duration_in_words
|
72
73
|
end
|
73
74
|
|
74
75
|
def call(env)
|
@@ -83,14 +84,15 @@ module Rack
|
|
83
84
|
status, headers, body = @file_server.call(env)
|
84
85
|
if @no_cache[url].nil?
|
85
86
|
headers['Cache-Control'] ="max-age=#{@duration_in_seconds}, public"
|
86
|
-
headers['Expires'] =
|
87
|
+
headers['Expires'] = duration_in_words
|
87
88
|
end
|
89
|
+
headers['Date'] = Time.now.httpdate
|
88
90
|
[status, headers, body]
|
89
91
|
end
|
90
92
|
end
|
91
93
|
|
92
94
|
def duration_in_words
|
93
|
-
(Time.now + self.duration_in_seconds).
|
95
|
+
(Time.now.utc + self.duration_in_seconds).httpdate
|
94
96
|
end
|
95
97
|
|
96
98
|
def duration_in_seconds
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-contrib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- rack-devel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-03-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -28,16 +28,22 @@ dependencies:
|
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.0'
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '3'
|
34
37
|
type: :development
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
|
-
- - "
|
41
|
+
- - ">="
|
39
42
|
- !ruby/object:Gem::Version
|
40
43
|
version: '1.0'
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '3'
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: git-version-bump
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -216,14 +222,28 @@ dependencies:
|
|
216
222
|
requirements:
|
217
223
|
- - "~>"
|
218
224
|
- !ruby/object:Gem::Version
|
219
|
-
version: 0.
|
225
|
+
version: '0.17'
|
226
|
+
type: :development
|
227
|
+
prerelease: false
|
228
|
+
version_requirements: !ruby/object:Gem::Requirement
|
229
|
+
requirements:
|
230
|
+
- - "~>"
|
231
|
+
- !ruby/object:Gem::Version
|
232
|
+
version: '0.17'
|
233
|
+
- !ruby/object:Gem::Dependency
|
234
|
+
name: timecop
|
235
|
+
requirement: !ruby/object:Gem::Requirement
|
236
|
+
requirements:
|
237
|
+
- - "~>"
|
238
|
+
- !ruby/object:Gem::Version
|
239
|
+
version: '0.9'
|
220
240
|
type: :development
|
221
241
|
prerelease: false
|
222
242
|
version_requirements: !ruby/object:Gem::Requirement
|
223
243
|
requirements:
|
224
244
|
- - "~>"
|
225
245
|
- !ruby/object:Gem::Version
|
226
|
-
version: 0.
|
246
|
+
version: '0.9'
|
227
247
|
description: Contributed Rack Middleware and Utilities
|
228
248
|
email: rack-devel@googlegroups.com
|
229
249
|
executables: []
|
@@ -250,6 +270,7 @@ files:
|
|
250
270
|
- lib/rack/contrib/expectation_cascade.rb
|
251
271
|
- lib/rack/contrib/garbagecollector.rb
|
252
272
|
- lib/rack/contrib/host_meta.rb
|
273
|
+
- lib/rack/contrib/json_body_parser.rb
|
253
274
|
- lib/rack/contrib/jsonp.rb
|
254
275
|
- lib/rack/contrib/lazy_conditional_get.rb
|
255
276
|
- lib/rack/contrib/lighttpd_script_name_fix.rb
|
@@ -271,7 +292,7 @@ files:
|
|
271
292
|
- lib/rack/contrib/static_cache.rb
|
272
293
|
- lib/rack/contrib/time_zone.rb
|
273
294
|
- lib/rack/contrib/try_static.rb
|
274
|
-
homepage:
|
295
|
+
homepage: https://github.com/rack/rack-contrib/
|
275
296
|
licenses:
|
276
297
|
- MIT
|
277
298
|
metadata: {}
|
@@ -296,8 +317,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
296
317
|
- !ruby/object:Gem::Version
|
297
318
|
version: '0'
|
298
319
|
requirements: []
|
299
|
-
|
300
|
-
rubygems_version: 2.6.13
|
320
|
+
rubygems_version: 3.0.3
|
301
321
|
signing_key:
|
302
322
|
specification_version: 2
|
303
323
|
summary: Contributed Rack Middleware and Utilities
|