julewire-rack 1.0.0 → 1.1.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 +4 -4
- data/CHANGELOG.md +10 -0
- data/julewire-rack.gemspec +1 -1
- data/lib/julewire/rack/capture/buffered_response_body.rb +4 -14
- data/lib/julewire/rack/capture/header_selection.rb +5 -5
- data/lib/julewire/rack/capture/request_body.rb +25 -7
- data/lib/julewire/rack/capture/settings.rb +1 -1
- data/lib/julewire/rack/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: eb74d11c52a34a94a086bce1adcb38f347f12665a3c48b31e09cb2e851a66346
|
|
4
|
+
data.tar.gz: e44437009a72f9bb50eb48908efaa3b4825c75129dc406d20fc58f998645a434
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7e9f9858ef76ee7f26a8b9aa59fb4c2196082285f3e9416444a33d6c6f54332e2db9938fad1a00b3a2ea5d020e7d81e322d87abe4475f7e7035bb68a256bcf57
|
|
7
|
+
data.tar.gz: 4ef90c074f7a6adbb0942b646fa57efd8213581cf9c5710a4d879815ae8c3ea955adfa9d7f57ce21a79baeab82562658045788564f3ad2e8d14f9e412285399e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
## Unreleased
|
|
2
2
|
|
|
3
|
+
## 1.1.0 - 2026-07-20
|
|
4
|
+
|
|
5
|
+
- Cap request body capture by observed bytes, even when `Content-Length` claims
|
|
6
|
+
a smaller body.
|
|
7
|
+
- Require julewire-core 1.1.0.
|
|
8
|
+
|
|
9
|
+
## 1.0.1 - 2026-06-25
|
|
10
|
+
|
|
11
|
+
- Require julewire-core 1.0.1.
|
|
12
|
+
|
|
3
13
|
## 1.0.0 - 2026-06-21
|
|
4
14
|
|
|
5
15
|
- Initial release: Rack-family request lifecycle support primitives for Julewire
|
data/julewire-rack.gemspec
CHANGED
|
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
|
31
31
|
spec.executables = []
|
|
32
32
|
spec.require_paths = ["lib"]
|
|
33
33
|
|
|
34
|
-
spec.add_dependency "julewire-core", ">= 1.0"
|
|
34
|
+
spec.add_dependency "julewire-core", ">= 1.1.0"
|
|
35
35
|
spec.add_dependency "rack", ">= 3.2"
|
|
36
36
|
spec.add_dependency "zeitwerk", ">= 2.8.1"
|
|
37
37
|
end
|
|
@@ -8,7 +8,7 @@ module Julewire
|
|
|
8
8
|
def call(response, **) = new(response, **).summary_fields
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def initialize(response, content_types:, limit:, mode:
|
|
11
|
+
def initialize(response, content_types:, limit:, mode: nil)
|
|
12
12
|
@response = response
|
|
13
13
|
@content_types = content_types
|
|
14
14
|
@limit = limit
|
|
@@ -30,7 +30,7 @@ module Julewire
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
capture(body_parts)
|
|
33
|
-
return {} if @total_bytes.zero?
|
|
33
|
+
return {} if @total_bytes.zero?
|
|
34
34
|
|
|
35
35
|
JsonBody.fields(:response, @captured, bytes: @total_bytes, truncated: @truncated, mode: @mode)
|
|
36
36
|
end
|
|
@@ -38,11 +38,8 @@ module Julewire
|
|
|
38
38
|
private
|
|
39
39
|
|
|
40
40
|
def response_body_parts
|
|
41
|
-
return unless @response.respond_to?(:stream)
|
|
42
|
-
|
|
43
41
|
stream = @response.stream
|
|
44
42
|
return if stream.respond_to?(:to_path)
|
|
45
|
-
return unless stream.respond_to?(:to_ary)
|
|
46
43
|
|
|
47
44
|
stream.to_ary
|
|
48
45
|
rescue StandardError
|
|
@@ -59,9 +56,7 @@ module Julewire
|
|
|
59
56
|
end
|
|
60
57
|
|
|
61
58
|
def body_string(part)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
nil
|
|
59
|
+
part.to_str
|
|
65
60
|
rescue StandardError
|
|
66
61
|
nil
|
|
67
62
|
end
|
|
@@ -70,7 +65,7 @@ module Julewire
|
|
|
70
65
|
return unless body_parts.length == 1
|
|
71
66
|
|
|
72
67
|
body = body_string(body_parts.first)
|
|
73
|
-
return
|
|
68
|
+
return unless body && !body.empty?
|
|
74
69
|
|
|
75
70
|
JsonBody.fields(:response, body, bytes: body.bytesize, truncated: false, mode: @mode)
|
|
76
71
|
end
|
|
@@ -82,11 +77,6 @@ module Julewire
|
|
|
82
77
|
return @captured << body if @limit.nil?
|
|
83
78
|
|
|
84
79
|
remaining = @limit - @captured.bytesize
|
|
85
|
-
if remaining <= 0
|
|
86
|
-
@truncated = true if bytesize.positive?
|
|
87
|
-
return
|
|
88
|
-
end
|
|
89
|
-
|
|
90
80
|
@captured << body.byteslice(0, remaining)
|
|
91
81
|
@truncated = true if bytesize > remaining
|
|
92
82
|
end
|
|
@@ -15,21 +15,21 @@ module Julewire
|
|
|
15
15
|
|
|
16
16
|
class << self
|
|
17
17
|
def build(selector)
|
|
18
|
-
return new(true) if selector == true
|
|
19
18
|
return unless selector
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
allowed = Array(selector).to_h { [normalize_name(it), true] } unless selector == true
|
|
21
|
+
new(allowed)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def normalize_name(name) = name.to_s.tr("_", "-").downcase
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
def initialize(
|
|
28
|
-
@
|
|
27
|
+
def initialize(allowed)
|
|
28
|
+
@allowed = allowed
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def include?(name)
|
|
32
|
-
@
|
|
32
|
+
@allowed ? @allowed.key?(name) : !SENSITIVE_HEADER_SET.key?(name)
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
end
|
|
@@ -27,28 +27,46 @@ module Julewire
|
|
|
27
27
|
private
|
|
28
28
|
|
|
29
29
|
def capture_body
|
|
30
|
-
body = bounded_body
|
|
31
|
-
bytes = content_length || body.bytesize
|
|
30
|
+
body, bytes = bounded_body
|
|
32
31
|
captured, truncated = capture(body, total_bytes: bytes)
|
|
33
32
|
[captured, bytes, truncated]
|
|
34
33
|
rescue StandardError
|
|
35
34
|
nil
|
|
36
35
|
end
|
|
37
36
|
|
|
37
|
+
def captured_body_bytes(body, trust_actual_bytes:)
|
|
38
|
+
actual_bytes = body.bytesize
|
|
39
|
+
return actual_bytes if trust_actual_bytes && actual_bytes <= @limit
|
|
40
|
+
|
|
41
|
+
[content_length, actual_bytes].compact.max
|
|
42
|
+
end
|
|
43
|
+
|
|
38
44
|
def bounded_body
|
|
39
|
-
return
|
|
45
|
+
return uncapped_body unless @limit
|
|
40
46
|
|
|
41
47
|
length = content_length
|
|
42
|
-
return
|
|
48
|
+
return trusted_body if length && length <= @limit
|
|
49
|
+
|
|
50
|
+
body, position = read_body_stream(limit: @limit + 1)
|
|
51
|
+
[body, captured_body_bytes(body, trust_actual_bytes: position&.zero?)]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def uncapped_body
|
|
55
|
+
body = request_body
|
|
56
|
+
[body, body.bytesize]
|
|
57
|
+
end
|
|
43
58
|
|
|
44
|
-
|
|
59
|
+
def trusted_body
|
|
60
|
+
body = request_body
|
|
61
|
+
[body, captured_body_bytes(body, trust_actual_bytes: true)]
|
|
45
62
|
end
|
|
46
63
|
|
|
47
64
|
def request_body
|
|
48
65
|
# Rack/Rails may already buffer raw_post; the byte cap applies after that read.
|
|
49
66
|
return @request.raw_post if @request.respond_to?(:raw_post)
|
|
50
67
|
|
|
51
|
-
read_body_stream(limit: nil)
|
|
68
|
+
body, = read_body_stream(limit: nil)
|
|
69
|
+
body
|
|
52
70
|
end
|
|
53
71
|
|
|
54
72
|
def read_body_stream(limit:)
|
|
@@ -61,7 +79,7 @@ module Julewire
|
|
|
61
79
|
ensure
|
|
62
80
|
restore_body_stream(io, original_position)
|
|
63
81
|
end
|
|
64
|
-
body.to_str
|
|
82
|
+
[body.to_str, original_position]
|
|
65
83
|
end
|
|
66
84
|
|
|
67
85
|
def body_stream_position(io)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: julewire-rack
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alexander Grebennik
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version:
|
|
18
|
+
version: 1.1.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version:
|
|
25
|
+
version: 1.1.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: rack
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -95,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
96
|
version: '0'
|
|
97
97
|
requirements: []
|
|
98
|
-
rubygems_version: 4.0.
|
|
98
|
+
rubygems_version: 4.0.16
|
|
99
99
|
specification_version: 4
|
|
100
100
|
summary: Rack request lifecycle support for Julewire.
|
|
101
101
|
test_files: []
|