webmachine 2.0.1 → 2.0.2
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 +8 -0
- data/examples/logging.rb +1 -1
- data/lib/webmachine/adapters/rack.rb +81 -10
- data/lib/webmachine/adapters/webrick.rb +1 -1
- data/lib/webmachine/etags.rb +1 -0
- data/lib/webmachine/headers.rb +1 -1
- data/lib/webmachine/media_type.rb +3 -5
- data/lib/webmachine/streaming/io_encoder.rb +1 -0
- data/lib/webmachine/trace/pstore_trace_store.rb +4 -5
- data/lib/webmachine/version.rb +1 -1
- metadata +20 -47
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 34385e0209af616a39bbd85807eb5a1989e7c4119757de7de598404aca768e7a
|
|
4
|
+
data.tar.gz: f850905e898bd592b2c5ef61a15e67c005a16ee9dadae1fc6dc09371dd043473
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: da0492a20458fea3a771532b6c144bd7e0b65bd517d9d951d7669f8772fb239fe9028717cf8778ed51de44cd600da7c14799db20035bf8f33673a15aa1618c55
|
|
7
|
+
data.tar.gz: 0febf4b1cc9425928352377bfc191bae02a27696e6c18cac1f0f1f5d865fefe0143fc9e92be3d1c36f17e54a4f4e1434b7b917f605bfb916607894aed524f5c9
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
### HEAD
|
|
2
2
|
|
|
3
|
+
### 2.0.2
|
|
4
|
+
|
|
5
|
+
* Support Rack version 3
|
|
6
|
+
* Support Ruby 3.4 and 4.0
|
|
7
|
+
* Apply RuboCop fixes
|
|
8
|
+
* Clean up gemspec configuration
|
|
9
|
+
* Organise development and test dependencies in the Gemfile
|
|
10
|
+
|
|
3
11
|
### 2.0.1 Feb 27, 2024
|
|
4
12
|
|
|
5
13
|
* Don't include the `doc/`, `pkg/`, or `vendor/` directory in the gem package
|
data/examples/logging.rb
CHANGED
|
@@ -34,7 +34,7 @@ App = Webmachine::Application.new do |app|
|
|
|
34
34
|
|
|
35
35
|
app.configure do |config|
|
|
36
36
|
config.adapter = :WEBrick
|
|
37
|
-
config.adapter_options = {AccessLog: [], Logger: Logger.new(
|
|
37
|
+
config.adapter_options = {AccessLog: [], Logger: Logger.new(File::NULL)}
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
@@ -41,7 +41,7 @@ module Webmachine
|
|
|
41
41
|
DEFAULT_OPTIONS = {}
|
|
42
42
|
|
|
43
43
|
REQUEST_URI = 'REQUEST_URI'.freeze
|
|
44
|
-
VERSION_STRING = "#{Webmachine::SERVER_STRING} Rack/#{::Rack.
|
|
44
|
+
VERSION_STRING = "#{Webmachine::SERVER_STRING} Rack/#{::Rack.release}".freeze
|
|
45
45
|
NEWLINE = "\n".freeze
|
|
46
46
|
|
|
47
47
|
# Start the Rack adapter
|
|
@@ -52,7 +52,12 @@ module Webmachine
|
|
|
52
52
|
Host: application.configuration.ip
|
|
53
53
|
}).merge(application.configuration.adapter_options)
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
if rack_v3?
|
|
56
|
+
require 'rackup'
|
|
57
|
+
@server = ::Rackup::Server.new(options)
|
|
58
|
+
else
|
|
59
|
+
@server = ::Rack::Server.new(options)
|
|
60
|
+
end
|
|
56
61
|
@server.start
|
|
57
62
|
end
|
|
58
63
|
|
|
@@ -70,7 +75,7 @@ module Webmachine
|
|
|
70
75
|
response.headers[SERVER] = VERSION_STRING
|
|
71
76
|
|
|
72
77
|
rack_status = response.code
|
|
73
|
-
rack_headers = response.headers
|
|
78
|
+
rack_headers = build_rack_response_headers(response.headers)
|
|
74
79
|
rack_body = case response.body
|
|
75
80
|
when String # Strings are enumerable in ruby 1.8
|
|
76
81
|
[response.body]
|
|
@@ -78,10 +83,25 @@ module Webmachine
|
|
|
78
83
|
if (io_body = IO.try_convert(response.body))
|
|
79
84
|
io_body
|
|
80
85
|
elsif response.body.respond_to?(:call)
|
|
81
|
-
|
|
86
|
+
if rack_v3?
|
|
87
|
+
# In Rack 3 the server (e.g. WEBrick via Rackup) buffers the body
|
|
88
|
+
# and applies chunked encoding itself when Transfer-Encoding is set,
|
|
89
|
+
# so we must not pre-encode with ChunkedBody.
|
|
90
|
+
[response.body.call]
|
|
91
|
+
else
|
|
92
|
+
# Rack 2's WEBrick handler sends the body as-is; ChunkedBody is
|
|
93
|
+
# required to produce valid chunked-encoded wire data.
|
|
94
|
+
Webmachine::ChunkedBody.new(Array(response.body.call))
|
|
95
|
+
end
|
|
82
96
|
elsif response.body.respond_to?(:each)
|
|
83
|
-
|
|
84
|
-
|
|
97
|
+
if rack_v3?
|
|
98
|
+
# Return the plain enumerable. Rackup buffers it into a String then
|
|
99
|
+
# WEBrick chunks that String when Transfer-Encoding: chunked is set.
|
|
100
|
+
response.body
|
|
101
|
+
elsif response.headers[TRANSFER_ENCODING] == 'chunked'
|
|
102
|
+
# Rack 2: only pre-encode bodies that are already marked chunked;
|
|
103
|
+
# IOEncoder bodies carry their own Content-Length and must not be
|
|
104
|
+
# wrapped.
|
|
85
105
|
Webmachine::ChunkedBody.new(response.body)
|
|
86
106
|
else
|
|
87
107
|
response.body
|
|
@@ -97,6 +117,45 @@ module Webmachine
|
|
|
97
117
|
|
|
98
118
|
protected
|
|
99
119
|
|
|
120
|
+
# Build a Rack-compatible response headers hash from Webmachine's response
|
|
121
|
+
# headers.
|
|
122
|
+
#
|
|
123
|
+
# Header names are always lowercased: this is required by Rack 3 and is
|
|
124
|
+
# harmless for Rack 2 (all Rack 2 handlers match header names
|
|
125
|
+
# case-insensitively).
|
|
126
|
+
#
|
|
127
|
+
# The +set-cookie+ value is formatted differently per Rack version:
|
|
128
|
+
#
|
|
129
|
+
# * Rack 3 / Rackup: the value must be an Array. Rackup's WEBrick handler
|
|
130
|
+
# deletes the lowercase +set-cookie+ key and calls
|
|
131
|
+
# +res.cookies.concat(Array(value))+, emitting one Set-Cookie line per
|
|
132
|
+
# cookie. Joining with +\n+ instead would produce a header value
|
|
133
|
+
# containing a newline, which WEBrick 1.9+ rejects as
|
|
134
|
+
# +WEBrick::HTTPResponse::InvalidHeader+.
|
|
135
|
+
#
|
|
136
|
+
# * Rack 2 / Rack::Handler::WEBrick: the handler splits on +\n+ before
|
|
137
|
+
# adding cookies (+vs.split("\n")+), so the value must be a newline-joined
|
|
138
|
+
# String. Passing an Array causes a +NoMethodError+ because +Array+ does
|
|
139
|
+
# not define +#split+.
|
|
140
|
+
def build_rack_response_headers(response_headers)
|
|
141
|
+
response_headers.each_with_object({}) do |(key, value), h|
|
|
142
|
+
rack_key = key.downcase
|
|
143
|
+
h[rack_key] = if rack_key == 'set-cookie'
|
|
144
|
+
if rack_v3?
|
|
145
|
+
# Array lets Rackup emit one Set-Cookie header per cookie.
|
|
146
|
+
Array(value)
|
|
147
|
+
else
|
|
148
|
+
# Rack 2's handler splits on \n; give it a newline-joined String.
|
|
149
|
+
Array(value).join(NEWLINE)
|
|
150
|
+
end
|
|
151
|
+
elsif value.is_a?(Array)
|
|
152
|
+
value.join(NEWLINE)
|
|
153
|
+
else
|
|
154
|
+
value
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
100
159
|
def routing_tokens(rack_req)
|
|
101
160
|
nil # no-op for default, un-mapped rack adapter
|
|
102
161
|
end
|
|
@@ -107,6 +166,11 @@ module Webmachine
|
|
|
107
166
|
|
|
108
167
|
private
|
|
109
168
|
|
|
169
|
+
# Returns true when running under Rack 3.x.
|
|
170
|
+
def rack_v3?
|
|
171
|
+
::Rack.release.start_with?('3.')
|
|
172
|
+
end
|
|
173
|
+
|
|
110
174
|
def build_webmachine_request(rack_req, headers)
|
|
111
175
|
RackRequest.new(rack_req.request_method,
|
|
112
176
|
rack_req.url,
|
|
@@ -128,6 +192,9 @@ module Webmachine
|
|
|
128
192
|
|
|
129
193
|
class RackResponse
|
|
130
194
|
ONE_FIVE = '1.5'.freeze
|
|
195
|
+
# Header names are normalised to lowercase by build_rack_response_headers,
|
|
196
|
+
# so use the lowercase form everywhere inside RackResponse too.
|
|
197
|
+
LOWERCASE_CONTENT_TYPE = 'content-type'.freeze
|
|
131
198
|
|
|
132
199
|
def initialize(body, status, headers)
|
|
133
200
|
@body = body
|
|
@@ -136,8 +203,8 @@ module Webmachine
|
|
|
136
203
|
end
|
|
137
204
|
|
|
138
205
|
def finish
|
|
139
|
-
@headers[
|
|
140
|
-
@headers.delete(
|
|
206
|
+
@headers[LOWERCASE_CONTENT_TYPE] ||= TEXT_HTML if rack_release_enforcing_content_type
|
|
207
|
+
@headers.delete(LOWERCASE_CONTENT_TYPE) if response_without_body
|
|
141
208
|
[@status, @headers, @body]
|
|
142
209
|
end
|
|
143
210
|
|
|
@@ -177,8 +244,12 @@ module Webmachine
|
|
|
177
244
|
if @value
|
|
178
245
|
@value.join
|
|
179
246
|
else
|
|
180
|
-
|
|
181
|
-
|
|
247
|
+
# Rack 3 removed the requirement for rack.input to implement #rewind
|
|
248
|
+
# (Rack::Lint::InputWrapper in Rack 3 does not define it), so guard
|
|
249
|
+
# the call to avoid a NoMethodError on every PUT/POST request.
|
|
250
|
+
body = @request.body
|
|
251
|
+
body.rewind if body.respond_to?(:rewind)
|
|
252
|
+
body.read
|
|
182
253
|
end
|
|
183
254
|
end
|
|
184
255
|
|
data/lib/webmachine/etags.rb
CHANGED
data/lib/webmachine/headers.rb
CHANGED
|
@@ -6,6 +6,7 @@ module Webmachine
|
|
|
6
6
|
# Encapsulates a MIME media type, with logic for matching types.
|
|
7
7
|
class MediaType
|
|
8
8
|
extend Translation
|
|
9
|
+
|
|
9
10
|
# Matches valid media types
|
|
10
11
|
MEDIA_TYPE_REGEX = /^\s*([^;\s]+)\s*((?:;\s*\S+\s*)*)\s*$/.freeze
|
|
11
12
|
|
|
@@ -112,11 +113,8 @@ module Webmachine
|
|
|
112
113
|
# ignoring params and taking into account wildcards
|
|
113
114
|
def type_matches?(other)
|
|
114
115
|
other = self.class.parse(other)
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
else
|
|
118
|
-
other.major == major && other.minor == Dispatcher::Route::MATCH_ALL_STR
|
|
119
|
-
end
|
|
116
|
+
[Dispatcher::Route::MATCH_ALL_STR, MATCHES_ALL, type].include?(other.type) ||
|
|
117
|
+
(other.major == major && other.minor == Dispatcher::Route::MATCH_ALL_STR)
|
|
120
118
|
end
|
|
121
119
|
end # class MediaType
|
|
122
120
|
end # module Webmachine
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
require 'pstore'
|
|
2
|
-
|
|
3
1
|
module Webmachine
|
|
4
2
|
module Trace
|
|
5
|
-
# Implements a trace storage using
|
|
6
|
-
#
|
|
7
|
-
#
|
|
3
|
+
# Implements a trace storage using the pstore gem. To use this trace store,
|
|
4
|
+
# add `pstore` to your Gemfile and specify the :pstore engine and a path
|
|
5
|
+
# where it can store traces:
|
|
8
6
|
# @example
|
|
9
7
|
# Webmachine::Trace.trace_store = :pstore, "/tmp/webmachine.trace"
|
|
10
8
|
class PStoreTraceStore
|
|
11
9
|
# @api private
|
|
12
10
|
# @param [String] path where to store traces in a PStore
|
|
13
11
|
def initialize(path)
|
|
12
|
+
require 'pstore' # JIT load of the pstore gem. Avoid requiring the dependency when this class is not used.
|
|
14
13
|
@pstore = PStore.new(path)
|
|
15
14
|
end
|
|
16
15
|
|
data/lib/webmachine/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,43 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: webmachine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sean Cribbs
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-09-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
-
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: i18n
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - ">="
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.4.0
|
|
20
|
-
type: :runtime
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - ">="
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.4.0
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: multi_json
|
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
|
30
|
-
requirements:
|
|
31
|
-
- - ">="
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0'
|
|
34
|
-
type: :runtime
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - ">="
|
|
39
|
-
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0'
|
|
41
13
|
- !ruby/object:Gem::Dependency
|
|
42
14
|
name: as-notifications
|
|
43
15
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -73,33 +45,33 @@ dependencies:
|
|
|
73
45
|
- !ruby/object:Gem::Version
|
|
74
46
|
version: '0'
|
|
75
47
|
- !ruby/object:Gem::Dependency
|
|
76
|
-
name:
|
|
48
|
+
name: i18n
|
|
77
49
|
requirement: !ruby/object:Gem::Requirement
|
|
78
50
|
requirements:
|
|
79
|
-
- - "
|
|
51
|
+
- - ">="
|
|
80
52
|
- !ruby/object:Gem::Version
|
|
81
|
-
version:
|
|
82
|
-
type: :
|
|
53
|
+
version: 0.4.0
|
|
54
|
+
type: :runtime
|
|
83
55
|
prerelease: false
|
|
84
56
|
version_requirements: !ruby/object:Gem::Requirement
|
|
85
57
|
requirements:
|
|
86
|
-
- - "
|
|
58
|
+
- - ">="
|
|
87
59
|
- !ruby/object:Gem::Version
|
|
88
|
-
version:
|
|
60
|
+
version: 0.4.0
|
|
89
61
|
- !ruby/object:Gem::Dependency
|
|
90
|
-
name:
|
|
62
|
+
name: multi_json
|
|
91
63
|
requirement: !ruby/object:Gem::Requirement
|
|
92
64
|
requirements:
|
|
93
|
-
- - "
|
|
65
|
+
- - ">="
|
|
94
66
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: '
|
|
96
|
-
type: :
|
|
67
|
+
version: '0'
|
|
68
|
+
type: :runtime
|
|
97
69
|
prerelease: false
|
|
98
70
|
version_requirements: !ruby/object:Gem::Requirement
|
|
99
71
|
requirements:
|
|
100
|
-
- - "
|
|
72
|
+
- - ">="
|
|
101
73
|
- !ruby/object:Gem::Version
|
|
102
|
-
version: '
|
|
74
|
+
version: '0'
|
|
103
75
|
description: " webmachine is a toolkit for building HTTP applications in a declarative
|
|
104
76
|
fashion, that avoids the confusion of going through a CGI-style interface like Rack.
|
|
105
77
|
It is strongly influenced by the original Erlang project of the same name and shares
|
|
@@ -191,13 +163,14 @@ homepage: https://github.com/webmachine/webmachine-ruby
|
|
|
191
163
|
licenses:
|
|
192
164
|
- Apache-2.0
|
|
193
165
|
metadata:
|
|
166
|
+
allowed_push_host: https://rubygems.org
|
|
194
167
|
bug_tracker_uri: https://github.com/webmachine/webmachine-ruby/issues
|
|
195
168
|
changelog_uri: https://github.com/webmachine/webmachine-ruby/blob/HEAD/CHANGELOG.md
|
|
196
|
-
documentation_uri: https://www.rubydoc.info/gems/webmachine/2.0.
|
|
169
|
+
documentation_uri: https://www.rubydoc.info/gems/webmachine/2.0.2
|
|
197
170
|
homepage_uri: https://github.com/webmachine/webmachine-ruby
|
|
198
171
|
source_code_uri: https://github.com/webmachine/webmachine-ruby
|
|
199
172
|
wiki_uri: https://github.com/webmachine/webmachine-ruby/wiki
|
|
200
|
-
post_install_message:
|
|
173
|
+
post_install_message:
|
|
201
174
|
rdoc_options: []
|
|
202
175
|
require_paths:
|
|
203
176
|
- lib
|
|
@@ -212,8 +185,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
212
185
|
- !ruby/object:Gem::Version
|
|
213
186
|
version: '0'
|
|
214
187
|
requirements: []
|
|
215
|
-
rubygems_version: 3.
|
|
216
|
-
signing_key:
|
|
188
|
+
rubygems_version: 3.0.3.1
|
|
189
|
+
signing_key:
|
|
217
190
|
specification_version: 4
|
|
218
191
|
summary: webmachine is a toolkit for building HTTP applications,
|
|
219
192
|
test_files: []
|