grpc-rest 0.2.1 → 0.3.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/CHANGELOG +5 -0
- data/Gemfile.lock +1 -1
- data/README.md +15 -1
- data/lib/generator/controller.rb.erb +3 -3
- data/lib/generator/method.rb +1 -1
- data/lib/generator.rb +0 -1
- data/lib/grpc_rest/version.rb +1 -1
- data/lib/grpc_rest.rb +7 -2
- data/spec/__snapshots__/service.snap +13 -13
- data/spec/grpc_rest_spec.rb +20 -5
- data/spec/gruf_spec.rb +3 -3
- data/spec/testdata/base/app/controllers/my_service_controller.rb +39 -46
- data/spec/testdata/base/config/routes/grpc.rb +6 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 628c8c0d79cbe90cfcb02c74d1f4e785ed25d7d56267bd1da54d4fe911ba0daa
|
4
|
+
data.tar.gz: a14292a527e3b1ae8c3455b3146c5aa9d3760d4cb11c5a1f206bba22e7690a67
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64227c2f740fd93e1f9c1bcb3e4779fac6de80c47c5f85848b1ab785a5cde39347a03eee6184ab906937eac465ef40e601adcf0c625aeae97128440d9f8f6c55
|
7
|
+
data.tar.gz: 7c1a0b6bdc6f7d56380646b388fc8eca4755ad750d6a4054d1151d0052e2b661a2dafa4299b72cf883a7dc15fc71b0892fa166c64513b2c28d7f806010110cf6
|
data/CHANGELOG
CHANGED
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
7
7
|
|
8
8
|
## UNRELEASED
|
9
9
|
|
10
|
+
# 0.3.0 - 2025-06-11
|
11
|
+
|
12
|
+
- Feature: Add `strict_mode` configuration for rejecting invalid JSON fields.
|
13
|
+
- Fixes for test failures that were caused by changes in 0.2.0 - test files weren't correctly regenerated.
|
14
|
+
|
10
15
|
# 0.2.1 - 2025-05-06
|
11
16
|
- Fix: Use `Array.wrap` to prevent grpc-rest from crashing when query parameters don't have `[]` suffixed.
|
12
17
|
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -175,6 +175,14 @@ module Interceptors
|
|
175
175
|
end
|
176
176
|
```
|
177
177
|
|
178
|
+
### Configuration
|
179
|
+
|
180
|
+
GrpcRest currently has one configuration option, `strict_mode`, which defaults to false. When set to true, any JSON request that includes an unknown field will be rejected.
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
GrpcRest.strict_mode = true
|
184
|
+
```
|
185
|
+
|
178
186
|
## Contributing
|
179
187
|
|
180
188
|
Bug reports and pull requests are welcome on GitHub at https://github.com/flipp-oss/grpc-rest.
|
@@ -182,7 +190,13 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/flipp-
|
|
182
190
|
To regenerate Ruby protobuf code for tests, install the `grpc-tools` gem and run this from the base directory:
|
183
191
|
|
184
192
|
```
|
185
|
-
grpc_tools_ruby_protoc -I=./
|
193
|
+
grpc_tools_ruby_protoc -I=./spec/testdata --proto_path=./spec/google-deps --ruby_out=./spec --grpc_out=./spec ./spec/testdata/test_service.proto
|
194
|
+
```
|
195
|
+
|
196
|
+
To regenerate the controller and route files for tests, run:
|
197
|
+
|
198
|
+
```
|
199
|
+
bundle exec grpc_tools_ruby_protoc -I=./spec/testdata --proto_path=./spec/google-deps --rails_out=spec/testdata/base --rails_opt=require=spec/gen ./spec/testdata/test_service.proto
|
186
200
|
```
|
187
201
|
|
188
202
|
## License
|
@@ -17,9 +17,9 @@ class <%= service.name.demodulize %>Controller < ActionController::Base
|
|
17
17
|
|
18
18
|
<% service.methods.each do |method| %>
|
19
19
|
def <%= method.name %>
|
20
|
-
|
21
|
-
|
22
|
-
grpc_request = GrpcRest.init_request(<%= method.request_type %>, parameters
|
20
|
+
parameters = request.parameters.to_h.deep_transform_keys(&:underscore).
|
21
|
+
except(*%w(controller action <%= service.name.underscore %>))
|
22
|
+
grpc_request = GrpcRest.init_request(<%= method.request_type %>, parameters)
|
23
23
|
GrpcRest.assign_params(grpc_request, METHOD_PARAM_MAP["<%= method.name.underscore %>"], "<%= method.option_body %>", request.parameters)
|
24
24
|
render json: GrpcRest.send_request("<%= service.namespace %>::<%= service.name.classify %>", "<%= method.name.underscore %>", grpc_request, <%= method.rest_options.inspect %>)
|
25
25
|
end
|
data/lib/generator/method.rb
CHANGED
data/lib/generator.rb
CHANGED
data/lib/grpc_rest/version.rb
CHANGED
data/lib/grpc_rest.rb
CHANGED
@@ -6,6 +6,8 @@ require 'grpc/core/status_codes'
|
|
6
6
|
|
7
7
|
module GrpcRest
|
8
8
|
class << self
|
9
|
+
attr_accessor :strict_mode
|
10
|
+
|
9
11
|
def underscore(s)
|
10
12
|
GRPC::GenericService.underscore(s)
|
11
13
|
end
|
@@ -110,13 +112,16 @@ module GrpcRest
|
|
110
112
|
end
|
111
113
|
end
|
112
114
|
|
113
|
-
|
114
115
|
params
|
115
116
|
end
|
116
117
|
|
117
118
|
def init_request(request_class, params)
|
118
119
|
map_proto_record(request_class.descriptor, params)
|
119
|
-
|
120
|
+
if GrpcRest.strict_mode
|
121
|
+
request_class.decode_json(JSON.generate(params))
|
122
|
+
else
|
123
|
+
request_class.decode_json(JSON.generate(params), ignore_unknown_fields: true)
|
124
|
+
end
|
120
125
|
end
|
121
126
|
|
122
127
|
def assign_params(request, param_hash, body_string, params)
|
@@ -14,7 +14,7 @@ class MyServiceController < ActionController::Base
|
|
14
14
|
rescue_from ActionDispatch::Http::Parameters::ParseError, Google::Protobuf::TypeError do |e|
|
15
15
|
render json: GrpcRest.error_msg(e), status: :bad_request
|
16
16
|
end
|
17
|
-
METHOD_PARAM_MAP = {"test"=>[{:name=>"foobar", :val=>"
|
17
|
+
METHOD_PARAM_MAP = {"test"=>[{:name=>"foobar", :val=>"blah/*", :split_name=>["foobar"]}],
|
18
18
|
"test2"=>[],
|
19
19
|
"test3"=>
|
20
20
|
[{:name=>"sub_record.sub_id",
|
@@ -25,33 +25,33 @@ class MyServiceController < ActionController::Base
|
|
25
25
|
|
26
26
|
|
27
27
|
def test
|
28
|
-
|
29
|
-
|
30
|
-
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters
|
28
|
+
parameters = request.parameters.to_h.deep_transform_keys(&:underscore).
|
29
|
+
except(*%w(controller action my_service))
|
30
|
+
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters)
|
31
31
|
GrpcRest.assign_params(grpc_request, METHOD_PARAM_MAP["test"], "", request.parameters)
|
32
32
|
render json: GrpcRest.send_request("Testdata::MyService", "test", grpc_request, {:emit_defaults=>true})
|
33
33
|
end
|
34
34
|
|
35
35
|
def test2
|
36
|
-
|
37
|
-
|
38
|
-
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters
|
36
|
+
parameters = request.parameters.to_h.deep_transform_keys(&:underscore).
|
37
|
+
except(*%w(controller action my_service))
|
38
|
+
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters)
|
39
39
|
GrpcRest.assign_params(grpc_request, METHOD_PARAM_MAP["test2"], "second_record", request.parameters)
|
40
40
|
render json: GrpcRest.send_request("Testdata::MyService", "test2", grpc_request, {})
|
41
41
|
end
|
42
42
|
|
43
43
|
def test3
|
44
|
-
|
45
|
-
|
46
|
-
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters
|
44
|
+
parameters = request.parameters.to_h.deep_transform_keys(&:underscore).
|
45
|
+
except(*%w(controller action my_service))
|
46
|
+
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters)
|
47
47
|
GrpcRest.assign_params(grpc_request, METHOD_PARAM_MAP["test3"], "", request.parameters)
|
48
48
|
render json: GrpcRest.send_request("Testdata::MyService", "test3", grpc_request, {})
|
49
49
|
end
|
50
50
|
|
51
51
|
def test4
|
52
|
-
|
53
|
-
|
54
|
-
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters
|
52
|
+
parameters = request.parameters.to_h.deep_transform_keys(&:underscore).
|
53
|
+
except(*%w(controller action my_service))
|
54
|
+
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters)
|
55
55
|
GrpcRest.assign_params(grpc_request, METHOD_PARAM_MAP["test4"], "*", request.parameters)
|
56
56
|
render json: GrpcRest.send_request("Testdata::MyService", "test4", grpc_request, {})
|
57
57
|
end
|
data/spec/grpc_rest_spec.rb
CHANGED
@@ -10,15 +10,15 @@ class ServerImpl < Testdata::MyService::Service
|
|
10
10
|
Testdata::TestResponse.new(some_int: 1, full_response: req.to_json)
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
13
|
+
def test2(req)
|
14
14
|
Testdata::TestResponse.new(some_int: 2, full_response: req.to_json)
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
17
|
+
def test3(req)
|
18
18
|
Testdata::TestResponse.new(some_int: 3, full_response: req.to_json)
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def test4(req)
|
22
22
|
Testdata::TestResponse.new(some_int: 4, full_response: req.to_json)
|
23
23
|
end
|
24
24
|
end
|
@@ -44,6 +44,7 @@ RSpec.describe MyServiceController, type: :request do
|
|
44
44
|
}
|
45
45
|
|
46
46
|
post '/test2?test_id=abc&foobar=xyz×tamp_field=2024-04-03+01:02:03+UTC', params: params, as: :json
|
47
|
+
puts response.body
|
47
48
|
expect(response).to be_successful
|
48
49
|
expect(response.parsed_body).to eq({
|
49
50
|
'someInt' => 2,
|
@@ -103,6 +104,20 @@ RSpec.describe MyServiceController, type: :request do
|
|
103
104
|
}
|
104
105
|
end
|
105
106
|
|
107
|
+
it 'should pass with incorrect field' do
|
108
|
+
params[:blarg] = 'himom'
|
109
|
+
post '/test4', params: params, as: :json
|
110
|
+
expect(response).to be_successful
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should fail in strict mode' do
|
114
|
+
GrpcRest.strict_mode = true
|
115
|
+
params[:blarg] = 'himom'
|
116
|
+
post '/test4', params: params, as: :json
|
117
|
+
expect(response).not_to be_successful
|
118
|
+
GrpcRest.strict_mode = false
|
119
|
+
end
|
120
|
+
|
106
121
|
it 'should be successful' do
|
107
122
|
post '/test4', params: params, as: :json
|
108
123
|
expect(response).to be_successful
|
@@ -111,7 +126,7 @@ RSpec.describe MyServiceController, type: :request do
|
|
111
126
|
expect(full_response).to eq(
|
112
127
|
{ 'testId' => 'abc',
|
113
128
|
'foobar' => 'xyz',
|
114
|
-
|
129
|
+
'mapField' => { 'foo' => { 'anotherId' => 'id6', 'subId' => 'id5' } },
|
115
130
|
'repeatedString' => %w[W T F],
|
116
131
|
'subRecord' => { 'subId' => 'id1', 'anotherId' => 'id2' },
|
117
132
|
'secondRecord' => { 'subId' => 'id3', 'anotherId' => 'id4' },
|
@@ -141,7 +156,7 @@ RSpec.describe MyServiceController, type: :request do
|
|
141
156
|
expect(full_response).to eq(
|
142
157
|
{ 'testId' => 'abc',
|
143
158
|
'foobar' => 'xyz',
|
144
|
-
|
159
|
+
'mapField' => { 'foo' => { 'anotherId' => 'id6', 'subId' => 'id5' } },
|
145
160
|
'repeatedString' => %w[W T F],
|
146
161
|
'subRecord' => { 'subId' => 'id1', 'anotherId' => 'id2' },
|
147
162
|
'secondRecord' => { 'subId' => 'id3', 'anotherId' => 'id4' },
|
data/spec/gruf_spec.rb
CHANGED
@@ -11,15 +11,15 @@ class GrufServerImpl < Gruf::Controllers::Base
|
|
11
11
|
Testdata::TestResponse.new(some_int: 1, full_response: request.message.to_json)
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def test2
|
15
15
|
Testdata::TestResponse.new(some_int: 2, full_response: request.message.to_json)
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def test3
|
19
19
|
Testdata::TestResponse.new(some_int: 3, full_response: request.message.to_json)
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
22
|
+
def test4
|
23
23
|
Testdata::TestResponse.new(some_int: 4, full_response: request.message.to_json)
|
24
24
|
end
|
25
25
|
|
@@ -1,65 +1,58 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
####### THIS FILE IS AUTOMATICALLY GENERATED BY protoc-gen-rails. DO NOT MODIFY. #######
|
4
2
|
|
5
3
|
require 'grpc_rest'
|
6
4
|
class MyServiceController < ActionController::Base
|
7
5
|
protect_from_forgery with: :null_session
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
rescue_from StandardError do |e|
|
8
|
+
render json: GrpcRest.error_msg(e), status: :internal_server_error
|
9
|
+
end
|
12
10
|
rescue_from GRPC::BadStatus do |e|
|
13
|
-
|
11
|
+
render json: GrpcRest.error_msg(e), status: GrpcRest.grpc_http_status(e.code)
|
14
12
|
end
|
15
13
|
rescue_from ActionDispatch::Http::Parameters::ParseError, Google::Protobuf::TypeError do |e|
|
16
14
|
render json: GrpcRest.error_msg(e), status: :bad_request
|
17
15
|
end
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
],
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
def test
|
35
|
-
fields = Testdata::TestRequest.descriptor.to_a.map(&:name)
|
36
|
-
parameters = request.parameters.to_h.deep_transform_keys(&:underscore)
|
37
|
-
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters.slice(*fields))
|
38
|
-
GrpcRest.assign_params(grpc_request, METHOD_PARAM_MAP['test'], '', request.parameters)
|
39
|
-
render json: GrpcRest.send_request('Testdata::MyService', 'test', grpc_request, { emit_defaults: true })
|
16
|
+
METHOD_PARAM_MAP = {"test"=>[{:name=>"foobar", :val=>"blah/*", :split_name=>["foobar"]}],
|
17
|
+
"test2"=>[],
|
18
|
+
"test3"=>
|
19
|
+
[{:name=>"sub_record.sub_id",
|
20
|
+
:val=>"",
|
21
|
+
:split_name=>["sub_record", "sub_id"]}],
|
22
|
+
"test4"=>[]}
|
23
|
+
.freeze
|
24
|
+
|
25
|
+
|
26
|
+
def test
|
27
|
+
parameters = request.parameters.to_h.deep_transform_keys(&:underscore).
|
28
|
+
except(*%w(controller action my_service))
|
29
|
+
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters)
|
30
|
+
GrpcRest.assign_params(grpc_request, METHOD_PARAM_MAP["test"], "", request.parameters)
|
31
|
+
render json: GrpcRest.send_request("Testdata::MyService", "test", grpc_request, {:emit_defaults=>true})
|
40
32
|
end
|
41
33
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters
|
46
|
-
GrpcRest.assign_params(grpc_request, METHOD_PARAM_MAP[
|
47
|
-
render json: GrpcRest.send_request(
|
34
|
+
def test2
|
35
|
+
parameters = request.parameters.to_h.deep_transform_keys(&:underscore).
|
36
|
+
except(*%w(controller action my_service))
|
37
|
+
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters)
|
38
|
+
GrpcRest.assign_params(grpc_request, METHOD_PARAM_MAP["test2"], "second_record", request.parameters)
|
39
|
+
render json: GrpcRest.send_request("Testdata::MyService", "test2", grpc_request, {})
|
48
40
|
end
|
49
41
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters
|
54
|
-
GrpcRest.assign_params(grpc_request, METHOD_PARAM_MAP[
|
55
|
-
render json: GrpcRest.send_request(
|
42
|
+
def test3
|
43
|
+
parameters = request.parameters.to_h.deep_transform_keys(&:underscore).
|
44
|
+
except(*%w(controller action my_service))
|
45
|
+
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters)
|
46
|
+
GrpcRest.assign_params(grpc_request, METHOD_PARAM_MAP["test3"], "", request.parameters)
|
47
|
+
render json: GrpcRest.send_request("Testdata::MyService", "test3", grpc_request, {})
|
56
48
|
end
|
57
49
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters
|
62
|
-
GrpcRest.assign_params(grpc_request, METHOD_PARAM_MAP[
|
63
|
-
render json: GrpcRest.send_request(
|
50
|
+
def test4
|
51
|
+
parameters = request.parameters.to_h.deep_transform_keys(&:underscore).
|
52
|
+
except(*%w(controller action my_service))
|
53
|
+
grpc_request = GrpcRest.init_request(Testdata::TestRequest, parameters)
|
54
|
+
GrpcRest.assign_params(grpc_request, METHOD_PARAM_MAP["test4"], "*", request.parameters)
|
55
|
+
render json: GrpcRest.send_request("Testdata::MyService", "test4", grpc_request, {})
|
64
56
|
end
|
57
|
+
|
65
58
|
end
|
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
####### THIS FILE IS AUTOMATICALLY GENERATED BY protoc-gen-rails. DO NOT MODIFY. #######
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
post '/
|
8
|
-
post '/
|
5
|
+
|
6
|
+
get '/test/*foobar' => 'my_service#test'
|
7
|
+
post '/test2' => 'my_service#test2'
|
8
|
+
post '/test3/*sub_id' => 'my_service#test3'
|
9
|
+
post '/test4' => 'my_service#test4'
|
10
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grpc-rest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Orner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-protobuf
|