diff --git a/http/h2_stream.lua b/http/h2_stream.lua index 7ad7c4cf..e20f6de5 100644 --- a/http/h2_stream.lua +++ b/http/h2_stream.lua @@ -362,12 +362,15 @@ frame_handlers[0x1] = function(stream, flags, payload) pos = pos + 5 local new_parent = stream.connection.streams[stream_dep] - if new_parent == nil then - error("parent doesn't exist " .. stream_dep) -- FIXME + + -- 5.3.1. Stream Dependencies + -- A dependency on a stream that is not currently in the tree + -- results in that stream being given a default priority + if new_parent then + local ok, err = new_parent:reprioritise(stream, exclusive) + if not ok then return nil, err end + stream.weight = weight end - local ok, err = new_parent:reprioritise(stream, exclusive) - if not ok then return nil, err end - stream.weight = weight end if #payload - pos + 1 > MAX_HEADER_BUFFER_SIZE then diff --git a/spec/h2_connection_spec.lua b/spec/h2_connection_spec.lua index 4610738e..13e604fb 100644 --- a/spec/h2_connection_spec.lua +++ b/spec/h2_connection_spec.lua @@ -157,6 +157,37 @@ describe("http2 connection", function() assert.truthy(cq:empty()) end) end) + describe("priority on missing stream", function() + it("sets default priority for streams with missing parent", function() + local cq = cqueues.new() + local c, s = cs.pair() + cq:wrap(function() + c = h2_connection.new(c, "client") + local client_stream = c:new_stream() + local req_headers = new_headers() + req_headers:append(":method", "GET") + req_headers:append(":scheme", "http") + req_headers:append(":path", "/") + -- Encode HEADER payload and send with dependency on missing stream + c.encoding_context:encode_headers(req_headers) + local payload = c.encoding_context:render_data() + c.encoding_context:clear_data() + assert(client_stream:write_headers_frame(payload, true, true, nil, nil, 99, 99)) + client_stream:shutdown() + assert(c:close()) + end) + cq:wrap(function() + s = h2_connection.new(s, "server") + local stream = assert(s:get_next_incoming_stream()) + -- Check if set to default priority instead of missing parent + assert.is_not.same(stream.weight, 99) + stream:shutdown() + assert(s:close()) + end) + assert_loop(cq, TEST_TIMEOUT) + assert.truthy(cq:empty()) + end) + end) describe("settings", function() it("correctly handles odd frame sizes", function() local c = cs.pair()