protocol-http 0.22.5 → 0.22.9
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/http/body/readable.rb +1 -1
- data/lib/protocol/http/body/stream.rb +73 -22
- data/lib/protocol/http/headers.rb +14 -9
- data/lib/protocol/http/url.rb +9 -5
- data/lib/protocol/http/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +37 -4
- 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: 4b1672fc86e8bbe321f648e200205314ee472f9b01c326882f089e149b584f11
|
4
|
+
data.tar.gz: acbe42e8d8af4b50d018325b0204cec345ed161fbb7eba0583a512ce65c0a713
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1cda8cf0c22f5d9a01a308cc83f2b80209bc3ad98ec84c5082d0846e6835224bb6c2ef9f9cc25b12eaa542f77000fa13c7cc9d2aba2107ba362e737c13ef90a0
|
7
|
+
data.tar.gz: 4fcd1417896726bce8019ea8fc5ebdbd92f07484611855c4cc04b0ba1a59deb18a79dd1d0c4b8978b7ec48c3c27376b09f3d75cd33728d4d5474093a08699694
|
checksums.yaml.gz.sig
ADDED
Binary file
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
#
|
3
3
|
# Copyright, 2019, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
4
4
|
#
|
5
5
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
@@ -20,15 +20,19 @@
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
21
|
# THE SOFTWARE.
|
22
22
|
|
23
|
+
require_relative 'buffered'
|
24
|
+
|
23
25
|
module Protocol
|
24
26
|
module HTTP
|
25
27
|
module Body
|
26
28
|
# The input stream is an IO-like object which contains the raw HTTP POST data. When applicable, its external encoding must be “ASCII-8BIT” and it must be opened in binary mode, for Ruby 1.9 compatibility. The input stream must respond to gets, each, read and rewind.
|
27
29
|
class Stream
|
28
|
-
def initialize(input, output)
|
30
|
+
def initialize(input, output = Buffered.new)
|
29
31
|
@input = input
|
30
32
|
@output = output
|
31
33
|
|
34
|
+
raise ArgumentError, "Non-writable output!" unless output.respond_to?(:write)
|
35
|
+
|
32
36
|
# Will hold remaining data in `#read`.
|
33
37
|
@buffer = nil
|
34
38
|
@closed = false
|
@@ -45,29 +49,62 @@ module Protocol
|
|
45
49
|
# @param buffer [String] the buffer which will receive the data
|
46
50
|
# @return a buffer containing the data
|
47
51
|
def read(length = nil, buffer = nil)
|
52
|
+
return '' if length == 0
|
53
|
+
|
48
54
|
buffer ||= Async::IO::Buffer.new
|
49
|
-
|
55
|
+
|
56
|
+
# Take any previously buffered data and replace it into the given buffer.
|
57
|
+
if @buffer
|
58
|
+
buffer.replace(@buffer)
|
59
|
+
@buffer = nil
|
60
|
+
end
|
50
61
|
|
51
|
-
|
52
|
-
|
53
|
-
|
62
|
+
if length
|
63
|
+
while buffer.bytesize < length and chunk = read_next
|
64
|
+
buffer << chunk
|
65
|
+
end
|
66
|
+
|
67
|
+
# This ensures the subsequent `slice!` works correctly.
|
68
|
+
buffer.force_encoding(Encoding::BINARY)
|
69
|
+
|
70
|
+
# This will be at least one copy:
|
71
|
+
@buffer = buffer.byteslice(length, buffer.bytesize)
|
54
72
|
|
55
|
-
|
73
|
+
# This should be zero-copy:
|
74
|
+
buffer.slice!(length)
|
56
75
|
|
57
|
-
if
|
58
|
-
|
59
|
-
# But byteslice will generate a hidden copy. So let's freeze it first:
|
60
|
-
@buffer.freeze
|
61
|
-
|
62
|
-
buffer << @buffer.byteslice(0, remaining_length)
|
63
|
-
@buffer = @buffer.byteslice(remaining_length, @buffer.bytesize)
|
76
|
+
if buffer.empty?
|
77
|
+
return nil
|
64
78
|
else
|
65
|
-
|
66
|
-
@buffer = nil
|
79
|
+
return buffer
|
67
80
|
end
|
81
|
+
else
|
82
|
+
while chunk = read_next
|
83
|
+
buffer << chunk
|
84
|
+
end
|
85
|
+
|
86
|
+
return buffer
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Read at most `length` bytes from the stream. Will avoid reading from the underlying stream if possible.
|
91
|
+
def read_partial(length = nil)
|
92
|
+
if @buffer
|
93
|
+
buffer = @buffer
|
94
|
+
@buffer = nil
|
95
|
+
else
|
96
|
+
buffer = read_next
|
68
97
|
end
|
69
98
|
|
70
|
-
|
99
|
+
if buffer and length
|
100
|
+
if buffer.bytesize > length
|
101
|
+
# This ensures the subsequent `slice!` works correctly.
|
102
|
+
buffer.force_encoding(Encoding::BINARY)
|
103
|
+
|
104
|
+
@buffer = buffer.byteslice(length, buffer.bytesize)
|
105
|
+
buffer.slice!(length)
|
106
|
+
end
|
107
|
+
end
|
71
108
|
|
72
109
|
return buffer
|
73
110
|
end
|
@@ -76,6 +113,11 @@ module Protocol
|
|
76
113
|
@buffer ||= read_next
|
77
114
|
chunk = nil
|
78
115
|
|
116
|
+
unless @buffer
|
117
|
+
buffer&.clear
|
118
|
+
return
|
119
|
+
end
|
120
|
+
|
79
121
|
if @buffer.bytesize > length
|
80
122
|
chunk = @buffer.byteslice(0, length)
|
81
123
|
@buffer = @buffer.byteslice(length, @buffer.bytesize)
|
@@ -94,7 +136,12 @@ module Protocol
|
|
94
136
|
end
|
95
137
|
|
96
138
|
def write(buffer)
|
97
|
-
@output
|
139
|
+
if @output
|
140
|
+
@output.write(buffer)
|
141
|
+
return buffer.bytesize
|
142
|
+
else
|
143
|
+
raise IOError, "Stream is not writable, output has been closed!"
|
144
|
+
end
|
98
145
|
end
|
99
146
|
|
100
147
|
alias write_nonblock write
|
@@ -104,17 +151,21 @@ module Protocol
|
|
104
151
|
|
105
152
|
def close_read
|
106
153
|
@input&.close
|
154
|
+
@input = nil
|
107
155
|
end
|
108
156
|
|
109
157
|
# close must never be called on the input stream. huh?
|
110
158
|
def close_write
|
111
159
|
@output&.close
|
160
|
+
@output = nil
|
112
161
|
end
|
113
162
|
|
114
163
|
# Close the input and output bodies.
|
115
|
-
def close
|
164
|
+
def close(error = nil)
|
116
165
|
self.close_read
|
117
166
|
self.close_write
|
167
|
+
|
168
|
+
return nil
|
118
169
|
ensure
|
119
170
|
@closed = true
|
120
171
|
end
|
@@ -132,11 +183,11 @@ module Protocol
|
|
132
183
|
private
|
133
184
|
|
134
185
|
def read_next
|
135
|
-
if
|
136
|
-
return
|
186
|
+
if @input
|
187
|
+
return @input.read
|
137
188
|
else
|
138
189
|
@input = nil
|
139
|
-
|
190
|
+
raise IOError, "Stream is not readable, input has been closed!"
|
140
191
|
end
|
141
192
|
end
|
142
193
|
end
|
@@ -101,22 +101,27 @@ module Protocol
|
|
101
101
|
# An array of `[key, value]` pairs.
|
102
102
|
attr :fields
|
103
103
|
|
104
|
-
# @
|
104
|
+
# @returns Whether there are any trailers.
|
105
105
|
def trailer?
|
106
106
|
@tail != nil
|
107
107
|
end
|
108
108
|
|
109
|
-
# Record the current headers, and prepare to
|
109
|
+
# Record the current headers, and prepare to add trailers.
|
110
|
+
#
|
111
|
+
# This method is typically used after headers are sent to capture any
|
112
|
+
# additional headers which should then be sent as trailers.
|
113
|
+
#
|
114
|
+
# A sender that intends to generate one or more trailer fields in a
|
115
|
+
# message should generate a trailer header field in the header section of
|
116
|
+
# that message to indicate which fields might be present in the trailers.
|
117
|
+
#
|
118
|
+
# @parameter names [Array] The trailer header names which will be added later.
|
119
|
+
# @yields block {|name, value| ...} The trailer headers if any.
|
120
|
+
# @returns An enumerator which is suitable for iterating over trailers.
|
110
121
|
def trailer!(&block)
|
111
|
-
return nil unless self.include?(TRAILER)
|
112
|
-
|
113
122
|
@tail ||= @fields.size
|
114
123
|
|
115
|
-
return
|
116
|
-
|
117
|
-
if @tail
|
118
|
-
@fields.drop(@tail).each(&block)
|
119
|
-
end
|
124
|
+
return trailer(&block)
|
120
125
|
end
|
121
126
|
|
122
127
|
# Enumerate all headers in the trailer, if there are any.
|
data/lib/protocol/http/url.rb
CHANGED
@@ -23,13 +23,14 @@
|
|
23
23
|
module Protocol
|
24
24
|
module HTTP
|
25
25
|
module URL
|
26
|
-
# Escapes a
|
26
|
+
# Escapes a string using percent encoding.
|
27
27
|
def self.escape(string, encoding = string.encoding)
|
28
28
|
string.b.gsub(/([^a-zA-Z0-9_.\-]+)/) do |m|
|
29
29
|
'%' + m.unpack('H2' * m.bytesize).join('%').upcase
|
30
30
|
end.force_encoding(encoding)
|
31
31
|
end
|
32
32
|
|
33
|
+
# Unescapes a percent encoded string.
|
33
34
|
def self.unescape(string, encoding = string.encoding)
|
34
35
|
string.b.gsub(/%(\h\h)/) do |hex|
|
35
36
|
Integer(hex, 16).chr
|
@@ -39,7 +40,7 @@ module Protocol
|
|
39
40
|
# According to https://tools.ietf.org/html/rfc3986#section-3.3, we escape non-pchar.
|
40
41
|
NON_PCHAR = /([^a-zA-Z0-9_\-\.~!$&'()*+,;=:@\/]+)/.freeze
|
41
42
|
|
42
|
-
# Escapes
|
43
|
+
# Escapes non-path characters using percent encoding.
|
43
44
|
def self.escape_path(path)
|
44
45
|
encoding = path.encoding
|
45
46
|
path.b.gsub(NON_PCHAR) do |m|
|
@@ -47,7 +48,7 @@ module Protocol
|
|
47
48
|
end.force_encoding(encoding)
|
48
49
|
end
|
49
50
|
|
50
|
-
# Encodes a hash or array into a query string
|
51
|
+
# Encodes a hash or array into a query string.
|
51
52
|
def self.encode(value, prefix = nil)
|
52
53
|
case value
|
53
54
|
when Array
|
@@ -67,9 +68,12 @@ module Protocol
|
|
67
68
|
end
|
68
69
|
end
|
69
70
|
|
71
|
+
# Scan a string for URL-encoded key/value pairs.
|
72
|
+
# @yields {|key, value| ...}
|
73
|
+
# @parameter key [String] The unescaped key.
|
74
|
+
# @parameter value [String] The unescaped key.
|
70
75
|
def self.scan(string)
|
71
|
-
|
72
|
-
string.split('&').each do |assignment|
|
76
|
+
string.split('&') do |assignment|
|
73
77
|
key, value = assignment.split('=', 2)
|
74
78
|
|
75
79
|
yield unescape(key), unescape(value)
|
data.tar.gz.sig
ADDED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,47 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protocol-http
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.22.
|
4
|
+
version: 0.22.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
|
+
- Bruno Sutic
|
9
|
+
- Bryan Powell
|
10
|
+
- Olle Jonsson
|
11
|
+
- Yuta Iwama
|
8
12
|
autorequire:
|
9
13
|
bindir: bin
|
10
|
-
cert_chain:
|
11
|
-
|
14
|
+
cert_chain:
|
15
|
+
- |
|
16
|
+
-----BEGIN CERTIFICATE-----
|
17
|
+
MIIE2DCCA0CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMRgwFgYDVQQDDA9zYW11
|
18
|
+
ZWwud2lsbGlhbXMxHTAbBgoJkiaJk/IsZAEZFg1vcmlvbnRyYW5zZmVyMRIwEAYK
|
19
|
+
CZImiZPyLGQBGRYCY28xEjAQBgoJkiaJk/IsZAEZFgJuejAeFw0yMjA4MDYwNDUz
|
20
|
+
MjRaFw0zMjA4MDMwNDUzMjRaMGExGDAWBgNVBAMMD3NhbXVlbC53aWxsaWFtczEd
|
21
|
+
MBsGCgmSJomT8ixkARkWDW9yaW9udHJhbnNmZXIxEjAQBgoJkiaJk/IsZAEZFgJj
|
22
|
+
bzESMBAGCgmSJomT8ixkARkWAm56MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
|
23
|
+
igKCAYEAomvSopQXQ24+9DBB6I6jxRI2auu3VVb4nOjmmHq7XWM4u3HL+pni63X2
|
24
|
+
9qZdoq9xt7H+RPbwL28LDpDNflYQXoOhoVhQ37Pjn9YDjl8/4/9xa9+NUpl9XDIW
|
25
|
+
sGkaOY0eqsQm1pEWkHJr3zn/fxoKPZPfaJOglovdxf7dgsHz67Xgd/ka+Wo1YqoE
|
26
|
+
e5AUKRwUuvaUaumAKgPH+4E4oiLXI4T1Ff5Q7xxv6yXvHuYtlMHhYfgNn8iiW8WN
|
27
|
+
XibYXPNP7NtieSQqwR/xM6IRSoyXKuS+ZNGDPUUGk8RoiV/xvVN4LrVm9upSc0ss
|
28
|
+
RZ6qwOQmXCo/lLcDUxJAgG95cPw//sI00tZan75VgsGzSWAOdjQpFM0l4dxvKwHn
|
29
|
+
tUeT3ZsAgt0JnGqNm2Bkz81kG4A2hSyFZTFA8vZGhp+hz+8Q573tAR89y9YJBdYM
|
30
|
+
zp0FM4zwMNEUwgfRzv1tEVVUEXmoFCyhzonUUw4nE4CFu/sE3ffhjKcXcY//qiSW
|
31
|
+
xm4erY3XAgMBAAGjgZowgZcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O
|
32
|
+
BBYEFO9t7XWuFf2SKLmuijgqR4sGDlRsMC4GA1UdEQQnMCWBI3NhbXVlbC53aWxs
|
33
|
+
aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MC4GA1UdEgQnMCWBI3NhbXVlbC53aWxs
|
34
|
+
aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MA0GCSqGSIb3DQEBCwUAA4IBgQB5sxkE
|
35
|
+
cBsSYwK6fYpM+hA5B5yZY2+L0Z+27jF1pWGgbhPH8/FjjBLVn+VFok3CDpRqwXCl
|
36
|
+
xCO40JEkKdznNy2avOMra6PFiQyOE74kCtv7P+Fdc+FhgqI5lMon6tt9rNeXmnW/
|
37
|
+
c1NaMRdxy999hmRGzUSFjozcCwxpy/LwabxtdXwXgSay4mQ32EDjqR1TixS1+smp
|
38
|
+
8C/NCWgpIfzpHGJsjvmH2wAfKtTTqB9CVKLCWEnCHyCaRVuKkrKjqhYCdmMBqCws
|
39
|
+
JkxfQWC+jBVeG9ZtPhQgZpfhvh+6hMhraUYRQ6XGyvBqEUe+yo6DKIT3MtGE2+CP
|
40
|
+
eX9i9ZWBydWb8/rvmwmX2kkcBbX0hZS1rcR593hGc61JR6lvkGYQ2MYskBveyaxt
|
41
|
+
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
42
|
+
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
43
|
+
-----END CERTIFICATE-----
|
44
|
+
date: 2022-08-07 00:00:00.000000000 Z
|
12
45
|
dependencies:
|
13
46
|
- !ruby/object:Gem::Dependency
|
14
47
|
name: bundler
|
@@ -112,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
145
|
- !ruby/object:Gem::Version
|
113
146
|
version: '0'
|
114
147
|
requirements: []
|
115
|
-
rubygems_version: 3.
|
148
|
+
rubygems_version: 3.3.7
|
116
149
|
signing_key:
|
117
150
|
specification_version: 4
|
118
151
|
summary: Provides abstractions to handle HTTP protocols.
|
metadata.gz.sig
ADDED
Binary file
|