Repository navigation
fix(httpv2): HTTP/2 frames lose octets on rebuild (#1242-#1248, #1251) - #1341
Conversation
|
Cross-review verdict on #1247 flips which value
RFC 9113 §6.5 has the last value win. So the rebuild is byte-exact, but indexing now hands consumers the superseded value, and the PR's breaking list does not mention it. Make Everything else held. Every repro is byte-exact. #1243 handles Length 0, three back-to-back frames and Length > buffer; the prefaced and non-prefaced Add to the breaking list: a custom reader registered via |
- Schema: bound the frame payload by its declared Length, and keep what follows as a `payload` dispatched as the next layer (#1243). Name the reserved R bit of the header, PUSH_PROMISE, GOAWAY and WINDOW_UPDATE stream fields (#1246). Keep undefined flag bits in `__flags__` (#1245). - Data: add `reserved`, `promised_reserved`, `last_reserved` and `increment_reserved`; frame types with no defined flags now carry a bare `Flags` holding the raw octet instead of `None`. - Makers: PADDED follows the flag, not a non-zero Pad Length, with a new `padded` keyword (#1244); `make` ORs its `flags` with the frame's; new `reserved` and `payload` keywords; PING opaque data must be 8 octets (#1251, HTTP/2 half). - Reader: SETTINGS keeps repeated identifiers in order in a new `Settings` multidict whose index answers the last value (#1247); `make` with raw frame octets parses them back with the frame schema (#1248). - HTTP dispatcher: record the connection preface as `preface` and rebuild it, also through an explicit `version=2` (#1242). Closes #1242 Closes #1243 Closes #1244 Closes #1245 Closes #1246 Closes #1247 Closes #1248 Refs #1251
95ffb1b to
f6e21cf
Compare
|
Round-2 verdict on The round-1 blocker is fixed. A new
The rebuild stays byte-exact. The new test fails against the previous head with The breaking list now names |
|
Coverage: 88.89% (unit tier, Python 3.14,
Per-file detail: the |
make pylint,make mypy,make isort) — ran the same tools on the four changed modules: mypy and isort clean, pylint adds nothing newmake testpasses, and a test case covers the change — the modules listed below only, not the full suiteWhat is the purpose of your pull request?
fix— corrects a defectDescription of your pull request and other information
Closes #1242
Closes #1243
Closes #1244
Closes #1245
Closes #1246
Closes #1247
Closes #1248
Refs #1251 (only the HTTP/2 PING half; the OSPF half is separate)
min(length, remaining)). Whatever follows is the schema's newpayload, which is passed to the next layer asRawand rebuilt byfrom_data.info.prefaceand writes it back. An explicitversion=2now skips the preface too.__value__. Reserved R bits get areservedsub-field at each of the four sites.Settingsmultidict (anOrderedMultiDictsubclass).getlistand the rebuild keep every entry in wire order;[],get,dict()andto_dict()return the last value per identifier (RFC 9113 §6.5).make(frame=<bytes>)raises AttributeError for every frame type #1248:make(frame=<bytes>)parses the octets back with the schema for that frame type. Octets that are wrong for the type raiseProtocolError.makesilently pads or truncates fixed-width inputs #1251: PING opaque data that is not 8 octets raisesProtocolError. The default is nowbytes(8)._test_http2_frameis unchanged.Breaking.
reserved,promised_reserved,last_reservedandincrement_reserved.flagsis now aFlagsobject, notNone, for PRIORITY, RST_STREAM, GOAWAY, WINDOW_UPDATE and unassigned frame types.makenow ORs theflagsargument with the frame's own flags.info.settingsis nowSettings, not a plainOrderedMultiDict.register_framemust now return an HTTP/2 data object withreservedandflags; one that does not breaksfrom_data(see the stub edit intest_http_unit.py).makekeywords:reserved,payloadandpreface, pluspadded/*_reservedon the frame constructors.Follow-up (not in this PR).
examples/generators/options.py:1159still saysflagsis "silently ignored", which is no longer true now thatmakecombines them.Evidence. Before the fix, all 16 repros rebuilt wrong and
frame=b'abc'raisedAttributeError. After it, all 16 match byte for byte, including when frames are followed by a SETTINGS ACK. All 241 HTTP layers inexamples/capturesstill round-trip.New tests. The new module has 10 tests. Against
origin/mainsource, 36 failed and 5 passed; against the previous head95ffb1b59, only the last-value test failed (1 != 3). The 5 that passed are the PRIORITY bad-bytes guard and the 8-octet PING controls. With the fix, all pass.Test runs.
test_http_unit: 65 passed.test_http2_roundtrip_unit: 10 passed.test_option_roundtrip_unit,test_construction_keyword_check_unitandtests/project: all passed (389 passed, 1 skipped).run_unittest_leg.py protocols --exclude protocols/internet: 860 tests, 0 failures.test_http_unit.pyedits. Its stubs gained the newreservedandPADDEDkeys. Two assertions pinned the old behaviour and were updated: explicitversion=2refusing a prefaced buffer, and info equality withoutpreface.