protocol-http1 0.37.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/protocol/http1/connection.rb +59 -49
- data/lib/protocol/http1/error.rb +1 -1
- data/lib/protocol/http1/version.rb +2 -2
- data/readme.md +8 -8
- data/releases.md +8 -0
- data.tar.gz.sig +0 -0
- metadata +5 -5
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9b20437da24d1840f9eba2a6cd768d224b1279856db05b08d4dac174cc36d26f
|
|
4
|
+
data.tar.gz: 1a0651bae0777c40bfbfee99b617492010e3c01e96c7fd7242f2a519d04c37d9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a22e2a5e9cf67e34e6577f1ec76c2be8a4b471f89bbeb01544e8bf9cfb2f5e1ed3b548d34b72af6b4769370f16a9f266d2a857d2196cba95a86fad2bc47ee3fe
|
|
7
|
+
data.tar.gz: c9fe0c68fa411bacdb8219af302d5b3d042f8bf763e83936561dedce2a0a31136ad442188084d0830fb563fa4ec057c97dd9bdca64e80826ba17331fa5e472ff
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
|
-
# Copyright, 2019-
|
|
4
|
+
# Copyright, 2019-2026, by Samuel Williams.
|
|
5
5
|
# Copyright, 2019, by Brian Morearty.
|
|
6
6
|
# Copyright, 2020, by Bruno Sutic.
|
|
7
7
|
# Copyright, 2023-2024, by Thomas Morgan.
|
|
@@ -266,6 +266,8 @@ module Protocol
|
|
|
266
266
|
@stream.write("host: #{authority}\r\n") if authority
|
|
267
267
|
|
|
268
268
|
write_headers(headers)
|
|
269
|
+
rescue
|
|
270
|
+
raise ::Protocol::HTTP::RequestRefusedError
|
|
269
271
|
end
|
|
270
272
|
|
|
271
273
|
# Write a response to the connection. It is expected you will write the body after this method.
|
|
@@ -614,32 +616,34 @@ module Protocol
|
|
|
614
616
|
|
|
615
617
|
if head
|
|
616
618
|
@stream.flush
|
|
619
|
+
else
|
|
620
|
+
@stream.flush unless body.ready?
|
|
617
621
|
|
|
618
|
-
|
|
622
|
+
chunk_length = 0
|
|
623
|
+
# Use a manual read loop (not body.each) so that body.close runs after the response is fully written and flushed. This ensures completion callbacks (e.g. rack.response_finished) don't delay the client.
|
|
624
|
+
while chunk = body.read
|
|
625
|
+
chunk_length += chunk.bytesize
|
|
626
|
+
|
|
627
|
+
if chunk_length > length
|
|
628
|
+
raise ContentLengthError, "Trying to write #{chunk_length} bytes, but content length was #{length} bytes!"
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
@stream.write(chunk)
|
|
632
|
+
@stream.flush unless body.ready?
|
|
633
|
+
end
|
|
619
634
|
|
|
620
|
-
|
|
621
|
-
end
|
|
622
|
-
|
|
623
|
-
@stream.flush unless body.ready?
|
|
624
|
-
|
|
625
|
-
chunk_length = 0
|
|
626
|
-
body.each do |chunk|
|
|
627
|
-
chunk_length += chunk.bytesize
|
|
635
|
+
@stream.flush
|
|
628
636
|
|
|
629
|
-
if chunk_length
|
|
630
|
-
raise ContentLengthError, "
|
|
637
|
+
if chunk_length != length
|
|
638
|
+
raise ContentLengthError, "Wrote #{chunk_length} bytes, but content length was #{length} bytes!"
|
|
631
639
|
end
|
|
632
|
-
|
|
633
|
-
@stream.write(chunk)
|
|
634
|
-
@stream.flush unless body.ready?
|
|
635
|
-
end
|
|
636
|
-
|
|
637
|
-
@stream.flush
|
|
638
|
-
|
|
639
|
-
if chunk_length != length
|
|
640
|
-
raise ContentLengthError, "Wrote #{chunk_length} bytes, but content length was #{length} bytes!"
|
|
641
640
|
end
|
|
641
|
+
rescue => error
|
|
642
|
+
raise
|
|
642
643
|
ensure
|
|
644
|
+
# Close the body after the response is fully flushed, so that completion callbacks run after the client has received the response:
|
|
645
|
+
body.close(error)
|
|
646
|
+
|
|
643
647
|
self.send_end_stream!
|
|
644
648
|
end
|
|
645
649
|
|
|
@@ -657,34 +661,36 @@ module Protocol
|
|
|
657
661
|
|
|
658
662
|
if head
|
|
659
663
|
@stream.flush
|
|
664
|
+
else
|
|
665
|
+
@stream.flush unless body.ready?
|
|
660
666
|
|
|
661
|
-
body.close
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
667
|
+
# Use a manual read loop (not body.each) so that body.close runs after the terminal chunk is written. With body.each, the ensure { close } fires before the terminal "0\r\n\r\n" is sent, delaying the client.
|
|
668
|
+
while chunk = body.read
|
|
669
|
+
next if chunk.size == 0
|
|
670
|
+
|
|
671
|
+
@stream.write("#{chunk.bytesize.to_s(16).upcase}\r\n")
|
|
672
|
+
@stream.write(chunk)
|
|
673
|
+
@stream.write(CRLF)
|
|
674
|
+
|
|
675
|
+
@stream.flush unless body.ready?
|
|
676
|
+
end
|
|
670
677
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
678
|
+
if trailer&.any?
|
|
679
|
+
@stream.write("0\r\n")
|
|
680
|
+
write_headers(trailer)
|
|
681
|
+
@stream.write("\r\n")
|
|
682
|
+
else
|
|
683
|
+
@stream.write("0\r\n\r\n")
|
|
684
|
+
end
|
|
674
685
|
|
|
675
|
-
@stream.flush
|
|
676
|
-
end
|
|
677
|
-
|
|
678
|
-
if trailer&.any?
|
|
679
|
-
@stream.write("0\r\n")
|
|
680
|
-
write_headers(trailer)
|
|
681
|
-
@stream.write("\r\n")
|
|
682
|
-
else
|
|
683
|
-
@stream.write("0\r\n\r\n")
|
|
686
|
+
@stream.flush
|
|
684
687
|
end
|
|
685
|
-
|
|
686
|
-
|
|
688
|
+
rescue => error
|
|
689
|
+
raise
|
|
687
690
|
ensure
|
|
691
|
+
# Close the body after the complete chunked response (including terminal chunk) is flushed, so that completion callbacks don't block the client from seeing the response as complete:
|
|
692
|
+
body.close(error)
|
|
693
|
+
|
|
688
694
|
self.send_end_stream!
|
|
689
695
|
end
|
|
690
696
|
|
|
@@ -697,12 +703,11 @@ module Protocol
|
|
|
697
703
|
@persistent = false
|
|
698
704
|
|
|
699
705
|
@stream.write("\r\n")
|
|
700
|
-
@stream.flush unless body.ready?
|
|
701
706
|
|
|
702
|
-
|
|
703
|
-
body.
|
|
704
|
-
|
|
705
|
-
body.
|
|
707
|
+
unless head
|
|
708
|
+
@stream.flush unless body.ready?
|
|
709
|
+
|
|
710
|
+
while chunk = body.read
|
|
706
711
|
@stream.write(chunk)
|
|
707
712
|
|
|
708
713
|
@stream.flush unless body.ready?
|
|
@@ -711,7 +716,12 @@ module Protocol
|
|
|
711
716
|
|
|
712
717
|
@stream.flush
|
|
713
718
|
@stream.close_write
|
|
719
|
+
rescue => error
|
|
720
|
+
raise
|
|
714
721
|
ensure
|
|
722
|
+
# Close the body after the stream is fully written and half-closed, so that completion callbacks run after the client has received the full response:
|
|
723
|
+
body.close(error)
|
|
724
|
+
|
|
715
725
|
self.send_end_stream!
|
|
716
726
|
end
|
|
717
727
|
|
data/lib/protocol/http1/error.rb
CHANGED
data/readme.md
CHANGED
|
@@ -30,6 +30,14 @@ Please see the [project documentation](https://socketry.github.io/protocol-http1
|
|
|
30
30
|
|
|
31
31
|
Please see the [project releases](https://socketry.github.io/protocol-http1/releases/index) for all releases.
|
|
32
32
|
|
|
33
|
+
### v0.38.0
|
|
34
|
+
|
|
35
|
+
- `write_request` now raises `Protocol::HTTP::RequestRefusedError` if the request line or headers cannot be written, indicating the request was not processed and can be safely retried.
|
|
36
|
+
|
|
37
|
+
### v0.37.1
|
|
38
|
+
|
|
39
|
+
- Defer `body.close` in `write_chunked_body`, `write_fixed_length_body`, and `write_body_and_close` until after the response is fully written and flushed. Previously, `body.each` called `close` in its `ensure` block before the terminal chunk (chunked encoding) or final flush was written, causing `rack.response_finished` callbacks to delay the client-visible response completion.
|
|
40
|
+
|
|
33
41
|
### v0.37.0
|
|
34
42
|
|
|
35
43
|
- `Protocol::HTTP1::BadRequest` now includes `Protocol::HTTP::BadRequest` for better interoperability and handling of bad request errors across different HTTP protocol implementations.
|
|
@@ -65,14 +73,6 @@ Please see the [project releases](https://socketry.github.io/protocol-http1/rele
|
|
|
65
73
|
- Fix header parsing to handle tab characters between values correctly.
|
|
66
74
|
- Complete documentation coverage for all public APIs.
|
|
67
75
|
|
|
68
|
-
### v0.31.0
|
|
69
|
-
|
|
70
|
-
- Enforce one-way transition for persistent connections to prevent invalid state changes.
|
|
71
|
-
|
|
72
|
-
### v0.30.0
|
|
73
|
-
|
|
74
|
-
- Make `authority` header optional in HTTP requests for improved flexibility.
|
|
75
|
-
|
|
76
76
|
## Contributing
|
|
77
77
|
|
|
78
78
|
We welcome contributions to this project.
|
data/releases.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
+
## v0.38.0
|
|
4
|
+
|
|
5
|
+
- `write_request` now raises `Protocol::HTTP::RequestRefusedError` if the request line or headers cannot be written, indicating the request was not processed and can be safely retried.
|
|
6
|
+
|
|
7
|
+
## v0.37.1
|
|
8
|
+
|
|
9
|
+
- Defer `body.close` in `write_chunked_body`, `write_fixed_length_body`, and `write_body_and_close` until after the response is fully written and flushed. Previously, `body.each` called `close` in its `ensure` block before the terminal chunk (chunked encoding) or final flush was written, causing `rack.response_finished` callbacks to delay the client-visible response completion.
|
|
10
|
+
|
|
3
11
|
## v0.37.0
|
|
4
12
|
|
|
5
13
|
- `Protocol::HTTP1::BadRequest` now includes `Protocol::HTTP::BadRequest` for better interoperability and handling of bad request errors across different HTTP protocol implementations.
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: protocol-http1
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.38.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
@@ -49,14 +49,14 @@ dependencies:
|
|
|
49
49
|
requirements:
|
|
50
50
|
- - "~>"
|
|
51
51
|
- !ruby/object:Gem::Version
|
|
52
|
-
version: '0.
|
|
52
|
+
version: '0.61'
|
|
53
53
|
type: :runtime
|
|
54
54
|
prerelease: false
|
|
55
55
|
version_requirements: !ruby/object:Gem::Requirement
|
|
56
56
|
requirements:
|
|
57
57
|
- - "~>"
|
|
58
58
|
- !ruby/object:Gem::Version
|
|
59
|
-
version: '0.
|
|
59
|
+
version: '0.61'
|
|
60
60
|
executables: []
|
|
61
61
|
extensions: []
|
|
62
62
|
extra_rdoc_files: []
|
|
@@ -90,14 +90,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
90
90
|
requirements:
|
|
91
91
|
- - ">="
|
|
92
92
|
- !ruby/object:Gem::Version
|
|
93
|
-
version: '3.
|
|
93
|
+
version: '3.3'
|
|
94
94
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
95
|
requirements:
|
|
96
96
|
- - ">="
|
|
97
97
|
- !ruby/object:Gem::Version
|
|
98
98
|
version: '0'
|
|
99
99
|
requirements: []
|
|
100
|
-
rubygems_version: 4.0.
|
|
100
|
+
rubygems_version: 4.0.6
|
|
101
101
|
specification_version: 4
|
|
102
102
|
summary: A low level implementation of the HTTP/1 protocol.
|
|
103
103
|
test_files: []
|
metadata.gz.sig
CHANGED
|
Binary file
|