blest 0.0.2 → 1.0.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
- data/README.md +60 -99
- data/lib/blest.rb +811 -143
- data/spec/blest_spec.rb +220 -0
- metadata +10 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4f44d941bb783457e67fa52ada69792f5f645a76bac399165d59c73f4ba7b4b
|
4
|
+
data.tar.gz: 8f7ee45d396ae4cab3c8178f1bef7e6605612efb94e259cbb35bcd3da842e347
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aecfa3005a9a29bcfd4b4f501710a0f8a49251ff7fc62f4043bfe8e5b0e7f6c8e2ddbb09df2ae14c08bc7617a09ab08d84ed52d9023272bd9bb05dabd1fb8e41
|
7
|
+
data.tar.gz: 2855b895975b23f418e0e084ecd3d15bd8df43764a896aca1f8fa5788d21e74ab7fb5ff5fdc4bbcd79a074dff7ce2f14bb3a10ee4e497d8ef1d63b1a645066c3
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# BLEST Ruby
|
2
2
|
|
3
|
-
The Ruby reference implementation of BLEST (Batch-able, Lightweight, Encrypted State Transfer), an improved communication protocol for web APIs which leverages JSON, supports request batching
|
3
|
+
The Ruby reference implementation of BLEST (Batch-able, Lightweight, Encrypted State Transfer), an improved communication protocol for web APIs which leverages JSON, supports request batching by default, and provides a modern alternative to REST.
|
4
4
|
|
5
|
-
To learn more about BLEST, please
|
5
|
+
To learn more about BLEST, please visit the website: https://blest.jhunt.dev
|
6
6
|
|
7
7
|
For a front-end implementation in React, please visit https://github.com/jhuntdev/blest-react
|
8
8
|
|
@@ -10,9 +10,8 @@ For a front-end implementation in React, please visit https://github.com/jhuntde
|
|
10
10
|
|
11
11
|
- Built on JSON - Reduce parsing time and overhead
|
12
12
|
- Request Batching - Save bandwidth and reduce load times
|
13
|
-
- Compact Payloads - Save more bandwidth
|
14
|
-
-
|
15
|
-
- Single Endpoint - Reduce complexity and improve data privacy
|
13
|
+
- Compact Payloads - Save even more bandwidth
|
14
|
+
- Single Endpoint - Reduce complexity and facilitate introspection
|
16
15
|
- Fully Encrypted - Improve data privacy
|
17
16
|
|
18
17
|
## Installation
|
@@ -25,139 +24,101 @@ gem install blest
|
|
25
24
|
|
26
25
|
## Usage
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
<!-- Use the `create_http_client` function to create a BLEST HTTP client. -->
|
31
|
-
|
32
|
-
### create_request_handler
|
27
|
+
The `Blest` class of this library has an interface similar to Sinatra. It also provides a `Router` class with a `handle` method for use in an existing Ruby API and an `HttpClient` class with a `request` method for making BLEST HTTP requests.
|
33
28
|
|
34
29
|
```ruby
|
35
|
-
require 'webrick'
|
36
|
-
require 'json'
|
37
30
|
require 'blest'
|
38
31
|
|
32
|
+
app = Blest.new(timeout: 1000, port: 8080, host: 'localhost', cors: 'http://localhost:3000')
|
33
|
+
|
39
34
|
# Create some middleware (optional)
|
40
|
-
|
41
|
-
if
|
42
|
-
context[
|
43
|
-
|
35
|
+
app.before do |body, context|
|
36
|
+
if context.dig('headers', 'auth') == 'myToken'?
|
37
|
+
context['user'] = {
|
38
|
+
# user info for example
|
44
39
|
}
|
45
40
|
nil
|
46
41
|
else
|
47
42
|
raise RuntimeError, "Unauthorized"
|
48
43
|
end
|
49
|
-
|
44
|
+
end
|
50
45
|
|
51
46
|
# Create a route controller
|
52
|
-
|
47
|
+
app.route('greet') do |body, context|
|
53
48
|
{
|
54
|
-
greeting: "Hi, #{
|
49
|
+
greeting: "Hi, #{body['name']}!"
|
55
50
|
}
|
56
|
-
}
|
57
|
-
|
58
|
-
# Create a router
|
59
|
-
router = {
|
60
|
-
greet: [auth_middleware, greet_controller]
|
61
|
-
}
|
62
|
-
|
63
|
-
# Create a request handler
|
64
|
-
handler = create_request_handler(router)
|
65
|
-
|
66
|
-
class HttpRequestHandler < WEBrick::HTTPServlet::AbstractServlet
|
67
|
-
def do_OPTIONS(request, response)
|
68
|
-
response.status = 200
|
69
|
-
response['Access-Control-Allow-Origin'] = '*'
|
70
|
-
response['Access-Control-Allow-Methods'] = 'POST, OPTIONS'
|
71
|
-
response['Access-Control-Allow-Headers'] = 'Content-Type'
|
72
|
-
end
|
73
|
-
|
74
|
-
def do_POST(request, response)
|
75
|
-
response['Content-Type'] = 'application/json'
|
76
|
-
response['Access-Control-Allow-Origin'] = '*'
|
77
|
-
|
78
|
-
# Parse JSON body
|
79
|
-
begin
|
80
|
-
payload = JSON.parse(request.body)
|
81
|
-
|
82
|
-
# Define the request context
|
83
|
-
context = {
|
84
|
-
headers: request.headers
|
85
|
-
}
|
86
|
-
|
87
|
-
# Use the request handler
|
88
|
-
result, error = handler.(payload, context)
|
89
|
-
|
90
|
-
# Do something with the result or error
|
91
|
-
if error
|
92
|
-
response_body = error.to_json
|
93
|
-
response.status = 500
|
94
|
-
response.body = response_body
|
95
|
-
elsif result
|
96
|
-
response_body = result.to_json
|
97
|
-
response.status = 200
|
98
|
-
response.body = response_body
|
99
|
-
else
|
100
|
-
response.status = 204
|
101
|
-
end
|
102
|
-
|
103
|
-
rescue JSON::ParserError
|
104
|
-
response.status = 400
|
105
|
-
response.body = { message: 'Invalid JSON' }.to_json
|
106
|
-
end
|
107
|
-
end
|
108
51
|
end
|
109
52
|
|
110
|
-
# Create WEBrick server
|
111
|
-
server = WEBrick::HTTPServer.new(Port: 8000)
|
112
|
-
|
113
|
-
# Mount custom request handler
|
114
|
-
server.mount('/', HttpRequestHandler)
|
115
|
-
|
116
|
-
trap('INT') { server.shutdown }
|
117
|
-
|
118
53
|
# Start the server
|
119
|
-
|
54
|
+
app.listen
|
120
55
|
```
|
121
56
|
|
122
|
-
###
|
57
|
+
### Router
|
58
|
+
|
59
|
+
The following example uses Sinatra.
|
123
60
|
|
124
61
|
```ruby
|
62
|
+
require 'sinatra'
|
63
|
+
require 'json'
|
125
64
|
require 'blest'
|
126
65
|
|
66
|
+
# Instantiate the Router
|
67
|
+
router = Router.new(timeout: 1000)
|
68
|
+
|
127
69
|
# Create some middleware (optional)
|
128
|
-
|
129
|
-
if
|
130
|
-
context[
|
131
|
-
|
70
|
+
router.before do |body, context|
|
71
|
+
if context.dig('headers', 'auth') == 'myToken'?
|
72
|
+
context['user'] = {
|
73
|
+
# user info for example
|
132
74
|
}
|
133
75
|
nil
|
134
76
|
else
|
135
77
|
raise RuntimeError, "Unauthorized"
|
136
78
|
end
|
137
|
-
|
79
|
+
end
|
138
80
|
|
139
81
|
# Create a route controller
|
140
|
-
|
82
|
+
router.route('greet') do |body, context|
|
141
83
|
{
|
142
|
-
greeting: "Hi, #{
|
84
|
+
greeting: "Hi, #{body['name']}!"
|
143
85
|
}
|
144
|
-
|
86
|
+
end
|
145
87
|
|
146
|
-
#
|
147
|
-
|
148
|
-
|
149
|
-
}
|
88
|
+
# Handle BLEST requests
|
89
|
+
post '/' do
|
90
|
+
json_body = JSON.parse(request.body.read)
|
91
|
+
headers = request.env.select { |k, _| k.start_with?('HTTP_') }
|
92
|
+
result, error = router.handle.call(json_body, { 'headers' => headers })
|
93
|
+
content_type :json
|
94
|
+
if error
|
95
|
+
raise Sinatra::Error.new(error.status || 500, error)
|
96
|
+
else
|
97
|
+
result
|
98
|
+
end
|
99
|
+
end
|
100
|
+
```
|
150
101
|
|
151
|
-
|
152
|
-
handler = create_request_handler(router)
|
102
|
+
### HttpClient
|
153
103
|
|
154
|
-
|
155
|
-
|
104
|
+
```ruby
|
105
|
+
require 'blest'
|
156
106
|
|
157
|
-
#
|
158
|
-
|
107
|
+
# Create a client
|
108
|
+
client = HttpClient.new('http://localhost:8080', max_batch_size = 25, buffer_delay = 10, http_headers = {
|
109
|
+
'Authorization': 'Bearer token'
|
110
|
+
})
|
111
|
+
|
112
|
+
# Send a request
|
113
|
+
begin
|
114
|
+
result = client.request('greet', { 'name': 'Steve' }, ['greeting']).value
|
115
|
+
# Do something with the result
|
116
|
+
rescue => error
|
117
|
+
# Do something in case of error
|
118
|
+
end
|
159
119
|
```
|
160
120
|
|
121
|
+
|
161
122
|
## License
|
162
123
|
|
163
124
|
This project is licensed under the [MIT License](LICENSE).
|