|
36 | 36 |
|
37 | 37 | import org.apache.hc.core5.function.Supplier;
|
38 | 38 | import org.apache.hc.core5.http.Header;
|
39 |
| -import org.apache.hc.core5.http.HttpException; |
40 | 39 | import org.apache.hc.core5.http.config.CharCodingConfig;
|
41 | 40 | import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
|
42 | 41 | import org.apache.hc.core5.http.impl.CharCodingSupport;
|
@@ -245,7 +244,7 @@ void testInputMultipleFrames() throws Exception {
|
245 | 244 | }
|
246 | 245 |
|
247 | 246 | @Test
|
248 |
| - void testInputHeaderContinuationFrame() throws IOException, HttpException { |
| 247 | + void testInputHeaderContinuationFrame() throws Exception { |
249 | 248 | final H2Config h2Config = H2Config.custom().setMaxFrameSize(FrameConsts.MIN_FRAME_SIZE)
|
250 | 249 | .build();
|
251 | 250 |
|
@@ -538,5 +537,113 @@ void testContinuationAfterEndOfStream() throws Exception {
|
538 | 537 | Assertions.assertEquals(H2Error.PROTOCOL_ERROR, H2Error.getByCode(exception.getCode()));
|
539 | 538 | }
|
540 | 539 |
|
| 540 | + |
| 541 | + @Test |
| 542 | + void testInputHeaderContinuationFramesNoLimit() throws Exception { |
| 543 | + final H2Config h2Config = H2Config.custom() |
| 544 | + .setMaxContinuations(Integer.MAX_VALUE) |
| 545 | + .build(); |
| 546 | + |
| 547 | + final ByteArrayBuffer headerBuf = new ByteArrayBuffer(19); |
| 548 | + final HPackEncoder encoder = new HPackEncoder(H2Config.INIT.getHeaderTableSize(), CharCodingSupport.createEncoder(CharCodingConfig.DEFAULT)); |
| 549 | + final List<Header> headers = new ArrayList<>(); |
| 550 | + headers.add(new BasicHeader(":status", "200")); |
| 551 | + for (int i = 1; i <= 100; i++) { |
| 552 | + headers.add(new BasicHeader("test-header-key-" + i, "value-" + i)); |
| 553 | + } |
| 554 | + encoder.encodeHeaders(headerBuf, headers, h2Config.isCompressionEnabled()); |
| 555 | + |
| 556 | + Assertions.assertTrue(headerBuf.length() > 750); |
| 557 | + |
| 558 | + final AbstractH2StreamMultiplexer streamMultiplexer = new H2StreamMultiplexerImpl( |
| 559 | + protocolIOSession, |
| 560 | + FRAME_FACTORY, |
| 561 | + StreamIdGenerator.ODD, |
| 562 | + httpProcessor, |
| 563 | + CharCodingConfig.DEFAULT, |
| 564 | + h2Config, |
| 565 | + h2StreamListener, |
| 566 | + () -> streamHandler); |
| 567 | + |
| 568 | + final WritableByteChannelMock writableChannel = new WritableByteChannelMock(1024); |
| 569 | + final FrameOutputBuffer outBuffer = new FrameOutputBuffer(16 * 1024); |
| 570 | + |
| 571 | + final RawFrame headerFrame = FRAME_FACTORY.createHeaders(2, ByteBuffer.wrap(headerBuf.array(), 0, 250), false, false); |
| 572 | + outBuffer.write(headerFrame, writableChannel); |
| 573 | + |
| 574 | + streamMultiplexer.onInput(ByteBuffer.wrap(writableChannel.toByteArray())); |
| 575 | + |
| 576 | + writableChannel.reset(); |
| 577 | + final RawFrame continuationFrame1 = FRAME_FACTORY.createContinuation(2, ByteBuffer.wrap(headerBuf.array(), 250, 250), false); |
| 578 | + outBuffer.write(continuationFrame1, writableChannel); |
| 579 | + streamMultiplexer.onInput(ByteBuffer.wrap(writableChannel.toByteArray())); |
| 580 | + |
| 581 | + writableChannel.reset(); |
| 582 | + final RawFrame continuationFrame2 = FRAME_FACTORY.createContinuation(2, ByteBuffer.wrap(headerBuf.array(), 500, 250), false); |
| 583 | + outBuffer.write(continuationFrame2, writableChannel); |
| 584 | + streamMultiplexer.onInput(ByteBuffer.wrap(writableChannel.toByteArray())); |
| 585 | + |
| 586 | + writableChannel.reset(); |
| 587 | + final RawFrame continuationFrame3 = FRAME_FACTORY.createContinuation(2, ByteBuffer.wrap(headerBuf.array(), 750, headerBuf.length() - 750), true); |
| 588 | + outBuffer.write(continuationFrame3, writableChannel); |
| 589 | + streamMultiplexer.onInput(ByteBuffer.wrap(writableChannel.toByteArray())); |
| 590 | + |
| 591 | + Mockito.verify(streamHandler).consumeHeader(headersCaptor.capture(), ArgumentMatchers.eq(false)); |
| 592 | + Assertions.assertFalse(headersCaptor.getValue().isEmpty()); |
| 593 | + } |
| 594 | + |
| 595 | + @Test |
| 596 | + void testInputHeaderContinuationFramesMaxLimit() throws Exception { |
| 597 | + final H2Config h2Config = H2Config.custom() |
| 598 | + .setMaxContinuations(2) |
| 599 | + .build(); |
| 600 | + |
| 601 | + final ByteArrayBuffer headerBuf = new ByteArrayBuffer(19); |
| 602 | + final HPackEncoder encoder = new HPackEncoder(H2Config.INIT.getHeaderTableSize(), CharCodingSupport.createEncoder(CharCodingConfig.DEFAULT)); |
| 603 | + final List<Header> headers = new ArrayList<>(); |
| 604 | + headers.add(new BasicHeader(":status", "200")); |
| 605 | + for (int i = 1; i <= 100; i++) { |
| 606 | + headers.add(new BasicHeader("test-header-key-" + i, "value-" + i)); |
| 607 | + } |
| 608 | + encoder.encodeHeaders(headerBuf, headers, h2Config.isCompressionEnabled()); |
| 609 | + |
| 610 | + Assertions.assertTrue(headerBuf.length() > 750); |
| 611 | + |
| 612 | + final AbstractH2StreamMultiplexer streamMultiplexer = new H2StreamMultiplexerImpl( |
| 613 | + protocolIOSession, |
| 614 | + FRAME_FACTORY, |
| 615 | + StreamIdGenerator.ODD, |
| 616 | + httpProcessor, |
| 617 | + CharCodingConfig.DEFAULT, |
| 618 | + h2Config, |
| 619 | + h2StreamListener, |
| 620 | + () -> streamHandler); |
| 621 | + |
| 622 | + final WritableByteChannelMock writableChannel = new WritableByteChannelMock(1024); |
| 623 | + final FrameOutputBuffer outBuffer = new FrameOutputBuffer(16 * 1024); |
| 624 | + |
| 625 | + final RawFrame headerFrame = FRAME_FACTORY.createHeaders(2, ByteBuffer.wrap(headerBuf.array(), 0, 250), false, false); |
| 626 | + outBuffer.write(headerFrame, writableChannel); |
| 627 | + |
| 628 | + streamMultiplexer.onInput(ByteBuffer.wrap(writableChannel.toByteArray())); |
| 629 | + |
| 630 | + writableChannel.reset(); |
| 631 | + final RawFrame continuationFrame1 = FRAME_FACTORY.createContinuation(2, ByteBuffer.wrap(headerBuf.array(), 250, 250), false); |
| 632 | + outBuffer.write(continuationFrame1, writableChannel); |
| 633 | + streamMultiplexer.onInput(ByteBuffer.wrap(writableChannel.toByteArray())); |
| 634 | + |
| 635 | + writableChannel.reset(); |
| 636 | + final RawFrame continuationFrame2 = FRAME_FACTORY.createContinuation(2, ByteBuffer.wrap(headerBuf.array(), 500, 250), false); |
| 637 | + outBuffer.write(continuationFrame2, writableChannel); |
| 638 | + streamMultiplexer.onInput(ByteBuffer.wrap(writableChannel.toByteArray())); |
| 639 | + |
| 640 | + writableChannel.reset(); |
| 641 | + final RawFrame continuationFrame3 = FRAME_FACTORY.createContinuation(2, ByteBuffer.wrap(headerBuf.array(), 750, headerBuf.length() - 750), true); |
| 642 | + outBuffer.write(continuationFrame3, writableChannel); |
| 643 | + |
| 644 | + Assertions.assertThrows(H2ConnectionException.class, () -> |
| 645 | + streamMultiplexer.onInput(ByteBuffer.wrap(writableChannel.toByteArray()))); |
| 646 | + } |
| 647 | + |
541 | 648 | }
|
542 | 649 |
|
0 commit comments