1# -*- coding: utf-8 -*- 2""" 3test_basic_logic 4~~~~~~~~~~~~~~~~ 5 6Test the basic logic of the h2 state machines. 7""" 8import random 9import sys 10 11import hyperframe 12import pytest 13 14import h2.config 15import h2.connection 16import h2.errors 17import h2.events 18import h2.exceptions 19import h2.frame_buffer 20import h2.settings 21import h2.stream 22 23import helpers 24 25from hypothesis import given 26from hypothesis.strategies import integers 27 28 29IS_PYTHON3 = sys.version_info >= (3, 0) 30 31 32class TestBasicClient(object): 33 """ 34 Basic client-side tests. 35 """ 36 example_request_headers = [ 37 (u':authority', u'example.com'), 38 (u':path', u'/'), 39 (u':scheme', u'https'), 40 (u':method', u'GET'), 41 ] 42 bytes_example_request_headers = [ 43 (b':authority', b'example.com'), 44 (b':path', b'/'), 45 (b':scheme', b'https'), 46 (b':method', b'GET'), 47 ] 48 example_response_headers = [ 49 (u':status', u'200'), 50 (u'server', u'fake-serv/0.1.0') 51 ] 52 bytes_example_response_headers = [ 53 (b':status', b'200'), 54 (b'server', b'fake-serv/0.1.0') 55 ] 56 57 def test_begin_connection(self, frame_factory): 58 """ 59 Client connections emit the HTTP/2 preamble. 60 """ 61 c = h2.connection.H2Connection() 62 expected_settings = frame_factory.build_settings_frame( 63 c.local_settings 64 ) 65 expected_data = ( 66 b'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n' + expected_settings.serialize() 67 ) 68 69 events = c.initiate_connection() 70 assert not events 71 assert c.data_to_send() == expected_data 72 73 def test_sending_headers(self): 74 """ 75 Single headers frames are correctly encoded. 76 """ 77 c = h2.connection.H2Connection() 78 c.initiate_connection() 79 80 # Clear the data, then send headers. 81 c.clear_outbound_data_buffer() 82 events = c.send_headers(1, self.example_request_headers) 83 assert not events 84 assert c.data_to_send() == ( 85 b'\x00\x00\r\x01\x04\x00\x00\x00\x01' 86 b'A\x88/\x91\xd3]\x05\\\x87\xa7\x84\x87\x82' 87 ) 88 89 def test_sending_data(self): 90 """ 91 Single data frames are encoded correctly. 92 """ 93 c = h2.connection.H2Connection() 94 c.initiate_connection() 95 c.send_headers(1, self.example_request_headers) 96 97 # Clear the data, then send some data. 98 c.clear_outbound_data_buffer() 99 events = c.send_data(1, b'some data') 100 assert not events 101 data_to_send = c.data_to_send() 102 assert ( 103 data_to_send == b'\x00\x00\t\x00\x00\x00\x00\x00\x01some data' 104 ) 105 106 buffer = h2.frame_buffer.FrameBuffer(server=False) 107 buffer.max_frame_size = 65535 108 buffer.add_data(data_to_send) 109 data_frame = list(buffer)[0] 110 sanity_check_data_frame( 111 data_frame=data_frame, 112 expected_flow_controlled_length=len(b'some data'), 113 expect_padded_flag=False, 114 expected_data_frame_pad_length=0 115 ) 116 117 def test_sending_data_in_memoryview(self): 118 """ 119 Support memoryview for sending data. 120 """ 121 c = h2.connection.H2Connection() 122 c.initiate_connection() 123 c.send_headers(1, self.example_request_headers) 124 125 # Clear the data, then send some data. 126 c.clear_outbound_data_buffer() 127 events = c.send_data(1, memoryview(b'some data')) 128 assert not events 129 data_to_send = c.data_to_send() 130 assert ( 131 data_to_send == b'\x00\x00\t\x00\x00\x00\x00\x00\x01some data' 132 ) 133 134 def test_sending_data_with_padding(self): 135 """ 136 Single data frames with padding are encoded correctly. 137 """ 138 c = h2.connection.H2Connection() 139 c.initiate_connection() 140 c.send_headers(1, self.example_request_headers) 141 142 # Clear the data, then send some data. 143 c.clear_outbound_data_buffer() 144 events = c.send_data(1, b'some data', pad_length=5) 145 assert not events 146 data_to_send = c.data_to_send() 147 assert data_to_send == ( 148 b'\x00\x00\x0f\x00\x08\x00\x00\x00\x01' 149 b'\x05some data\x00\x00\x00\x00\x00' 150 ) 151 152 buffer = h2.frame_buffer.FrameBuffer(server=False) 153 buffer.max_frame_size = 65535 154 buffer.add_data(data_to_send) 155 data_frame = list(buffer)[0] 156 sanity_check_data_frame( 157 data_frame=data_frame, 158 expected_flow_controlled_length=len(b'some data') + 1 + 5, 159 expect_padded_flag=True, 160 expected_data_frame_pad_length=5 161 ) 162 163 def test_sending_data_with_zero_length_padding(self): 164 """ 165 Single data frames with zero-length padding are encoded 166 correctly. 167 """ 168 c = h2.connection.H2Connection() 169 c.initiate_connection() 170 c.send_headers(1, self.example_request_headers) 171 172 # Clear the data, then send some data. 173 c.clear_outbound_data_buffer() 174 events = c.send_data(1, b'some data', pad_length=0) 175 assert not events 176 data_to_send = c.data_to_send() 177 assert data_to_send == ( 178 b'\x00\x00\x0a\x00\x08\x00\x00\x00\x01' 179 b'\x00some data' 180 ) 181 182 buffer = h2.frame_buffer.FrameBuffer(server=False) 183 buffer.max_frame_size = 65535 184 buffer.add_data(data_to_send) 185 data_frame = list(buffer)[0] 186 sanity_check_data_frame( 187 data_frame=data_frame, 188 expected_flow_controlled_length=len(b'some data') + 1, 189 expect_padded_flag=True, 190 expected_data_frame_pad_length=0 191 ) 192 193 @pytest.mark.parametrize("expected_error,pad_length", [ 194 (None, 0), 195 (None, 255), 196 (None, None), 197 (ValueError, -1), 198 (ValueError, 256), 199 (TypeError, 'invalid'), 200 (TypeError, ''), 201 (TypeError, '10'), 202 (TypeError, {}), 203 (TypeError, ['1', '2', '3']), 204 (TypeError, []), 205 (TypeError, 1.5), 206 (TypeError, 1.0), 207 (TypeError, -1.0), 208 ]) 209 def test_sending_data_with_invalid_padding_length(self, 210 expected_error, 211 pad_length): 212 """ 213 ``send_data`` with a ``pad_length`` parameter that is an integer 214 outside the range of [0, 255] throws a ``ValueError``, and a 215 ``pad_length`` parameter which is not an ``integer`` type 216 throws a ``TypeError``. 217 """ 218 c = h2.connection.H2Connection() 219 c.initiate_connection() 220 c.send_headers(1, self.example_request_headers) 221 222 c.clear_outbound_data_buffer() 223 if expected_error is not None: 224 with pytest.raises(expected_error): 225 c.send_data(1, b'some data', pad_length=pad_length) 226 else: 227 c.send_data(1, b'some data', pad_length=pad_length) 228 229 def test_closing_stream_sending_data(self, frame_factory): 230 """ 231 We can close a stream with a data frame. 232 """ 233 c = h2.connection.H2Connection() 234 c.initiate_connection() 235 c.send_headers(1, self.example_request_headers) 236 237 f = frame_factory.build_data_frame( 238 data=b'some data', 239 flags=['END_STREAM'], 240 ) 241 242 # Clear the data, then send some data. 243 c.clear_outbound_data_buffer() 244 events = c.send_data(1, b'some data', end_stream=True) 245 assert not events 246 assert c.data_to_send() == f.serialize() 247 248 def test_receiving_a_response(self, frame_factory): 249 """ 250 When receiving a response, the ResponseReceived event fires. 251 """ 252 config = h2.config.H2Configuration(header_encoding='utf-8') 253 c = h2.connection.H2Connection(config=config) 254 c.initiate_connection() 255 c.send_headers(1, self.example_request_headers, end_stream=True) 256 257 # Clear the data 258 f = frame_factory.build_headers_frame( 259 self.example_response_headers 260 ) 261 events = c.receive_data(f.serialize()) 262 263 assert len(events) == 1 264 event = events[0] 265 266 assert isinstance(event, h2.events.ResponseReceived) 267 assert event.stream_id == 1 268 assert event.headers == self.example_response_headers 269 270 def test_receiving_a_response_bytes(self, frame_factory): 271 """ 272 When receiving a response, the ResponseReceived event fires with bytes 273 headers if the encoding is set appropriately. 274 """ 275 config = h2.config.H2Configuration(header_encoding=False) 276 c = h2.connection.H2Connection(config=config) 277 c.initiate_connection() 278 c.send_headers(1, self.example_request_headers, end_stream=True) 279 280 # Clear the data 281 f = frame_factory.build_headers_frame( 282 self.example_response_headers 283 ) 284 events = c.receive_data(f.serialize()) 285 286 assert len(events) == 1 287 event = events[0] 288 289 assert isinstance(event, h2.events.ResponseReceived) 290 assert event.stream_id == 1 291 assert event.headers == self.bytes_example_response_headers 292 293 def test_receiving_a_response_change_encoding(self, frame_factory): 294 """ 295 When receiving a response, the ResponseReceived event fires with bytes 296 headers if the encoding is set appropriately, but if this changes then 297 the change reflects it. 298 """ 299 config = h2.config.H2Configuration(header_encoding=False) 300 c = h2.connection.H2Connection(config=config) 301 c.initiate_connection() 302 c.send_headers(1, self.example_request_headers, end_stream=True) 303 304 f = frame_factory.build_headers_frame( 305 self.example_response_headers 306 ) 307 events = c.receive_data(f.serialize()) 308 309 assert len(events) == 1 310 event = events[0] 311 312 assert isinstance(event, h2.events.ResponseReceived) 313 assert event.stream_id == 1 314 assert event.headers == self.bytes_example_response_headers 315 316 c.send_headers(3, self.example_request_headers, end_stream=True) 317 c.config.header_encoding = 'utf-8' 318 f = frame_factory.build_headers_frame( 319 self.example_response_headers, 320 stream_id=3, 321 ) 322 events = c.receive_data(f.serialize()) 323 324 assert len(events) == 1 325 event = events[0] 326 327 assert isinstance(event, h2.events.ResponseReceived) 328 assert event.stream_id == 3 329 assert event.headers == self.example_response_headers 330 331 def test_end_stream_without_data(self, frame_factory): 332 """ 333 Ending a stream without data emits a zero-length DATA frame with 334 END_STREAM set. 335 """ 336 c = h2.connection.H2Connection() 337 c.initiate_connection() 338 c.send_headers(1, self.example_request_headers, end_stream=False) 339 340 # Clear the data 341 c.clear_outbound_data_buffer() 342 f = frame_factory.build_data_frame(b'', flags=['END_STREAM']) 343 events = c.end_stream(1) 344 345 assert not events 346 assert c.data_to_send() == f.serialize() 347 348 def test_cannot_send_headers_on_lower_stream_id(self): 349 """ 350 Once stream ID x has been used, cannot use stream ID y where y < x. 351 """ 352 c = h2.connection.H2Connection() 353 c.initiate_connection() 354 c.send_headers(3, self.example_request_headers, end_stream=False) 355 356 with pytest.raises(h2.exceptions.StreamIDTooLowError) as e: 357 c.send_headers(1, self.example_request_headers, end_stream=True) 358 359 assert e.value.stream_id == 1 360 assert e.value.max_stream_id == 3 361 362 def test_receiving_pushed_stream(self, frame_factory): 363 """ 364 Pushed streams fire a PushedStreamReceived event, followed by 365 ResponseReceived when the response headers are received. 366 """ 367 config = h2.config.H2Configuration(header_encoding='utf-8') 368 c = h2.connection.H2Connection(config=config) 369 c.initiate_connection() 370 c.send_headers(1, self.example_request_headers, end_stream=False) 371 372 f1 = frame_factory.build_headers_frame( 373 self.example_response_headers 374 ) 375 f2 = frame_factory.build_push_promise_frame( 376 stream_id=1, 377 promised_stream_id=2, 378 headers=self.example_request_headers, 379 flags=['END_HEADERS'], 380 ) 381 f3 = frame_factory.build_headers_frame( 382 self.example_response_headers, 383 stream_id=2, 384 ) 385 data = b''.join(x.serialize() for x in [f1, f2, f3]) 386 387 events = c.receive_data(data) 388 389 assert len(events) == 3 390 stream_push_event = events[1] 391 response_event = events[2] 392 assert isinstance(stream_push_event, h2.events.PushedStreamReceived) 393 assert isinstance(response_event, h2.events.ResponseReceived) 394 395 assert stream_push_event.pushed_stream_id == 2 396 assert stream_push_event.parent_stream_id == 1 397 assert ( 398 stream_push_event.headers == self.example_request_headers 399 ) 400 assert response_event.stream_id == 2 401 assert response_event.headers == self.example_response_headers 402 403 def test_receiving_pushed_stream_bytes(self, frame_factory): 404 """ 405 Pushed headers are not decoded if the header encoding is set to False. 406 """ 407 config = h2.config.H2Configuration(header_encoding=False) 408 c = h2.connection.H2Connection(config=config) 409 c.initiate_connection() 410 c.send_headers(1, self.example_request_headers, end_stream=False) 411 412 f1 = frame_factory.build_headers_frame( 413 self.example_response_headers 414 ) 415 f2 = frame_factory.build_push_promise_frame( 416 stream_id=1, 417 promised_stream_id=2, 418 headers=self.example_request_headers, 419 flags=['END_HEADERS'], 420 ) 421 f3 = frame_factory.build_headers_frame( 422 self.example_response_headers, 423 stream_id=2, 424 ) 425 data = b''.join(x.serialize() for x in [f1, f2, f3]) 426 427 events = c.receive_data(data) 428 429 assert len(events) == 3 430 stream_push_event = events[1] 431 response_event = events[2] 432 assert isinstance(stream_push_event, h2.events.PushedStreamReceived) 433 assert isinstance(response_event, h2.events.ResponseReceived) 434 435 assert stream_push_event.pushed_stream_id == 2 436 assert stream_push_event.parent_stream_id == 1 437 assert ( 438 stream_push_event.headers == self.bytes_example_request_headers 439 ) 440 assert response_event.stream_id == 2 441 assert response_event.headers == self.bytes_example_response_headers 442 443 def test_cannot_receive_pushed_stream_when_enable_push_is_0(self, 444 frame_factory): 445 """ 446 If we have set SETTINGS_ENABLE_PUSH to 0, receiving PUSH_PROMISE frames 447 triggers the connection to be closed. 448 """ 449 c = h2.connection.H2Connection() 450 c.initiate_connection() 451 c.local_settings.enable_push = 0 452 c.send_headers(1, self.example_request_headers, end_stream=False) 453 454 f1 = frame_factory.build_settings_frame({}, ack=True) 455 f2 = frame_factory.build_headers_frame( 456 self.example_response_headers 457 ) 458 f3 = frame_factory.build_push_promise_frame( 459 stream_id=1, 460 promised_stream_id=2, 461 headers=self.example_request_headers, 462 flags=['END_HEADERS'], 463 ) 464 c.receive_data(f1.serialize()) 465 c.receive_data(f2.serialize()) 466 c.clear_outbound_data_buffer() 467 468 with pytest.raises(h2.exceptions.ProtocolError): 469 c.receive_data(f3.serialize()) 470 471 expected_frame = frame_factory.build_goaway_frame( 472 0, h2.errors.ErrorCodes.PROTOCOL_ERROR 473 ) 474 assert c.data_to_send() == expected_frame.serialize() 475 476 def test_receiving_response_no_body(self, frame_factory): 477 """ 478 Receiving a response without a body fires two events, ResponseReceived 479 and StreamEnded. 480 """ 481 c = h2.connection.H2Connection() 482 c.initiate_connection() 483 c.send_headers(1, self.example_request_headers, end_stream=True) 484 485 f = frame_factory.build_headers_frame( 486 self.example_response_headers, 487 flags=['END_STREAM'] 488 ) 489 events = c.receive_data(f.serialize()) 490 491 assert len(events) == 2 492 response_event = events[0] 493 end_stream = events[1] 494 495 assert isinstance(response_event, h2.events.ResponseReceived) 496 assert isinstance(end_stream, h2.events.StreamEnded) 497 498 def test_oversize_headers(self): 499 """ 500 Sending headers that are oversized generates a stream of CONTINUATION 501 frames. 502 """ 503 all_bytes = [chr(x) for x in range(0, 256)] 504 if IS_PYTHON3: 505 all_bytes = [x.encode('latin1') for x in all_bytes] 506 507 large_binary_string = b''.join( 508 random.choice(all_bytes) for _ in range(0, 256) 509 ) 510 test_headers = [ 511 (':authority', 'example.com'), 512 (':path', '/'), 513 (':method', 'GET'), 514 (':scheme', 'https'), 515 ('key', large_binary_string) 516 ] 517 c = h2.connection.H2Connection() 518 519 # Greatly shrink the max frame size to force us over. 520 c.max_outbound_frame_size = 48 521 c.initiate_connection() 522 c.send_headers(1, test_headers, end_stream=True) 523 524 # Use the frame buffer here, because we don't care about decoding 525 # the headers. Don't send all the data in because that will force the 526 # frame buffer to stop caching the CONTINUATION frames, so instead 527 # send all but one byte. 528 buffer = h2.frame_buffer.FrameBuffer(server=True) 529 buffer.max_frame_size = 65535 530 data = c.data_to_send() 531 buffer.add_data(data[:-1]) 532 533 # Drain the buffer, confirming that it only provides a single frame 534 # (the settings frame) 535 assert len(list(buffer)) == 1 536 537 # Get the cached frames. 538 frames = buffer._headers_buffer 539 540 # Split the frames up. 541 headers_frame = frames[0] 542 continuation_frames = frames[1:] 543 544 assert isinstance(headers_frame, hyperframe.frame.HeadersFrame) 545 assert all( 546 map( 547 lambda f: isinstance(f, hyperframe.frame.ContinuationFrame), 548 continuation_frames) 549 ) 550 assert all( 551 map(lambda f: len(f.data) <= c.max_outbound_frame_size, frames) 552 ) 553 554 assert frames[0].flags == {'END_STREAM'} 555 556 buffer.add_data(data[-1:]) 557 headers = list(buffer)[0] 558 assert isinstance(headers, hyperframe.frame.HeadersFrame) 559 560 def test_handle_stream_reset(self, frame_factory): 561 """ 562 Streams being remotely reset fires a StreamReset event. 563 """ 564 c = h2.connection.H2Connection() 565 c.initiate_connection() 566 c.send_headers(1, self.example_request_headers, end_stream=True) 567 c.clear_outbound_data_buffer() 568 569 f = frame_factory.build_rst_stream_frame( 570 stream_id=1, 571 error_code=h2.errors.ErrorCodes.STREAM_CLOSED, 572 ) 573 events = c.receive_data(f.serialize()) 574 575 assert len(events) == 1 576 event = events[0] 577 578 assert isinstance(event, h2.events.StreamReset) 579 assert event.stream_id == 1 580 assert event.error_code is h2.errors.ErrorCodes.STREAM_CLOSED 581 assert isinstance(event.error_code, h2.errors.ErrorCodes) 582 assert event.remote_reset 583 584 def test_handle_stream_reset_with_unknown_erorr_code(self, frame_factory): 585 """ 586 Streams being remotely reset with unknown error codes behave exactly as 587 they do with known error codes, but the error code on the event is an 588 int, instead of being an ErrorCodes. 589 """ 590 c = h2.connection.H2Connection() 591 c.initiate_connection() 592 c.send_headers(1, self.example_request_headers, end_stream=True) 593 c.clear_outbound_data_buffer() 594 595 f = frame_factory.build_rst_stream_frame(stream_id=1, error_code=0xFA) 596 events = c.receive_data(f.serialize()) 597 598 assert len(events) == 1 599 event = events[0] 600 601 assert isinstance(event, h2.events.StreamReset) 602 assert event.stream_id == 1 603 assert event.error_code == 250 604 assert not isinstance(event.error_code, h2.errors.ErrorCodes) 605 assert event.remote_reset 606 607 def test_can_consume_partial_data_from_connection(self): 608 """ 609 We can do partial reads from the connection. 610 """ 611 c = h2.connection.H2Connection() 612 c.initiate_connection() 613 614 assert len(c.data_to_send(2)) == 2 615 assert len(c.data_to_send(3)) == 3 616 assert 0 < len(c.data_to_send(500)) < 500 617 assert len(c.data_to_send(10)) == 0 618 assert len(c.data_to_send()) == 0 619 620 def test_we_can_update_settings(self, frame_factory): 621 """ 622 Updating the settings emits a SETTINGS frame. 623 """ 624 c = h2.connection.H2Connection() 625 c.initiate_connection() 626 c.clear_outbound_data_buffer() 627 628 new_settings = { 629 h2.settings.SettingCodes.HEADER_TABLE_SIZE: 52, 630 h2.settings.SettingCodes.ENABLE_PUSH: 0, 631 } 632 events = c.update_settings(new_settings) 633 assert not events 634 635 f = frame_factory.build_settings_frame(new_settings) 636 assert c.data_to_send() == f.serialize() 637 638 def test_settings_get_acked_correctly(self, frame_factory): 639 """ 640 When settings changes are ACKed, they contain the changed settings. 641 """ 642 c = h2.connection.H2Connection() 643 c.initiate_connection() 644 645 new_settings = { 646 h2.settings.SettingCodes.HEADER_TABLE_SIZE: 52, 647 h2.settings.SettingCodes.ENABLE_PUSH: 0, 648 } 649 c.update_settings(new_settings) 650 651 f = frame_factory.build_settings_frame({}, ack=True) 652 events = c.receive_data(f.serialize()) 653 654 assert len(events) == 1 655 event = events[0] 656 657 assert isinstance(event, h2.events.SettingsAcknowledged) 658 assert len(event.changed_settings) == len(new_settings) 659 for setting, value in new_settings.items(): 660 assert event.changed_settings[setting].new_value == value 661 662 def test_cannot_create_new_outbound_stream_over_limit(self, frame_factory): 663 """ 664 When the number of outbound streams exceeds the remote peer's 665 MAX_CONCURRENT_STREAMS setting, attempting to open new streams fails. 666 """ 667 c = h2.connection.H2Connection() 668 c.initiate_connection() 669 670 f = frame_factory.build_settings_frame( 671 {h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS: 1} 672 ) 673 c.receive_data(f.serialize())[0] 674 675 c.send_headers(1, self.example_request_headers) 676 677 with pytest.raises(h2.exceptions.TooManyStreamsError): 678 c.send_headers(3, self.example_request_headers) 679 680 def test_can_receive_trailers(self, frame_factory): 681 """ 682 When two HEADERS blocks are received in the same stream from a 683 server, the second set are trailers. 684 """ 685 config = h2.config.H2Configuration(header_encoding='utf-8') 686 c = h2.connection.H2Connection(config=config) 687 c.initiate_connection() 688 c.send_headers(1, self.example_request_headers) 689 f = frame_factory.build_headers_frame(self.example_response_headers) 690 c.receive_data(f.serialize()) 691 692 # Send in trailers. 693 trailers = [('content-length', '0')] 694 f = frame_factory.build_headers_frame( 695 trailers, 696 flags=['END_STREAM'], 697 ) 698 events = c.receive_data(f.serialize()) 699 assert len(events) == 2 700 701 event = events[0] 702 assert isinstance(event, h2.events.TrailersReceived) 703 assert event.headers == trailers 704 assert event.stream_id == 1 705 706 def test_reject_trailers_not_ending_stream(self, frame_factory): 707 """ 708 When trailers are received without the END_STREAM flag being present, 709 this is a ProtocolError. 710 """ 711 c = h2.connection.H2Connection() 712 c.initiate_connection() 713 c.send_headers(1, self.example_request_headers) 714 f = frame_factory.build_headers_frame(self.example_response_headers) 715 c.receive_data(f.serialize()) 716 717 # Send in trailers. 718 c.clear_outbound_data_buffer() 719 trailers = [('content-length', '0')] 720 f = frame_factory.build_headers_frame( 721 trailers, 722 flags=[], 723 ) 724 725 with pytest.raises(h2.exceptions.ProtocolError): 726 c.receive_data(f.serialize()) 727 728 expected_frame = frame_factory.build_goaway_frame( 729 last_stream_id=0, error_code=h2.errors.ErrorCodes.PROTOCOL_ERROR, 730 ) 731 assert c.data_to_send() == expected_frame.serialize() 732 733 def test_can_send_trailers(self, frame_factory): 734 """ 735 When a second set of headers are sent, they are properly trailers. 736 """ 737 c = h2.connection.H2Connection() 738 c.initiate_connection() 739 c.clear_outbound_data_buffer() 740 c.send_headers(1, self.example_request_headers) 741 742 # Now send trailers. 743 trailers = [('content-length', '0')] 744 c.send_headers(1, trailers, end_stream=True) 745 746 frame_factory.refresh_encoder() 747 f1 = frame_factory.build_headers_frame( 748 self.example_request_headers, 749 ) 750 f2 = frame_factory.build_headers_frame( 751 trailers, 752 flags=['END_STREAM'], 753 ) 754 assert c.data_to_send() == f1.serialize() + f2.serialize() 755 756 def test_trailers_must_have_end_stream(self, frame_factory): 757 """ 758 A set of trailers must carry the END_STREAM flag. 759 """ 760 c = h2.connection.H2Connection() 761 c.initiate_connection() 762 763 # Send headers. 764 c.send_headers(1, self.example_request_headers) 765 766 # Now send trailers. 767 trailers = [('content-length', '0')] 768 769 with pytest.raises(h2.exceptions.ProtocolError): 770 c.send_headers(1, trailers) 771 772 def test_headers_are_lowercase(self, frame_factory): 773 """ 774 When headers are sent, they are forced to lower-case. 775 """ 776 weird_headers = self.example_request_headers + [ 777 ('ChAnGiNg-CaSe', 'AlsoHere'), 778 ('alllowercase', 'alllowercase'), 779 ('ALLCAPS', 'ALLCAPS'), 780 ] 781 expected_headers = self.example_request_headers + [ 782 ('changing-case', 'AlsoHere'), 783 ('alllowercase', 'alllowercase'), 784 ('allcaps', 'ALLCAPS'), 785 ] 786 787 c = h2.connection.H2Connection() 788 c.initiate_connection() 789 c.clear_outbound_data_buffer() 790 791 c.send_headers(1, weird_headers) 792 expected_frame = frame_factory.build_headers_frame( 793 headers=expected_headers 794 ) 795 796 assert c.data_to_send() == expected_frame.serialize() 797 798 @given(frame_size=integers(min_value=2**14, max_value=(2**24 - 1))) 799 def test_changing_max_frame_size(self, frame_factory, frame_size): 800 """ 801 When the user changes the max frame size and the change is ACKed, the 802 remote peer is now bound by the new frame size. 803 """ 804 # We need to refresh the encoder because hypothesis has a problem with 805 # integrating with py.test, meaning that we use the same frame factory 806 # for all tests. 807 # See https://github.com/HypothesisWorks/hypothesis-python/issues/377 808 frame_factory.refresh_encoder() 809 810 c = h2.connection.H2Connection() 811 c.initiate_connection() 812 813 # Set up the stream. 814 c.send_headers(1, self.example_request_headers, end_stream=True) 815 headers_frame = frame_factory.build_headers_frame( 816 headers=self.example_response_headers, 817 ) 818 c.receive_data(headers_frame.serialize()) 819 820 # Change the max frame size. 821 c.update_settings( 822 {h2.settings.SettingCodes.MAX_FRAME_SIZE: frame_size} 823 ) 824 settings_ack = frame_factory.build_settings_frame({}, ack=True) 825 c.receive_data(settings_ack.serialize()) 826 827 # Greatly increase the flow control windows: we're not here to test 828 # flow control today. 829 c.increment_flow_control_window(increment=(2 * frame_size) + 1) 830 c.increment_flow_control_window( 831 increment=(2 * frame_size) + 1, stream_id=1 832 ) 833 834 # Send one DATA frame that is exactly the max frame size: confirm it's 835 # fine. 836 data = frame_factory.build_data_frame( 837 data=(b'\x00' * frame_size), 838 ) 839 events = c.receive_data(data.serialize()) 840 assert len(events) == 1 841 assert isinstance(events[0], h2.events.DataReceived) 842 assert events[0].flow_controlled_length == frame_size 843 844 # Send one that is one byte too large: confirm a protocol error is 845 # raised. 846 data.data += b'\x00' 847 with pytest.raises(h2.exceptions.ProtocolError): 848 c.receive_data(data.serialize()) 849 850 def test_cookies_are_joined_on_push(self, frame_factory): 851 """ 852 RFC 7540 Section 8.1.2.5 requires that we join multiple Cookie headers 853 in a header block together when they're received on a push. 854 """ 855 # This is a moderately varied set of cookie headers: some combined, 856 # some split. 857 cookie_headers = [ 858 ('cookie', 859 'username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC'), 860 ('cookie', 'path=1'), 861 ('cookie', 'test1=val1; test2=val2') 862 ] 863 expected = ( 864 'username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC; ' 865 'path=1; test1=val1; test2=val2' 866 ) 867 868 config = h2.config.H2Configuration(header_encoding='utf-8') 869 c = h2.connection.H2Connection(config=config) 870 c.initiate_connection() 871 c.send_headers(1, self.example_request_headers, end_stream=True) 872 873 f = frame_factory.build_push_promise_frame( 874 stream_id=1, 875 promised_stream_id=2, 876 headers=self.example_request_headers + cookie_headers 877 ) 878 events = c.receive_data(f.serialize()) 879 880 assert len(events) == 1 881 e = events[0] 882 883 cookie_fields = [(n, v) for n, v in e.headers if n == 'cookie'] 884 assert len(cookie_fields) == 1 885 886 _, v = cookie_fields[0] 887 assert v == expected 888 889 def test_cookies_arent_joined_without_normalization(self, frame_factory): 890 """ 891 If inbound header normalization is disabled, cookie headers aren't 892 joined. 893 """ 894 # This is a moderately varied set of cookie headers: some combined, 895 # some split. 896 cookie_headers = [ 897 ('cookie', 898 'username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC'), 899 ('cookie', 'path=1'), 900 ('cookie', 'test1=val1; test2=val2') 901 ] 902 903 config = h2.config.H2Configuration( 904 client_side=True, 905 normalize_inbound_headers=False, 906 header_encoding='utf-8' 907 ) 908 c = h2.connection.H2Connection(config=config) 909 c.initiate_connection() 910 c.send_headers(1, self.example_request_headers, end_stream=True) 911 912 f = frame_factory.build_push_promise_frame( 913 stream_id=1, 914 promised_stream_id=2, 915 headers=self.example_request_headers + cookie_headers 916 ) 917 events = c.receive_data(f.serialize()) 918 919 assert len(events) == 1 920 e = events[0] 921 922 received_cookies = [(n, v) for n, v in e.headers if n == 'cookie'] 923 assert len(received_cookies) == 3 924 assert cookie_headers == received_cookies 925 926 927class TestBasicServer(object): 928 """ 929 Basic server-side tests. 930 """ 931 example_request_headers = [ 932 (u':authority', u'example.com'), 933 (u':path', u'/'), 934 (u':scheme', u'https'), 935 (u':method', u'GET'), 936 ] 937 bytes_example_request_headers = [ 938 (b':authority', b'example.com'), 939 (b':path', b'/'), 940 (b':scheme', b'https'), 941 (b':method', b'GET'), 942 ] 943 example_response_headers = [ 944 (':status', '200'), 945 ('server', 'hyper-h2/0.1.0') 946 ] 947 server_config = h2.config.H2Configuration( 948 client_side=False, header_encoding='utf-8' 949 ) 950 951 def test_ignores_preamble(self): 952 """ 953 The preamble does not cause any events or frames to be written. 954 """ 955 c = h2.connection.H2Connection(config=self.server_config) 956 preamble = b'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n' 957 958 events = c.receive_data(preamble) 959 assert not events 960 assert not c.data_to_send() 961 962 @pytest.mark.parametrize("chunk_size", range(1, 24)) 963 def test_drip_feed_preamble(self, chunk_size): 964 """ 965 The preamble can be sent in in less than a single buffer. 966 """ 967 c = h2.connection.H2Connection(config=self.server_config) 968 preamble = b'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n' 969 events = [] 970 971 for i in range(0, len(preamble), chunk_size): 972 events += c.receive_data(preamble[i:i+chunk_size]) 973 974 assert not events 975 assert not c.data_to_send() 976 977 def test_initiate_connection_sends_server_preamble(self, frame_factory): 978 """ 979 For server-side connections, initiate_connection sends a server 980 preamble. 981 """ 982 c = h2.connection.H2Connection(config=self.server_config) 983 expected_settings = frame_factory.build_settings_frame( 984 c.local_settings 985 ) 986 expected_data = expected_settings.serialize() 987 988 events = c.initiate_connection() 989 assert not events 990 assert c.data_to_send() == expected_data 991 992 def test_headers_event(self, frame_factory): 993 """ 994 When a headers frame is received a RequestReceived event fires. 995 """ 996 c = h2.connection.H2Connection(config=self.server_config) 997 c.receive_data(frame_factory.preamble()) 998 999 f = frame_factory.build_headers_frame(self.example_request_headers) 1000 data = f.serialize() 1001 events = c.receive_data(data) 1002 1003 assert len(events) == 1 1004 event = events[0] 1005 1006 assert isinstance(event, h2.events.RequestReceived) 1007 assert event.stream_id == 1 1008 assert event.headers == self.example_request_headers 1009 1010 def test_headers_event_bytes(self, frame_factory): 1011 """ 1012 When a headers frame is received a RequestReceived event fires with 1013 bytes headers if the encoding is set appropriately. 1014 """ 1015 config = h2.config.H2Configuration( 1016 client_side=False, header_encoding=False 1017 ) 1018 c = h2.connection.H2Connection(config=config) 1019 c.receive_data(frame_factory.preamble()) 1020 1021 f = frame_factory.build_headers_frame(self.example_request_headers) 1022 data = f.serialize() 1023 events = c.receive_data(data) 1024 1025 assert len(events) == 1 1026 event = events[0] 1027 1028 assert isinstance(event, h2.events.RequestReceived) 1029 assert event.stream_id == 1 1030 assert event.headers == self.bytes_example_request_headers 1031 1032 def test_data_event(self, frame_factory): 1033 """ 1034 Test that data received on a stream fires a DataReceived event. 1035 """ 1036 c = h2.connection.H2Connection(config=self.server_config) 1037 c.receive_data(frame_factory.preamble()) 1038 1039 f1 = frame_factory.build_headers_frame( 1040 self.example_request_headers, stream_id=3 1041 ) 1042 f2 = frame_factory.build_data_frame( 1043 b'some request data', 1044 stream_id=3, 1045 ) 1046 data = b''.join(map(lambda f: f.serialize(), [f1, f2])) 1047 events = c.receive_data(data) 1048 1049 assert len(events) == 2 1050 event = events[1] 1051 1052 assert isinstance(event, h2.events.DataReceived) 1053 assert event.stream_id == 3 1054 assert event.data == b'some request data' 1055 assert event.flow_controlled_length == 17 1056 1057 def test_data_event_with_padding(self, frame_factory): 1058 """ 1059 Test that data received on a stream fires a DataReceived event that 1060 accounts for padding. 1061 """ 1062 c = h2.connection.H2Connection(config=self.server_config) 1063 c.receive_data(frame_factory.preamble()) 1064 1065 f1 = frame_factory.build_headers_frame( 1066 self.example_request_headers, stream_id=3 1067 ) 1068 f2 = frame_factory.build_data_frame( 1069 b'some request data', 1070 stream_id=3, 1071 padding_len=20 1072 ) 1073 data = b''.join(map(lambda f: f.serialize(), [f1, f2])) 1074 events = c.receive_data(data) 1075 1076 assert len(events) == 2 1077 event = events[1] 1078 1079 assert isinstance(event, h2.events.DataReceived) 1080 assert event.stream_id == 3 1081 assert event.data == b'some request data' 1082 assert event.flow_controlled_length == 17 + 20 + 1 1083 1084 def test_receiving_ping_frame(self, frame_factory): 1085 """ 1086 Ping frames should be immediately ACKed. 1087 """ 1088 c = h2.connection.H2Connection(config=self.server_config) 1089 c.receive_data(frame_factory.preamble()) 1090 1091 ping_data = b'\x01' * 8 1092 sent_frame = frame_factory.build_ping_frame(ping_data) 1093 expected_frame = frame_factory.build_ping_frame( 1094 ping_data, flags=["ACK"] 1095 ) 1096 expected_data = expected_frame.serialize() 1097 1098 c.clear_outbound_data_buffer() 1099 events = c.receive_data(sent_frame.serialize()) 1100 1101 assert len(events) == 1 1102 event = events[0] 1103 1104 assert isinstance(event, h2.events.PingReceived) 1105 assert event.ping_data == ping_data 1106 1107 assert c.data_to_send() == expected_data 1108 1109 def test_receiving_settings_frame_event(self, frame_factory): 1110 """ 1111 Settings frames should cause a RemoteSettingsChanged event to fire. 1112 """ 1113 c = h2.connection.H2Connection(config=self.server_config) 1114 c.receive_data(frame_factory.preamble()) 1115 1116 f = frame_factory.build_settings_frame( 1117 settings=helpers.SAMPLE_SETTINGS 1118 ) 1119 events = c.receive_data(f.serialize()) 1120 1121 assert len(events) == 1 1122 event = events[0] 1123 1124 assert isinstance(event, h2.events.RemoteSettingsChanged) 1125 assert len(event.changed_settings) == len(helpers.SAMPLE_SETTINGS) 1126 1127 def test_acknowledging_settings(self, frame_factory): 1128 """ 1129 Acknowledging settings causes appropriate Settings frame to be emitted. 1130 """ 1131 c = h2.connection.H2Connection(config=self.server_config) 1132 c.receive_data(frame_factory.preamble()) 1133 1134 received_frame = frame_factory.build_settings_frame( 1135 settings=helpers.SAMPLE_SETTINGS 1136 ) 1137 expected_frame = frame_factory.build_settings_frame( 1138 settings={}, ack=True 1139 ) 1140 expected_data = expected_frame.serialize() 1141 1142 c.clear_outbound_data_buffer() 1143 events = c.receive_data(received_frame.serialize()) 1144 1145 assert len(events) == 1 1146 assert c.data_to_send() == expected_data 1147 1148 def test_close_connection(self, frame_factory): 1149 """ 1150 Closing the connection with no error code emits a GOAWAY frame with 1151 error code 0. 1152 """ 1153 c = h2.connection.H2Connection(config=self.server_config) 1154 c.receive_data(frame_factory.preamble()) 1155 f = frame_factory.build_goaway_frame(last_stream_id=0) 1156 expected_data = f.serialize() 1157 1158 c.clear_outbound_data_buffer() 1159 events = c.close_connection() 1160 1161 assert not events 1162 assert c.data_to_send() == expected_data 1163 1164 @pytest.mark.parametrize("error_code", h2.errors.ErrorCodes) 1165 def test_close_connection_with_error_code(self, frame_factory, error_code): 1166 """ 1167 Closing the connection with an error code emits a GOAWAY frame with 1168 that error code. 1169 """ 1170 c = h2.connection.H2Connection(config=self.server_config) 1171 c.receive_data(frame_factory.preamble()) 1172 f = frame_factory.build_goaway_frame( 1173 error_code=error_code, last_stream_id=0 1174 ) 1175 expected_data = f.serialize() 1176 1177 c.clear_outbound_data_buffer() 1178 events = c.close_connection(error_code) 1179 1180 assert not events 1181 assert c.data_to_send() == expected_data 1182 1183 @pytest.mark.parametrize("last_stream_id,output", [ 1184 (None, 23), 1185 (0, 0), 1186 (42, 42) 1187 ]) 1188 def test_close_connection_with_last_stream_id(self, frame_factory, 1189 last_stream_id, output): 1190 """ 1191 Closing the connection with last_stream_id set emits a GOAWAY frame 1192 with that value. 1193 """ 1194 c = h2.connection.H2Connection(config=self.server_config) 1195 c.receive_data(frame_factory.preamble()) 1196 headers_frame = frame_factory.build_headers_frame( 1197 [ 1198 (':authority', 'example.com'), 1199 (':path', '/'), 1200 (':scheme', 'https'), 1201 (':method', 'GET'), 1202 ], 1203 stream_id=23) 1204 c.receive_data(headers_frame.serialize()) 1205 1206 f = frame_factory.build_goaway_frame( 1207 last_stream_id=output 1208 ) 1209 expected_data = f.serialize() 1210 1211 c.clear_outbound_data_buffer() 1212 events = c.close_connection(last_stream_id=last_stream_id) 1213 1214 assert not events 1215 assert c.data_to_send() == expected_data 1216 1217 @pytest.mark.parametrize("additional_data,output", [ 1218 (None, b''), 1219 (b'', b''), 1220 (b'foobar', b'foobar') 1221 ]) 1222 def test_close_connection_with_additional_data(self, frame_factory, 1223 additional_data, output): 1224 """ 1225 Closing the connection with additional debug data emits a GOAWAY frame 1226 with that data attached. 1227 """ 1228 c = h2.connection.H2Connection(config=self.server_config) 1229 c.receive_data(frame_factory.preamble()) 1230 f = frame_factory.build_goaway_frame( 1231 last_stream_id=0, additional_data=output 1232 ) 1233 expected_data = f.serialize() 1234 1235 c.clear_outbound_data_buffer() 1236 events = c.close_connection(additional_data=additional_data) 1237 1238 assert not events 1239 assert c.data_to_send() == expected_data 1240 1241 def test_reset_stream(self, frame_factory): 1242 """ 1243 Resetting a stream with no error code emits a RST_STREAM frame with 1244 error code 0. 1245 """ 1246 c = h2.connection.H2Connection(config=self.server_config) 1247 c.receive_data(frame_factory.preamble()) 1248 f = frame_factory.build_headers_frame(self.example_request_headers) 1249 c.receive_data(f.serialize()) 1250 c.clear_outbound_data_buffer() 1251 1252 expected_frame = frame_factory.build_rst_stream_frame(stream_id=1) 1253 expected_data = expected_frame.serialize() 1254 1255 events = c.reset_stream(stream_id=1) 1256 1257 assert not events 1258 assert c.data_to_send() == expected_data 1259 1260 @pytest.mark.parametrize("error_code", h2.errors.ErrorCodes) 1261 def test_reset_stream_with_error_code(self, frame_factory, error_code): 1262 """ 1263 Resetting a stream with an error code emits a RST_STREAM frame with 1264 that error code. 1265 """ 1266 c = h2.connection.H2Connection(config=self.server_config) 1267 c.receive_data(frame_factory.preamble()) 1268 f = frame_factory.build_headers_frame( 1269 self.example_request_headers, 1270 stream_id=3 1271 ) 1272 c.receive_data(f.serialize()) 1273 c.clear_outbound_data_buffer() 1274 1275 expected_frame = frame_factory.build_rst_stream_frame( 1276 stream_id=3, error_code=error_code 1277 ) 1278 expected_data = expected_frame.serialize() 1279 1280 events = c.reset_stream(stream_id=3, error_code=error_code) 1281 1282 assert not events 1283 assert c.data_to_send() == expected_data 1284 1285 def test_cannot_reset_nonexistent_stream(self, frame_factory): 1286 """ 1287 Resetting nonexistent streams raises NoSuchStreamError. 1288 """ 1289 c = h2.connection.H2Connection(config=self.server_config) 1290 c.receive_data(frame_factory.preamble()) 1291 f = frame_factory.build_headers_frame( 1292 self.example_request_headers, 1293 stream_id=3 1294 ) 1295 c.receive_data(f.serialize()) 1296 1297 with pytest.raises(h2.exceptions.NoSuchStreamError) as e: 1298 c.reset_stream(stream_id=1) 1299 1300 assert e.value.stream_id == 1 1301 1302 with pytest.raises(h2.exceptions.NoSuchStreamError) as e: 1303 c.reset_stream(stream_id=5) 1304 1305 assert e.value.stream_id == 5 1306 1307 def test_basic_sending_ping_frame_logic(self, frame_factory): 1308 """ 1309 Sending ping frames serializes a ping frame on stream 0 with 1310 approriate opaque data. 1311 """ 1312 c = h2.connection.H2Connection(config=self.server_config) 1313 c.receive_data(frame_factory.preamble()) 1314 c.clear_outbound_data_buffer() 1315 1316 ping_data = b'\x01\x02\x03\x04\x05\x06\x07\x08' 1317 1318 expected_frame = frame_factory.build_ping_frame(ping_data) 1319 expected_data = expected_frame.serialize() 1320 1321 events = c.ping(ping_data) 1322 1323 assert not events 1324 assert c.data_to_send() == expected_data 1325 1326 @pytest.mark.parametrize( 1327 'opaque_data', 1328 [ 1329 b'', 1330 b'\x01\x02\x03\x04\x05\x06\x07', 1331 u'abcdefgh', 1332 b'too many bytes', 1333 ] 1334 ) 1335 def test_ping_frame_opaque_data_must_be_length_8_bytestring(self, 1336 frame_factory, 1337 opaque_data): 1338 """ 1339 Sending a ping frame only works with 8-byte bytestrings. 1340 """ 1341 c = h2.connection.H2Connection(config=self.server_config) 1342 c.receive_data(frame_factory.preamble()) 1343 1344 with pytest.raises(ValueError): 1345 c.ping(opaque_data) 1346 1347 def test_receiving_ping_acknowledgement(self, frame_factory): 1348 """ 1349 Receiving a PING acknowledgement fires a PingAckReceived event. 1350 """ 1351 c = h2.connection.H2Connection(config=self.server_config) 1352 c.receive_data(frame_factory.preamble()) 1353 1354 ping_data = b'\x01\x02\x03\x04\x05\x06\x07\x08' 1355 1356 f = frame_factory.build_ping_frame( 1357 ping_data, flags=['ACK'] 1358 ) 1359 events = c.receive_data(f.serialize()) 1360 1361 assert len(events) == 1 1362 event = events[0] 1363 1364 assert isinstance(event, h2.events.PingAckReceived) 1365 assert isinstance(event, h2.events.PingAcknowledged) # deprecated 1366 assert event.ping_data == ping_data 1367 1368 def test_stream_ended_remotely(self, frame_factory): 1369 """ 1370 When the remote stream ends with a non-empty data frame a DataReceived 1371 event and a StreamEnded event are fired. 1372 """ 1373 c = h2.connection.H2Connection(config=self.server_config) 1374 c.receive_data(frame_factory.preamble()) 1375 1376 f1 = frame_factory.build_headers_frame( 1377 self.example_request_headers, stream_id=3 1378 ) 1379 f2 = frame_factory.build_data_frame( 1380 b'some request data', 1381 flags=['END_STREAM'], 1382 stream_id=3, 1383 ) 1384 data = b''.join(map(lambda f: f.serialize(), [f1, f2])) 1385 events = c.receive_data(data) 1386 1387 assert len(events) == 3 1388 data_event = events[1] 1389 stream_ended_event = events[2] 1390 1391 assert isinstance(data_event, h2.events.DataReceived) 1392 assert isinstance(stream_ended_event, h2.events.StreamEnded) 1393 stream_ended_event.stream_id == 3 1394 1395 def test_can_push_stream(self, frame_factory): 1396 """ 1397 Pushing a stream causes a PUSH_PROMISE frame to be emitted. 1398 """ 1399 c = h2.connection.H2Connection(config=self.server_config) 1400 c.receive_data(frame_factory.preamble()) 1401 f = frame_factory.build_headers_frame( 1402 self.example_request_headers 1403 ) 1404 c.receive_data(f.serialize()) 1405 1406 frame_factory.refresh_encoder() 1407 expected_frame = frame_factory.build_push_promise_frame( 1408 stream_id=1, 1409 promised_stream_id=2, 1410 headers=self.example_request_headers, 1411 flags=['END_HEADERS'], 1412 ) 1413 1414 c.clear_outbound_data_buffer() 1415 c.push_stream( 1416 stream_id=1, 1417 promised_stream_id=2, 1418 request_headers=self.example_request_headers 1419 ) 1420 1421 assert c.data_to_send() == expected_frame.serialize() 1422 1423 def test_cannot_push_streams_when_disabled(self, frame_factory): 1424 """ 1425 When the remote peer has disabled stream pushing, we should fail. 1426 """ 1427 c = h2.connection.H2Connection(config=self.server_config) 1428 c.receive_data(frame_factory.preamble()) 1429 f = frame_factory.build_settings_frame( 1430 {h2.settings.SettingCodes.ENABLE_PUSH: 0} 1431 ) 1432 c.receive_data(f.serialize()) 1433 1434 f = frame_factory.build_headers_frame( 1435 self.example_request_headers 1436 ) 1437 c.receive_data(f.serialize()) 1438 1439 with pytest.raises(h2.exceptions.ProtocolError): 1440 c.push_stream( 1441 stream_id=1, 1442 promised_stream_id=2, 1443 request_headers=self.example_request_headers 1444 ) 1445 1446 def test_settings_remote_change_header_table_size(self, frame_factory): 1447 """ 1448 Acknowledging a remote HEADER_TABLE_SIZE settings change causes us to 1449 change the header table size of our encoder. 1450 """ 1451 c = h2.connection.H2Connection(config=self.server_config) 1452 c.receive_data(frame_factory.preamble()) 1453 1454 assert c.encoder.header_table_size == 4096 1455 1456 received_frame = frame_factory.build_settings_frame( 1457 {h2.settings.SettingCodes.HEADER_TABLE_SIZE: 80} 1458 ) 1459 c.receive_data(received_frame.serialize())[0] 1460 1461 assert c.encoder.header_table_size == 80 1462 1463 def test_settings_local_change_header_table_size(self, frame_factory): 1464 """ 1465 The remote peer acknowledging a local HEADER_TABLE_SIZE settings change 1466 does not cause us to change the header table size of our decoder. 1467 1468 For an explanation of why this test is this way around, see issue #37. 1469 """ 1470 c = h2.connection.H2Connection(config=self.server_config) 1471 c.receive_data(frame_factory.preamble()) 1472 1473 assert c.decoder.header_table_size == 4096 1474 1475 expected_frame = frame_factory.build_settings_frame({}, ack=True) 1476 c.update_settings( 1477 {h2.settings.SettingCodes.HEADER_TABLE_SIZE: 80} 1478 ) 1479 c.receive_data(expected_frame.serialize()) 1480 c.clear_outbound_data_buffer() 1481 1482 assert c.decoder.header_table_size == 4096 1483 1484 def test_restricting_outbound_frame_size_by_settings(self, frame_factory): 1485 """ 1486 The remote peer can shrink the maximum outbound frame size using 1487 settings. 1488 """ 1489 c = h2.connection.H2Connection(config=self.server_config) 1490 c.initiate_connection() 1491 c.receive_data(frame_factory.preamble()) 1492 1493 f = frame_factory.build_headers_frame(self.example_request_headers) 1494 c.receive_data(f.serialize()) 1495 c.clear_outbound_data_buffer() 1496 1497 with pytest.raises(h2.exceptions.FrameTooLargeError): 1498 c.send_data(1, b'\x01' * 17000) 1499 1500 received_frame = frame_factory.build_settings_frame( 1501 {h2.settings.SettingCodes.MAX_FRAME_SIZE: 17001} 1502 ) 1503 c.receive_data(received_frame.serialize()) 1504 1505 c.send_data(1, b'\x01' * 17000) 1506 assert c.data_to_send() 1507 1508 def test_restricting_inbound_frame_size_by_settings(self, frame_factory): 1509 """ 1510 We throw ProtocolErrors and tear down connections if oversize frames 1511 are received. 1512 """ 1513 c = h2.connection.H2Connection(config=self.server_config) 1514 c.receive_data(frame_factory.preamble()) 1515 h = frame_factory.build_headers_frame(self.example_request_headers) 1516 c.receive_data(h.serialize()) 1517 c.clear_outbound_data_buffer() 1518 1519 data_frame = frame_factory.build_data_frame(b'\x01' * 17000) 1520 1521 with pytest.raises(h2.exceptions.ProtocolError): 1522 c.receive_data(data_frame.serialize()) 1523 1524 expected_frame = frame_factory.build_goaway_frame( 1525 last_stream_id=1, error_code=h2.errors.ErrorCodes.FRAME_SIZE_ERROR 1526 ) 1527 assert c.data_to_send() == expected_frame.serialize() 1528 1529 def test_cannot_receive_new_streams_over_limit(self, frame_factory): 1530 """ 1531 When the number of inbound streams exceeds our MAX_CONCURRENT_STREAMS 1532 setting, their attempt to open new streams fails. 1533 """ 1534 c = h2.connection.H2Connection(config=self.server_config) 1535 c.receive_data(frame_factory.preamble()) 1536 c.update_settings( 1537 {h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS: 1} 1538 ) 1539 f = frame_factory.build_settings_frame({}, ack=True) 1540 c.receive_data(f.serialize()) 1541 1542 f = frame_factory.build_headers_frame( 1543 stream_id=1, 1544 headers=self.example_request_headers, 1545 ) 1546 c.receive_data(f.serialize()) 1547 c.clear_outbound_data_buffer() 1548 1549 f = frame_factory.build_headers_frame( 1550 stream_id=3, 1551 headers=self.example_request_headers, 1552 ) 1553 with pytest.raises(h2.exceptions.TooManyStreamsError): 1554 c.receive_data(f.serialize()) 1555 1556 expected_frame = frame_factory.build_goaway_frame( 1557 last_stream_id=1, error_code=h2.errors.ErrorCodes.PROTOCOL_ERROR, 1558 ) 1559 assert c.data_to_send() == expected_frame.serialize() 1560 1561 def test_can_receive_trailers(self, frame_factory): 1562 """ 1563 When two HEADERS blocks are received in the same stream from a 1564 client, the second set are trailers. 1565 """ 1566 c = h2.connection.H2Connection(config=self.server_config) 1567 c.receive_data(frame_factory.preamble()) 1568 f = frame_factory.build_headers_frame(self.example_request_headers) 1569 c.receive_data(f.serialize()) 1570 1571 # Send in trailers. 1572 trailers = [('content-length', '0')] 1573 f = frame_factory.build_headers_frame( 1574 trailers, 1575 flags=['END_STREAM'], 1576 ) 1577 events = c.receive_data(f.serialize()) 1578 assert len(events) == 2 1579 1580 event = events[0] 1581 assert isinstance(event, h2.events.TrailersReceived) 1582 assert event.headers == trailers 1583 assert event.stream_id == 1 1584 1585 def test_reject_trailers_not_ending_stream(self, frame_factory): 1586 """ 1587 When trailers are received without the END_STREAM flag being present, 1588 this is a ProtocolError. 1589 """ 1590 c = h2.connection.H2Connection(config=self.server_config) 1591 c.receive_data(frame_factory.preamble()) 1592 f = frame_factory.build_headers_frame(self.example_request_headers) 1593 c.receive_data(f.serialize()) 1594 1595 # Send in trailers. 1596 c.clear_outbound_data_buffer() 1597 trailers = [('content-length', '0')] 1598 f = frame_factory.build_headers_frame( 1599 trailers, 1600 flags=[], 1601 ) 1602 1603 with pytest.raises(h2.exceptions.ProtocolError): 1604 c.receive_data(f.serialize()) 1605 1606 expected_frame = frame_factory.build_goaway_frame( 1607 last_stream_id=1, error_code=h2.errors.ErrorCodes.PROTOCOL_ERROR, 1608 ) 1609 assert c.data_to_send() == expected_frame.serialize() 1610 1611 def test_can_send_trailers(self, frame_factory): 1612 """ 1613 When a second set of headers are sent, they are properly trailers. 1614 """ 1615 c = h2.connection.H2Connection(config=self.server_config) 1616 c.receive_data(frame_factory.preamble()) 1617 f = frame_factory.build_headers_frame(self.example_request_headers) 1618 c.receive_data(f.serialize()) 1619 1620 # Send headers. 1621 c.clear_outbound_data_buffer() 1622 c.send_headers(1, self.example_response_headers) 1623 1624 # Now send trailers. 1625 trailers = [('content-length', '0')] 1626 c.send_headers(1, trailers, end_stream=True) 1627 1628 frame_factory.refresh_encoder() 1629 f1 = frame_factory.build_headers_frame( 1630 self.example_response_headers, 1631 ) 1632 f2 = frame_factory.build_headers_frame( 1633 trailers, 1634 flags=['END_STREAM'], 1635 ) 1636 assert c.data_to_send() == f1.serialize() + f2.serialize() 1637 1638 def test_trailers_must_have_end_stream(self, frame_factory): 1639 """ 1640 A set of trailers must carry the END_STREAM flag. 1641 """ 1642 c = h2.connection.H2Connection(config=self.server_config) 1643 c.receive_data(frame_factory.preamble()) 1644 f = frame_factory.build_headers_frame(self.example_request_headers) 1645 c.receive_data(f.serialize()) 1646 1647 # Send headers. 1648 c.send_headers(1, self.example_response_headers) 1649 1650 # Now send trailers. 1651 trailers = [('content-length', '0')] 1652 1653 with pytest.raises(h2.exceptions.ProtocolError): 1654 c.send_headers(1, trailers) 1655 1656 @pytest.mark.parametrize("frame_id", range(12, 256)) 1657 def test_unknown_frames_are_ignored(self, frame_factory, frame_id): 1658 c = h2.connection.H2Connection(config=self.server_config) 1659 c.receive_data(frame_factory.preamble()) 1660 c.clear_outbound_data_buffer() 1661 1662 f = frame_factory.build_data_frame(data=b'abcdefghtdst') 1663 f.type = frame_id 1664 1665 events = c.receive_data(f.serialize()) 1666 assert not c.data_to_send() 1667 assert len(events) == 1 1668 assert isinstance(events[0], h2.events.UnknownFrameReceived) 1669 assert isinstance(events[0].frame, hyperframe.frame.ExtensionFrame) 1670 1671 def test_can_send_goaway_repeatedly(self, frame_factory): 1672 """ 1673 We can send a GOAWAY frame as many times as we like. 1674 """ 1675 c = h2.connection.H2Connection(config=self.server_config) 1676 c.receive_data(frame_factory.preamble()) 1677 c.clear_outbound_data_buffer() 1678 1679 c.close_connection() 1680 c.close_connection() 1681 c.close_connection() 1682 1683 f = frame_factory.build_goaway_frame(last_stream_id=0) 1684 1685 assert c.data_to_send() == (f.serialize() * 3) 1686 1687 def test_receiving_goaway_frame(self, frame_factory): 1688 """ 1689 Receiving a GOAWAY frame causes a ConnectionTerminated event to be 1690 fired and transitions the connection to the CLOSED state, and clears 1691 the outbound data buffer. 1692 """ 1693 c = h2.connection.H2Connection(config=self.server_config) 1694 c.initiate_connection() 1695 c.receive_data(frame_factory.preamble()) 1696 1697 f = frame_factory.build_goaway_frame( 1698 last_stream_id=5, error_code=h2.errors.ErrorCodes.SETTINGS_TIMEOUT 1699 ) 1700 events = c.receive_data(f.serialize()) 1701 1702 assert len(events) == 1 1703 event = events[0] 1704 1705 assert isinstance(event, h2.events.ConnectionTerminated) 1706 assert event.error_code == h2.errors.ErrorCodes.SETTINGS_TIMEOUT 1707 assert isinstance(event.error_code, h2.errors.ErrorCodes) 1708 assert event.last_stream_id == 5 1709 assert event.additional_data is None 1710 assert c.state_machine.state == h2.connection.ConnectionState.CLOSED 1711 1712 assert not c.data_to_send() 1713 1714 def test_receiving_multiple_goaway_frames(self, frame_factory): 1715 """ 1716 Multiple GOAWAY frames can be received at once, and are allowed. Each 1717 one fires a ConnectionTerminated event. 1718 """ 1719 c = h2.connection.H2Connection(config=self.server_config) 1720 c.receive_data(frame_factory.preamble()) 1721 c.clear_outbound_data_buffer() 1722 1723 f = frame_factory.build_goaway_frame(last_stream_id=0) 1724 events = c.receive_data(f.serialize() * 3) 1725 1726 assert len(events) == 3 1727 assert all( 1728 isinstance(event, h2.events.ConnectionTerminated) 1729 for event in events 1730 ) 1731 1732 def test_receiving_goaway_frame_with_additional_data(self, frame_factory): 1733 """ 1734 GOAWAY frame can contain additional data, 1735 it should be available via ConnectionTerminated event. 1736 """ 1737 c = h2.connection.H2Connection(config=self.server_config) 1738 c.initiate_connection() 1739 c.receive_data(frame_factory.preamble()) 1740 1741 additional_data = b'debug data' 1742 f = frame_factory.build_goaway_frame(last_stream_id=0, 1743 additional_data=additional_data) 1744 events = c.receive_data(f.serialize()) 1745 1746 assert len(events) == 1 1747 event = events[0] 1748 1749 assert isinstance(event, h2.events.ConnectionTerminated) 1750 assert event.additional_data == additional_data 1751 1752 def test_receiving_goaway_frame_with_unknown_error(self, frame_factory): 1753 """ 1754 Receiving a GOAWAY frame with an unknown error code behaves exactly the 1755 same as receiving one we know about, but the code is reported as an 1756 integer instead of as an ErrorCodes. 1757 """ 1758 c = h2.connection.H2Connection(config=self.server_config) 1759 c.initiate_connection() 1760 c.receive_data(frame_factory.preamble()) 1761 1762 f = frame_factory.build_goaway_frame( 1763 last_stream_id=5, error_code=0xFA 1764 ) 1765 events = c.receive_data(f.serialize()) 1766 1767 assert len(events) == 1 1768 event = events[0] 1769 1770 assert isinstance(event, h2.events.ConnectionTerminated) 1771 assert event.error_code == 250 1772 assert not isinstance(event.error_code, h2.errors.ErrorCodes) 1773 assert event.last_stream_id == 5 1774 assert event.additional_data is None 1775 assert c.state_machine.state == h2.connection.ConnectionState.CLOSED 1776 1777 assert not c.data_to_send() 1778 1779 def test_cookies_are_joined(self, frame_factory): 1780 """ 1781 RFC 7540 Section 8.1.2.5 requires that we join multiple Cookie headers 1782 in a header block together. 1783 """ 1784 # This is a moderately varied set of cookie headers: some combined, 1785 # some split. 1786 cookie_headers = [ 1787 ('cookie', 1788 'username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC'), 1789 ('cookie', 'path=1'), 1790 ('cookie', 'test1=val1; test2=val2') 1791 ] 1792 expected = ( 1793 'username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC; ' 1794 'path=1; test1=val1; test2=val2' 1795 ) 1796 1797 c = h2.connection.H2Connection(config=self.server_config) 1798 c.initiate_connection() 1799 c.receive_data(frame_factory.preamble()) 1800 1801 f = frame_factory.build_headers_frame( 1802 self.example_request_headers + cookie_headers 1803 ) 1804 events = c.receive_data(f.serialize()) 1805 1806 assert len(events) == 1 1807 e = events[0] 1808 1809 cookie_fields = [(n, v) for n, v in e.headers if n == 'cookie'] 1810 assert len(cookie_fields) == 1 1811 1812 _, v = cookie_fields[0] 1813 assert v == expected 1814 1815 def test_cookies_arent_joined_without_normalization(self, frame_factory): 1816 """ 1817 If inbound header normalization is disabled, cookie headers aren't 1818 joined. 1819 """ 1820 # This is a moderately varied set of cookie headers: some combined, 1821 # some split. 1822 cookie_headers = [ 1823 ('cookie', 1824 'username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC'), 1825 ('cookie', 'path=1'), 1826 ('cookie', 'test1=val1; test2=val2') 1827 ] 1828 1829 config = h2.config.H2Configuration( 1830 client_side=False, 1831 normalize_inbound_headers=False, 1832 header_encoding='utf-8' 1833 ) 1834 c = h2.connection.H2Connection(config=config) 1835 c.initiate_connection() 1836 c.receive_data(frame_factory.preamble()) 1837 1838 f = frame_factory.build_headers_frame( 1839 self.example_request_headers + cookie_headers 1840 ) 1841 events = c.receive_data(f.serialize()) 1842 1843 assert len(events) == 1 1844 e = events[0] 1845 1846 received_cookies = [(n, v) for n, v in e.headers if n == 'cookie'] 1847 assert len(received_cookies) == 3 1848 assert cookie_headers == received_cookies 1849 1850 def test_stream_repr(self): 1851 """ 1852 Ensure stream string representation is appropriate. 1853 """ 1854 s = h2.stream.H2Stream(4, None, 12, 14) 1855 assert repr(s) == "<H2Stream id:4 state:<StreamState.IDLE: 0>>" 1856 1857 1858def sanity_check_data_frame(data_frame, 1859 expected_flow_controlled_length, 1860 expect_padded_flag, 1861 expected_data_frame_pad_length): 1862 """ 1863 ``data_frame`` is a frame of type ``hyperframe.frame.DataFrame``, 1864 and the ``flags`` and ``flow_controlled_length`` of ``data_frame`` 1865 match expectations. 1866 """ 1867 1868 assert isinstance(data_frame, hyperframe.frame.DataFrame) 1869 1870 assert data_frame.flow_controlled_length == expected_flow_controlled_length 1871 1872 if expect_padded_flag: 1873 assert 'PADDED' in data_frame.flags 1874 else: 1875 assert 'PADDED' not in data_frame.flags 1876 1877 assert data_frame.pad_length == expected_data_frame_pad_length 1878