Skip to content

Commit 10f1d0e

Browse files
authored
fix: Fixed exception when decoding from a rack source that uses InputWrapper (#50)
Signed-off-by: Daniel Azuma <[email protected]>
1 parent 77b7380 commit 10f1d0e

File tree

3 files changed

+46
-8
lines changed

3 files changed

+46
-8
lines changed

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ gem "google-style", "~> 1.25.1"
55
gem "minitest", "~> 5.14"
66
gem "minitest-focus", "~> 1.1"
77
gem "minitest-rg", "~> 5.2"
8+
gem "rack", "~> 2.2"
89
gem "redcarpet", "~> 3.5" unless ::RUBY_PLATFORM == "java"
910
gem "yard", "~> 0.9.25"

lib/cloud_events/http_binding.rb

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,11 @@ def decode_rack_env env, **format_args
8989
if input && content_type&.media_type == "application"
9090
case content_type.subtype_base
9191
when "cloudevents"
92-
input.set_encoding content_type.charset if content_type.charset
93-
return decode_structured_content input.read, content_type.subtype_format, **format_args
92+
content = read_with_charset input, content_type.charset
93+
return decode_structured_content content, content_type.subtype_format, **format_args
9494
when "cloudevents-batch"
95-
input.set_encoding content_type.charset if content_type.charset
96-
return decode_batched_content input.read, content_type.subtype_format, **format_args
95+
content = read_with_charset input, content_type.charset
96+
return decode_batched_content content, content_type.subtype_format, **format_args
9797
end
9898
end
9999
decode_binary_content env, content_type
@@ -152,10 +152,7 @@ def decode_binary_content env, content_type
152152
return nil if spec_version.nil?
153153
raise SpecVersionError, "Unrecognized specversion: #{spec_version}" unless spec_version == "1.0"
154154
input = env["rack.input"]
155-
data = if input
156-
input.set_encoding content_type.charset if content_type&.charset
157-
input.read
158-
end
155+
data = read_with_charset input, content_type&.charset if input
159156
attributes = { "spec_version" => spec_version, "data" => data }
160157
attributes["data_content_type"] = content_type if content_type
161158
omit_names = ["specversion", "spec_version", "data", "datacontenttype", "data_content_type"]
@@ -289,6 +286,18 @@ def percent_encode str
289286

290287
private
291288

289+
def read_with_charset io, charset
290+
str = io.read
291+
if charset
292+
begin
293+
str.force_encoding charset
294+
rescue ::ArgumentError
295+
# Do nothing for now if the charset is unrecognized
296+
end
297+
end
298+
str
299+
end
300+
292301
def string_content_type str
293302
if str.encoding == ::Encoding.ASCII_8BIT
294303
"application/octet-stream"

test/test_http_binding.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
require "json"
77
require "stringio"
88
require "uri"
9+
require "rack/lint"
910

1011
describe CloudEvents::HttpBinding do
1112
let(:http_binding) { CloudEvents::HttpBinding.default }
@@ -140,6 +141,33 @@
140141
assert_equal my_json_struct_encoded, body
141142
end
142143

144+
it "decodes a binary rack env using an InputWrapper and re-encodes as structured" do
145+
env = {
146+
"rack.input" => Rack::Lint::InputWrapper.new(StringIO.new(my_simple_data)),
147+
"HTTP_CE_ID" => my_id,
148+
"HTTP_CE_SOURCE" => my_source_string,
149+
"HTTP_CE_TYPE" => my_type,
150+
"HTTP_CE_SPECVERSION" => spec_version,
151+
"CONTENT_TYPE" => my_content_type_string,
152+
"HTTP_CE_DATASCHEMA" => my_schema_string,
153+
"HTTP_CE_SUBJECT" => my_subject,
154+
"HTTP_CE_TIME" => my_time_string
155+
}
156+
event = http_binding.decode_rack_env env
157+
assert_equal my_id, event.id
158+
assert_equal my_source, event.source
159+
assert_equal my_type, event.type
160+
assert_equal spec_version, event.spec_version
161+
assert_equal my_simple_data, event.data
162+
assert_equal my_content_type, event.data_content_type
163+
assert_equal my_schema, event.data_schema
164+
assert_equal my_subject, event.subject
165+
assert_equal my_time, event.time
166+
headers, body = http_binding.encode_structured_content event, "json", sort: true
167+
assert_equal({ "Content-Type" => "application/cloudevents+json" }, headers)
168+
assert_equal my_json_struct_encoded, body
169+
end
170+
143171
it "decodes and re-encodes binary, honoring optional headers" do
144172
env = {
145173
"HTTP_CE_ID" => my_id,

0 commit comments

Comments
 (0)