grpc-rest 0.1.16 → 0.1.18
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 +6 -0
- data/Gemfile.lock +1 -1
- data/lib/grpc_rest/version.rb +1 -1
- data/lib/grpc_rest.rb +35 -2
- data/protoc-gen-rails/testdata/test_service.proto +7 -0
- data/spec/grpc_rest_spec.rb +17 -3
- data/spec/test_service_pb.rb +2 -1
- 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: 8c776db1bb156562864c41be6a4af47debe30d420329359847e71db6b5913711
|
4
|
+
data.tar.gz: 7c4745a5d2dd7e560d0e18b022972473a4487bedf9b9efc4ba387d5cbe42bfc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e7f53b6c264c80f768dd91c0c25da350651cd386d7a51b88f7eedf814d2f0eced41a261ee9e3800ba867fdb69bc4a87ac22700c6b33ae3d50d576555b66875e
|
7
|
+
data.tar.gz: 456d38962848fc73f1c40f0a59336de1d17017e2e138511f046836674a947a11390b20b7180a4b7d4d5befa6f132a23793d5cc7518263a93c1ed0be8255fa246
|
data/CHANGELOG
CHANGED
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
7
7
|
|
8
8
|
## UNRELEASED
|
9
9
|
|
10
|
+
# 0.1.18 - 2024-08-15
|
11
|
+
- Automatically add prefixes to enum values if not provided
|
12
|
+
|
13
|
+
# 0.1.17 - 2024-07-30
|
14
|
+
- Ignore unknown fields in JSON decoding
|
15
|
+
|
10
16
|
# 0.1.16 - 2024-07-09
|
11
17
|
- Support requests in camel case
|
12
18
|
|
data/Gemfile.lock
CHANGED
data/lib/grpc_rest/version.rb
CHANGED
data/lib/grpc_rest.rb
CHANGED
@@ -37,12 +37,45 @@ module GrpcRest
|
|
37
37
|
proto.public_send(:"#{tokens.last}=", value) if proto.respond_to?(:"#{tokens.last}=")
|
38
38
|
end
|
39
39
|
|
40
|
+
# https://stackoverflow.com/a/2158473/5199431
|
41
|
+
def longest_common_substring(arr)
|
42
|
+
return "" if arr.empty?
|
43
|
+
|
44
|
+
result = 0
|
45
|
+
first_val = arr[0]
|
46
|
+
(0...first_val.length).each do |k|
|
47
|
+
all_matched = true
|
48
|
+
character = first_val[k]
|
49
|
+
arr.each { |str| all_matched &= (character == str[k]) }
|
50
|
+
break unless all_matched
|
51
|
+
result += 1
|
52
|
+
end
|
53
|
+
first_val.slice(0, result)
|
54
|
+
end
|
55
|
+
|
56
|
+
def handle_enum_values(descriptor, value)
|
57
|
+
names = descriptor.subtype.to_h.keys.map(&:to_s)
|
58
|
+
prefix = longest_common_substring(names)
|
59
|
+
if prefix.present? && !value.starts_with?(prefix)
|
60
|
+
"#{prefix}#{value}"
|
61
|
+
else
|
62
|
+
value
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
40
66
|
def map_proto_type(proto, params)
|
41
67
|
proto.to_a.each do |descriptor|
|
42
68
|
field = descriptor.name
|
43
69
|
val = params[field]
|
44
70
|
next if val.nil?
|
45
|
-
|
71
|
+
if descriptor.subtype.is_a?(Google::Protobuf::EnumDescriptor)
|
72
|
+
if descriptor.label == :repeated
|
73
|
+
params[field] = val.map { |v| handle_enum_values(descriptor, v)}
|
74
|
+
else
|
75
|
+
params[field] = handle_enum_values(descriptor, val)
|
76
|
+
end
|
77
|
+
next
|
78
|
+
end
|
46
79
|
|
47
80
|
case descriptor.type
|
48
81
|
when *%i(int32 int64 uint32 uint64 sint32 sint64 fixed32 fixed64 sfixed32 sfixed64)
|
@@ -80,7 +113,7 @@ module GrpcRest
|
|
80
113
|
|
81
114
|
def init_request(request_class, params)
|
82
115
|
map_proto_type(request_class.descriptor, params)
|
83
|
-
request_class.decode_json(JSON.generate(params))
|
116
|
+
request_class.decode_json(JSON.generate(params), ignore_unknown_fields: true)
|
84
117
|
end
|
85
118
|
|
86
119
|
def assign_params(request, param_hash, body_string, params)
|
@@ -18,6 +18,7 @@ message TestRequest {
|
|
18
18
|
google.protobuf.Value bare_value = 9;
|
19
19
|
repeated SubRecord sub_records = 10;
|
20
20
|
int32 some_int = 11;
|
21
|
+
TestEnum some_enum = 12;
|
21
22
|
}
|
22
23
|
|
23
24
|
message SubRecord {
|
@@ -30,6 +31,12 @@ message TestResponse {
|
|
30
31
|
string full_response = 2;
|
31
32
|
}
|
32
33
|
|
34
|
+
enum TestEnum {
|
35
|
+
TEST_ENUM_UNSPECIFIED = 0;
|
36
|
+
TEST_ENUM_FOO = 1;
|
37
|
+
TEST_ENUM_BAR = 2;
|
38
|
+
}
|
39
|
+
|
33
40
|
service MyService {
|
34
41
|
rpc Test(TestRequest) returns (TestResponse) {
|
35
42
|
option (google.api.http) = {
|
data/spec/grpc_rest_spec.rb
CHANGED
@@ -63,8 +63,8 @@ RSpec.describe MyServiceController, type: :request do
|
|
63
63
|
end
|
64
64
|
|
65
65
|
describe 'full body splat' do
|
66
|
-
|
67
|
-
|
66
|
+
let(:params) do
|
67
|
+
{
|
68
68
|
test_id: 'abc',
|
69
69
|
some_int: "65",
|
70
70
|
foobar: 'xyz',
|
@@ -91,12 +91,26 @@ RSpec.describe MyServiceController, type: :request do
|
|
91
91
|
list_value: ['F', 'Y', 'I'],
|
92
92
|
bare_value: 45,
|
93
93
|
timestamp_field: '2024-04-03 01:02:03 UTC',
|
94
|
+
some_enum: 'TEST_ENUM_FOO'
|
94
95
|
}
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should be successful' do
|
99
|
+
post '/test4', params: params, as: :json
|
100
|
+
expect(response).to be_successful
|
101
|
+
expect(response.parsed_body).to eq({
|
102
|
+
'someInt' => 4,
|
103
|
+
'fullResponse' => %({"testId":"abc","foobar":"xyz","repeatedString":["W","T","F"],"subRecord":{"subId":"id1","anotherId":"id2"},"secondRecord":{"subId":"id3","anotherId":"id4"},"structField":{"bool_key":true,"str_key":"val","nil_key":null,"list_key":[{"inner_key":"inner_val"}],"int_key":123},"timestampField":"2024-04-03T01:02:03Z","listValue":["F","Y","I"],"bareValue":45,"someInt":65,"someEnum":"TEST_ENUM_FOO"})
|
104
|
+
})
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should be successful without the enum prefix' do
|
108
|
+
params[:some_enum] = 'FOO'
|
95
109
|
post '/test4', params: params, as: :json
|
96
110
|
expect(response).to be_successful
|
97
111
|
expect(response.parsed_body).to eq({
|
98
112
|
'someInt' => 4,
|
99
|
-
'fullResponse' => %({"testId":"abc","foobar":"xyz","repeatedString":["W","T","F"],"subRecord":{"subId":"id1","anotherId":"id2"},"secondRecord":{"subId":"id3","anotherId":"id4"},"structField":{"bool_key":true,"str_key":"val","nil_key":null,"list_key":[{"inner_key":"inner_val"}],"int_key":123},"timestampField":"2024-04-03T01:02:03Z","listValue":["F","Y","I"],"bareValue":45
|
113
|
+
'fullResponse' => %({"testId":"abc","foobar":"xyz","repeatedString":["W","T","F"],"subRecord":{"subId":"id1","anotherId":"id2"},"secondRecord":{"subId":"id3","anotherId":"id4"},"structField":{"bool_key":true,"str_key":"val","nil_key":null,"list_key":[{"inner_key":"inner_val"}],"int_key":123},"timestampField":"2024-04-03T01:02:03Z","listValue":["F","Y","I"],"bareValue":45,"someInt":65,"someEnum":"TEST_ENUM_FOO"})
|
100
114
|
})
|
101
115
|
end
|
102
116
|
end
|
data/spec/test_service_pb.rb
CHANGED
@@ -9,7 +9,7 @@ require 'google/protobuf/struct_pb'
|
|
9
9
|
require 'google/protobuf/timestamp_pb'
|
10
10
|
|
11
11
|
|
12
|
-
descriptor_data = "\n\x12test_service.proto\x12\x08testdata\x1a\x1cgoogle/api/annotations.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\
|
12
|
+
descriptor_data = "\n\x12test_service.proto\x12\x08testdata\x1a\x1cgoogle/api/annotations.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xbf\x03\n\x0bTestRequest\x12\x0f\n\x07test_id\x18\x01 \x01(\t\x12\x0e\n\x06\x66oobar\x18\x02 \x01(\t\x12\x17\n\x0frepeated_string\x18\x03 \x03(\t\x12\'\n\nsub_record\x18\x04 \x01(\x0b\x32\x13.testdata.SubRecord\x12*\n\rsecond_record\x18\x05 \x01(\x0b\x32\x13.testdata.SubRecord\x12-\n\x0cstruct_field\x18\x06 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x33\n\x0ftimestamp_field\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nlist_value\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.ListValue\x12*\n\nbare_value\x18\t \x01(\x0b\x32\x16.google.protobuf.Value\x12(\n\x0bsub_records\x18\n \x03(\x0b\x32\x13.testdata.SubRecord\x12\x10\n\x08some_int\x18\x0b \x01(\x05\x12%\n\tsome_enum\x18\x0c \x01(\x0e\x32\x12.testdata.TestEnum\"/\n\tSubRecord\x12\x0e\n\x06sub_id\x18\x01 \x01(\t\x12\x12\n\nanother_id\x18\x02 \x01(\t\"7\n\x0cTestResponse\x12\x10\n\x08some_int\x18\x01 \x01(\x05\x12\x15\n\rfull_response\x18\x02 \x01(\t*K\n\x08TestEnum\x12\x19\n\x15TEST_ENUM_UNSPECIFIED\x10\x00\x12\x11\n\rTEST_ENUM_FOO\x10\x01\x12\x11\n\rTEST_ENUM_BAR\x10\x02\x32\xdf\x02\n\tMyService\x12T\n\x04Test\x12\x15.testdata.TestRequest\x1a\x16.testdata.TestResponse\"\x1d\x82\xd3\xe4\x93\x02\x17\x12\x15/test/{foobar=blah/*}\x12U\n\x05Test2\x12\x15.testdata.TestRequest\x1a\x16.testdata.TestResponse\"\x1d\x82\xd3\xe4\x93\x02\x17\"\x06/test2:\rsecond_record\x12Z\n\x05Test3\x12\x15.testdata.TestRequest\x1a\x16.testdata.TestResponse\"\"\x82\xd3\xe4\x93\x02\x1c\"\x1a/test3/{sub_record.sub_id}\x12I\n\x05Test4\x12\x15.testdata.TestRequest\x1a\x16.testdata.TestResponse\"\x11\x82\xd3\xe4\x93\x02\x0b\"\x06/test4:\x01*b\x06proto3"
|
13
13
|
|
14
14
|
pool = Google::Protobuf::DescriptorPool.generated_pool
|
15
15
|
pool.add_serialized_file(descriptor_data)
|
@@ -18,4 +18,5 @@ module Testdata
|
|
18
18
|
TestRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("testdata.TestRequest").msgclass
|
19
19
|
SubRecord = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("testdata.SubRecord").msgclass
|
20
20
|
TestResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("testdata.TestResponse").msgclass
|
21
|
+
TestEnum = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("testdata.TestEnum").enummodule
|
21
22
|
end
|
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.1.
|
4
|
+
version: 0.1.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Orner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-08-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: grpc
|