Skip to content

Commit 0a1bd89

Browse files
committed
Handle framed RSC payloads in request spec
1 parent d0df4ab commit 0a1bd89

1 file changed

Lines changed: 40 additions & 4 deletions

File tree

spec/requests/server_components_spec.rb

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# frozen_string_literal: true
22

33
require "rails_helper"
4-
require "react_on_rails/length_prefixed_parser"
54

65
describe "Server Components" do
76
it "GET /server-components returns the demo page shell" do
@@ -12,13 +11,50 @@
1211

1312
describe "RSC payload endpoint" do
1413
def parsed_chunks
14+
body = response.body.b
1515
chunks = []
16-
parser = ReactOnRails::LengthPrefixedParser.new
17-
parser.feed(response.body.b) { |chunk| chunks << chunk }
18-
parser.flush
16+
17+
until body.empty?
18+
body = discard_blank_frame_lines(body)
19+
break if body.empty?
20+
21+
chunk, body = parse_length_prefixed_chunk(body)
22+
chunks << chunk
23+
end
24+
1925
chunks
2026
end
2127

28+
def discard_blank_frame_lines(body)
29+
body = body.byteslice(1..) || "".b while body.start_with?("\n")
30+
body
31+
end
32+
33+
def parse_length_prefixed_chunk(body)
34+
header_end = body.index("\n")
35+
raise "Malformed length-prefixed RSC payload: missing header newline" unless header_end
36+
37+
metadata_json, content_length_hex = body.byteslice(0, header_end).split("\t", 2)
38+
raise "Malformed length-prefixed RSC payload: missing tab separator" unless content_length_hex
39+
40+
content_start = header_end + 1
41+
content_length = Integer(content_length_hex, 16)
42+
content = body.byteslice(content_start, content_length)
43+
raise "Malformed length-prefixed RSC payload: truncated content" unless content&.bytesize == content_length
44+
45+
[
46+
parse_payload_metadata(metadata_json, content),
47+
body.byteslice(content_start + content_length, body.bytesize) || "".b
48+
]
49+
end
50+
51+
def parse_payload_metadata(metadata_json, content)
52+
metadata = JSON.parse(metadata_json.force_encoding(Encoding::UTF_8))
53+
content.force_encoding(Encoding::UTF_8)
54+
metadata["html"] = metadata.delete("payloadType") == "object" ? JSON.parse(content) : content
55+
metadata
56+
end
57+
2258
def expect_valid_rsc_payload
2359
expect(response).to have_http_status(:ok)
2460
expect(response.media_type).to eq("application/x-ndjson")

0 commit comments

Comments
 (0)