rack3-brotli 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/brotli/deflater.rb +108 -0
- data/lib/rack/brotli/version.rb +7 -0
- data/lib/rack/brotli.rb +11 -0
- metadata +174 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ee389cffae09bf684808d32bb04f226a53d1d7b71eb617b1f1632c8405ec295a
|
4
|
+
data.tar.gz: 5726d77510b5f1cc5928ddcad90ef893f61a26c7e2d6b1a22da8bf3593bc6808
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9d3a7cd8ecfc15638b256b488e0216f786bdea3e290326a5f06f6b0ec52609013307b81352517075c79444134affe60c168c1c6f47996ff66edf4e7214fd75c4
|
7
|
+
data.tar.gz: bcdacd25233f4c5470d46db9181122b7cc26035ab3d8912552d8177457664f74e472e9fccaed6d4a83c1ff1499ac0cf1775a3b14d1f81e48559f0cc0ca9f86ec
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "brotli"
|
4
|
+
require "rack/deflater"
|
5
|
+
require "rack/utils"
|
6
|
+
|
7
|
+
module Rack
|
8
|
+
module Brotli
|
9
|
+
# This middleware enables content encoding of http responses,
|
10
|
+
# usually for purposes of compression.
|
11
|
+
#
|
12
|
+
# Currently supported encodings:
|
13
|
+
#
|
14
|
+
# * br
|
15
|
+
#
|
16
|
+
# This middleware automatically detects when encoding is supported
|
17
|
+
# and allowed. For example no encoding is made when a cache
|
18
|
+
# directive of 'no-transform' is present, when the response status
|
19
|
+
# code is one that doesn't allow an entity body, or when the body
|
20
|
+
# is empty.
|
21
|
+
#
|
22
|
+
class Deflater < ::Rack::Deflater
|
23
|
+
def initialize(app, options = {})
|
24
|
+
super
|
25
|
+
|
26
|
+
@deflater_options = { quality: 5 }.merge(options[:deflater] || {})
|
27
|
+
end
|
28
|
+
|
29
|
+
def call(env)
|
30
|
+
status, headers, body = response = @app.call(env)
|
31
|
+
|
32
|
+
return response unless should_deflate?(env, status, headers, body)
|
33
|
+
|
34
|
+
request = Request.new(env)
|
35
|
+
|
36
|
+
encoding = Utils.select_best_encoding(%w[br identity],
|
37
|
+
request.accept_encoding)
|
38
|
+
|
39
|
+
# Set the Vary HTTP header.
|
40
|
+
vary = headers["vary"].to_s.split(",").map(&:strip)
|
41
|
+
unless vary.include?("*") || vary.any? { |v| v.downcase == "accept-encoding" }
|
42
|
+
headers["vary"] = vary.push("Accept-Encoding").join(",")
|
43
|
+
end
|
44
|
+
|
45
|
+
case encoding
|
46
|
+
when "br"
|
47
|
+
headers["content-encoding"] = "br"
|
48
|
+
headers.delete(CONTENT_LENGTH)
|
49
|
+
response[2] = BrotliStream.new(body, @sync, @deflater_options)
|
50
|
+
response
|
51
|
+
when "identity"
|
52
|
+
response
|
53
|
+
else # when nil
|
54
|
+
# Only possible encoding values here are 'br', 'identity', and nil
|
55
|
+
message = "An acceptable encoding for the requested resource #{request.fullpath} could not be found."
|
56
|
+
bp = Rack::BodyProxy.new([message]) { body.close if body.respond_to?(:close) }
|
57
|
+
[406, { CONTENT_TYPE => "text/plain", CONTENT_LENGTH => message.length.to_s }, bp]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# :nodoc:
|
62
|
+
class BrotliStream
|
63
|
+
BUFFER_LENGTH = 128 * 1_024
|
64
|
+
|
65
|
+
def initialize(body, sync, options)
|
66
|
+
@body = body
|
67
|
+
@sync = sync
|
68
|
+
@options = options
|
69
|
+
end
|
70
|
+
|
71
|
+
# Yield gzip compressed strings to the given block.
|
72
|
+
def each(&block)
|
73
|
+
@writer = block
|
74
|
+
br = ::Brotli::Writer.new(self, @options)
|
75
|
+
# @body.each is equivalent to @body.gets (slow)
|
76
|
+
if @body.is_a?(::File) # XXX: Should probably be ::IO
|
77
|
+
while (file_part = @body.read(BUFFER_LENGTH))
|
78
|
+
br.write(file_part)
|
79
|
+
br.flush if @sync
|
80
|
+
end
|
81
|
+
else
|
82
|
+
@body.each do |part|
|
83
|
+
# Skip empty strings, as they would result in no output,
|
84
|
+
# and flushing empty parts would raise Zlib::BufError.
|
85
|
+
next if part.empty?
|
86
|
+
|
87
|
+
br.write(part)
|
88
|
+
br.flush if @sync
|
89
|
+
end
|
90
|
+
end
|
91
|
+
ensure
|
92
|
+
br.finish
|
93
|
+
end
|
94
|
+
|
95
|
+
# Call the block passed to #each with the deflated data.
|
96
|
+
def write(data)
|
97
|
+
@writer.call(data)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Close the original body if possible.
|
101
|
+
def close
|
102
|
+
@body.close if @body.respond_to?(:close)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
private_constant :BrotliStream
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/lib/rack/brotli.rb
ADDED
metadata
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack3-brotli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cody Cutrer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-02-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: brotli
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rack
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :runtime
|
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: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.4.22
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.4.22
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: gem-release
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.2'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.2'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '5.22'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '5.22'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '13.1'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '13.1'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop-inst
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop-minitest
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.34'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.34'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rubocop-rake
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.5'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.5'
|
139
|
+
description: Rack::Brotli enables Google's Brotli compression on HTTP responses
|
140
|
+
email:
|
141
|
+
- cody@instructure.com
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- lib/rack/brotli.rb
|
147
|
+
- lib/rack/brotli/deflater.rb
|
148
|
+
- lib/rack/brotli/version.rb
|
149
|
+
homepage: https://github.com/instructure/rack3-brotli
|
150
|
+
licenses:
|
151
|
+
- MIT
|
152
|
+
metadata:
|
153
|
+
rubygems_mfa_required: 'true'
|
154
|
+
source_code_uri: https://github.com/instructure/rack3-brotli
|
155
|
+
post_install_message:
|
156
|
+
rdoc_options: []
|
157
|
+
require_paths:
|
158
|
+
- lib
|
159
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '2.7'
|
164
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
requirements: []
|
170
|
+
rubygems_version: 3.4.19
|
171
|
+
signing_key:
|
172
|
+
specification_version: 4
|
173
|
+
summary: Brotli compression for Rack 3 responses
|
174
|
+
test_files: []
|