rack-contrib 2.0.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
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
|
-
* [![Gitter](https://badges.gitter.im/Join Chat.svg)](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
|