protocol-http 0.26.2 → 0.26.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/protocol/http/body/readable.rb +14 -0
- data/lib/protocol/http/body/wrapper.rb +11 -0
- data/lib/protocol/http/headers.rb +2 -0
- data/lib/protocol/http/request.rb +17 -0
- data/lib/protocol/http/response.rb +14 -0
- data/lib/protocol/http/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +2 -3
- metadata.gz.sig +0 -0
- data/design.md +0 -167
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0817ddd3e60c6de45f9e5a73ecedb00e60c11c8171bcddca6b1da0b3bc898708'
|
4
|
+
data.tar.gz: bac2be42911aab9457374fc16d80ca4db76e9b7b4a9bacb5d6937e63e5520298
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f78f1dcb03b5d203fae96a278a2152ee938ac8256692bf379819d44742104bc3c310ed1e6ce09f652f71ac86a08b1157705e7500974a4b2cdfdba7a00ed5a6fb
|
7
|
+
data.tar.gz: 1bba3d55382e65a7a79f60c81d089c129dde3b4bc2ab5e550172797a86be0d962426d1beb4910710c96a418f5b4460c2578f34bcac15cb34e1e0f93f1fdcf253
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -92,6 +92,20 @@ module Protocol
|
|
92
92
|
return buffer
|
93
93
|
end
|
94
94
|
end
|
95
|
+
|
96
|
+
def as_json(...)
|
97
|
+
{
|
98
|
+
class: self.class.name,
|
99
|
+
length: self.length,
|
100
|
+
stream: self.stream?,
|
101
|
+
ready: self.ready?,
|
102
|
+
empty: self.empty?
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_json(...)
|
107
|
+
as_json.to_json(...)
|
108
|
+
end
|
95
109
|
end
|
96
110
|
end
|
97
111
|
end
|
@@ -73,6 +73,23 @@ module Protocol
|
|
73
73
|
@method != Methods::POST && (@body.nil? || @body.empty?)
|
74
74
|
end
|
75
75
|
|
76
|
+
def as_json(...)
|
77
|
+
{
|
78
|
+
scheme: @scheme,
|
79
|
+
authority: @authority,
|
80
|
+
method: @method,
|
81
|
+
path: @path,
|
82
|
+
version: @version,
|
83
|
+
headers: @headers&.as_json,
|
84
|
+
body: @body&.as_json,
|
85
|
+
protocol: @protocol
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_json(...)
|
90
|
+
as_json.to_json(...)
|
91
|
+
end
|
92
|
+
|
76
93
|
def to_s
|
77
94
|
"#{@scheme}://#{@authority}: #{@method} #{@path} #{@version}"
|
78
95
|
end
|
@@ -104,6 +104,20 @@ module Protocol
|
|
104
104
|
Response[500, Headers['content-type' => 'text/plain'], ["#{exception.class}: #{exception.message}"]]
|
105
105
|
end
|
106
106
|
|
107
|
+
def as_json(...)
|
108
|
+
{
|
109
|
+
version: @version,
|
110
|
+
status: @status,
|
111
|
+
headers: @headers&.as_json,
|
112
|
+
body: @body&.as_json,
|
113
|
+
protocol: @protocol
|
114
|
+
}
|
115
|
+
end
|
116
|
+
|
117
|
+
def to_json(...)
|
118
|
+
as_json.to_json(...)
|
119
|
+
end
|
120
|
+
|
107
121
|
def to_s
|
108
122
|
"#{@status} #{@version}"
|
109
123
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protocol-http
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.26.
|
4
|
+
version: 0.26.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -47,7 +47,7 @@ cert_chain:
|
|
47
47
|
Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
|
48
48
|
voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
|
49
49
|
-----END CERTIFICATE-----
|
50
|
-
date: 2024-04-
|
50
|
+
date: 2024-04-16 00:00:00.000000000 Z
|
51
51
|
dependencies: []
|
52
52
|
description:
|
53
53
|
email:
|
@@ -55,7 +55,6 @@ executables: []
|
|
55
55
|
extensions: []
|
56
56
|
extra_rdoc_files: []
|
57
57
|
files:
|
58
|
-
- design.md
|
59
58
|
- lib/protocol/http.rb
|
60
59
|
- lib/protocol/http/accept_encoding.rb
|
61
60
|
- lib/protocol/http/body/buffered.rb
|
metadata.gz.sig
CHANGED
Binary file
|
data/design.md
DELETED
@@ -1,167 +0,0 @@
|
|
1
|
-
# Middleware Design
|
2
|
-
|
3
|
-
`Body::Writable` is a queue of String chunks.
|
4
|
-
|
5
|
-
## Request Response Model
|
6
|
-
|
7
|
-
~~~ruby
|
8
|
-
class Request
|
9
|
-
attr :verb
|
10
|
-
attr :target
|
11
|
-
attr :body
|
12
|
-
end
|
13
|
-
|
14
|
-
class Response
|
15
|
-
attr :status
|
16
|
-
attr :headers
|
17
|
-
attr :body
|
18
|
-
end
|
19
|
-
|
20
|
-
def call(request)
|
21
|
-
return response
|
22
|
-
end
|
23
|
-
|
24
|
-
def call(request)
|
25
|
-
return @app.call(request)
|
26
|
-
end
|
27
|
-
~~~
|
28
|
-
|
29
|
-
## Stream Model
|
30
|
-
|
31
|
-
~~~ruby
|
32
|
-
class Stream
|
33
|
-
attr :verb
|
34
|
-
attr :target
|
35
|
-
|
36
|
-
def respond(status, headers) = ...
|
37
|
-
|
38
|
-
attr_accessor :input
|
39
|
-
attr_accessor :output
|
40
|
-
end
|
41
|
-
|
42
|
-
class Response
|
43
|
-
def initialize(verb, target)
|
44
|
-
@input = Body::Writable.new
|
45
|
-
@output = Body::Writable.new
|
46
|
-
end
|
47
|
-
|
48
|
-
def request(verb, target)
|
49
|
-
# Create a request stream suitable for writing into the buffered response:
|
50
|
-
Stream.new(verb, target, @input, @output)
|
51
|
-
end
|
52
|
-
|
53
|
-
def write(...)
|
54
|
-
@input.write(...)
|
55
|
-
end
|
56
|
-
|
57
|
-
def read
|
58
|
-
@output.read
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def call(stream)
|
63
|
-
# nothing. maybe error
|
64
|
-
end
|
65
|
-
|
66
|
-
def call(stream)
|
67
|
-
@app.call(stream)
|
68
|
-
end
|
69
|
-
~~~
|
70
|
-
|
71
|
-
# Client Design
|
72
|
-
|
73
|
-
## Request Response Model
|
74
|
-
|
75
|
-
~~~ruby
|
76
|
-
request = Request.new("GET", url)
|
77
|
-
response = call(request)
|
78
|
-
|
79
|
-
response.headers
|
80
|
-
response.read
|
81
|
-
~~~
|
82
|
-
|
83
|
-
## Stream Model
|
84
|
-
|
85
|
-
~~~ruby
|
86
|
-
response = Response.new
|
87
|
-
call(response.request("GET", url))
|
88
|
-
|
89
|
-
response.headers
|
90
|
-
response.read
|
91
|
-
~~~
|
92
|
-
|
93
|
-
## Differences
|
94
|
-
|
95
|
-
The request/response model has a symmetrical design which naturally uses the return value for the result of executing the request. The result encapsulates the behaviour of how to read the response status, headers and body. Because of that, streaming input and output becomes a function of the result object itself. As in:
|
96
|
-
|
97
|
-
~~~ruby
|
98
|
-
def call(request)
|
99
|
-
body = Body::Writable.new
|
100
|
-
|
101
|
-
Fiber.schedule do
|
102
|
-
while chunk = request.input.read
|
103
|
-
body.write(chunk.reverse)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
return Response[200, [], body]
|
108
|
-
end
|
109
|
-
|
110
|
-
input = Body::Writable.new
|
111
|
-
response = call(... body ...)
|
112
|
-
|
113
|
-
input.write("Hello World")
|
114
|
-
input.close
|
115
|
-
response.read -> "dlroW olleH"
|
116
|
-
~~~
|
117
|
-
|
118
|
-
The streaming model does not have the same symmetry, and instead opts for a uni-directional flow of information.
|
119
|
-
|
120
|
-
~~~ruby
|
121
|
-
def call(stream)
|
122
|
-
Fiber.schedule do
|
123
|
-
while chunk = stream.read
|
124
|
-
stream.write(chunk.reverse)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
input = Body::Writable.new
|
130
|
-
response = Response.new(...input...)
|
131
|
-
call(response.stream)
|
132
|
-
|
133
|
-
input.write("Hello World")
|
134
|
-
input.close
|
135
|
-
response.read -> "dlroW olleH"
|
136
|
-
~~~
|
137
|
-
|
138
|
-
The value of this uni-directional flow is that it is natural for the stream to be taken out of the scope imposed by the nested `call(request)` model. However, the user must explicitly close the stream, since it's no longer scoped to the client and/or server.
|
139
|
-
|
140
|
-
## Connection Upgrade
|
141
|
-
|
142
|
-
### HTTP/1
|
143
|
-
|
144
|
-
```
|
145
|
-
GET /path/to/websocket HTTP/1.1
|
146
|
-
connection: upgrade
|
147
|
-
upgrade: websocket
|
148
|
-
```
|
149
|
-
|
150
|
-
Request.new(GET, ..., protocol = websocket)
|
151
|
-
-> Response.new(101, ..., protocol = websocket)
|
152
|
-
|
153
|
-
```
|
154
|
-
101 Switching Protocols
|
155
|
-
upgrade: websocket
|
156
|
-
```
|
157
|
-
|
158
|
-
### HTTP/2
|
159
|
-
|
160
|
-
```
|
161
|
-
:method CONNECT
|
162
|
-
:path /path/to/websocket
|
163
|
-
:protocol websocket
|
164
|
-
```
|
165
|
-
|
166
|
-
Request.new(CONNECT, ..., protocol = websocket)
|
167
|
-
-> Response.new(200, ..., protocol = websocket)
|