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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -99
  3. data/lib/blest.rb +811 -143
  4. data/spec/blest_spec.rb +220 -0
  5. metadata +10 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7cbe0f3613fd73841d959cad671fb7ec368ff5de50a2e5e874048871070d70b5
4
- data.tar.gz: 209e015fa2bd51a03476ab597bbc4c4109037cfea52b79904a27f2a54fc1b368
3
+ metadata.gz: c4f44d941bb783457e67fa52ada69792f5f645a76bac399165d59c73f4ba7b4b
4
+ data.tar.gz: 8f7ee45d396ae4cab3c8178f1bef7e6605612efb94e259cbb35bcd3da842e347
5
5
  SHA512:
6
- metadata.gz: 8d9a2f9db5673835a9d0187374b52be72dd596a5ec9a3744a164cb6aecbefddfa0d96b3cd23bce63a706dd39fcdcde0e2c5f0231cd71086208d34820280b1d05
7
- data.tar.gz: e5d92953980bfe4a4e9a0d9c6c98db057cb5f5067af87680b2e83b4dc37df7ac52c5c3042697f63e9652dbefd3db2b0740f7c124b1837d330accd4b0360bfd57
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 and selective returns, and provides a modern alternative to REST.
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 refer to the white paper: https://jhunt.dev/BLEST%20White%20Paper.pdf
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
- - Selective Returns - Save even more bandwidth
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
- Use the `create_request_handler` function to create a request handler suitable for use in an existing Python application. Use the `create_http_server` function to create a standalone HTTP server for your request handler.
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
- auth_middleware = ->(params, context) {
41
- if params[:name].present?
42
- context[:user] = {
43
- name: params[:name]
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
- greet_controller = ->(params, context) {
47
+ app.route('greet') do |body, context|
53
48
  {
54
- greeting: "Hi, #{context[:user][:name]}!"
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
- server.start
54
+ app.listen
120
55
  ```
121
56
 
122
- ### create_http_server
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
- auth_middleware = ->(params, context) {
129
- if params[:name].present?
130
- context[:user] = {
131
- name: params[:name]
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
- greet_controller = ->(params, context) {
82
+ router.route('greet') do |body, context|
141
83
  {
142
- greeting: "Hi, #{context[:user][:name]}!"
84
+ greeting: "Hi, #{body['name']}!"
143
85
  }
144
- }
86
+ end
145
87
 
146
- # Create a router
147
- router = {
148
- greet: [auth_middleware, greet_controller]
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
- # Create a request handler
152
- handler = create_request_handler(router)
102
+ ### HttpClient
153
103
 
154
- # Create the server
155
- server = create_http_server(handler, { port: 8080 })
104
+ ```ruby
105
+ require 'blest'
156
106
 
157
- # Run the server
158
- server.()
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).