grpc-rest 0.1.21 → 0.1.24

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '090bea208182dd067a0a1f0347e9cb4484610dca9a7a4f1c2f7689fa216d40e8'
4
- data.tar.gz: 3695746b75dcbba972e88249ad2785551d7e0e4fbd9d8a01140496dfa4f2a002
3
+ metadata.gz: b4e105820176e2fb387f9ff63ae82a086de8d1b291d372f8e8ba3d38dfc34859
4
+ data.tar.gz: 1e480bc608d0524821ba06d408681830294ab34c9e36bd330b881f48128f8e33
5
5
  SHA512:
6
- metadata.gz: 963b26c2d6141a20a3739341bd564005000a7dfdbe42a0bee3becffd04bc1f7d455a692135f21037399e12431c0bba91e73c17b4aa0d4bef6c75944fef4d2782
7
- data.tar.gz: eaad993e480c9a9e7d05c55dedd4a7de06712666b3cd5601b6566bcd5da955a5b30e7528562b117b35297862cc4a6ad3930c8aabcc5eb81bbba6417ab3babae5
6
+ metadata.gz: c8118e6cbb88e44bc3577e66c4639f3e5b87ff18515f1c27d9dd5d458caacac52030f39afbd4a108b2009115b7e28ce9c9c7a810419517f700894538febfe3de
7
+ data.tar.gz: e591ab5d4d0481048f4e61814d1552d83c782f91191fd4f3f1aa430bacfc257aaac2ff3225152767b5acb7e13f1dcc75c42cb86ae93919d6b3cfc483b7bea53d
data/CHANGELOG CHANGED
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## UNRELEASED
9
9
 
10
+ # 0.1.24 - 2024-12-09
11
+ - Log error backtraces.
12
+
13
+ # 0.1.23 - 2024-11-25
14
+ - Fix: Return a 400 status code when payload is invalid JSON
15
+
16
+ # 0.1.22 - 2024-10-31
17
+ - Fix: calling `fail!` in gruf Interceptors was failing with an unrelated exception.
18
+
10
19
  # 0.1.21 - 2024-09-12
11
20
  - Feature: Support gruf Interceptors.
12
21
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- grpc-rest (0.1.21)
4
+ grpc-rest (0.1.22)
5
5
  grpc
6
6
  rails (>= 6.0)
7
7
 
data/README.md CHANGED
@@ -154,9 +154,24 @@ service MyService {
154
154
 
155
155
  ## Gruf Interceptors
156
156
 
157
- grpc-rest supports [gruf](https://github.com/bigcommerce/gruf) Interceptors. As long as you're not using a custom interceptor
157
+ grpc-rest supports [gruf](https://github.com/bigcommerce/gruf) Interceptors through a custom `GrpcRest::BaseInterceptor` class. As long as you're not using a custom interceptor
158
158
  registry, your interceptors will be called normally around the controller.
159
159
 
160
+ ```ruby
161
+ require 'grpc_rest/base_interceptor'
162
+
163
+ module Interceptors
164
+ # Interceptor for catching errors from controllers
165
+ class ErrorInterceptor < GrpcRest::BaseInterceptor
166
+
167
+ def call
168
+ # Your code here
169
+ end
170
+
171
+ end
172
+ end
173
+ ```
174
+
160
175
  ## To Do
161
176
 
162
177
  * Replace Go implementation with Ruby (+ executable)
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'gruf'
4
+
5
+ module GrpcRest
6
+ # Fixes an issue with the fail! method since the active call is not instantiated yet.
7
+ # Overloads https://github.com/bigcommerce/gruf/blob/main/lib/gruf/errors/helpers.rb#L34
8
+ class BaseInterceptor < ::Gruf::Interceptors::ServerInterceptor
9
+ def fail!(error_code, _app_code, message = 'unknown error', metadata = {})
10
+ raise grpc_error(error_code, message.to_s, metadata)
11
+ end
12
+
13
+ private
14
+
15
+ # Ported from https://github.com/flipp-oss/grpc-rest/blob/main/lib/grpc_rest.rb#L142
16
+ def grpc_error(error_code, message, metadata)
17
+ case error_code
18
+ when :ok
19
+ GRPC::Ok.new(message, metadata)
20
+ when 499
21
+ GRPC::Cancelled.new(message, metadata)
22
+ when :bad_request, :invalid_argument
23
+ GRPC::InvalidArgument.new(message, metadata)
24
+ when :gateway_timeout
25
+ GRPC::DeadlineExceeded.new(message, metadata)
26
+ when :not_found
27
+ GRPC::NotFound.new(message, metadata)
28
+ when :conflict
29
+ GRPC::AlreadyExists.new(message, metadata)
30
+ when :forbidden
31
+ GRPC::PermissionDenied.new(message, metadata)
32
+ when :unauthorized
33
+ GRPC::Unauthenticated.new(message, metadata)
34
+ when :too_many_requests
35
+ GRPC::ResourceExhausted.new(message, metadata)
36
+ when :not_implemented
37
+ GRPC::Unimplemented.new(message, metadata)
38
+ when :service_unavailable
39
+ GRPC::Unavailable.new(message, metadata)
40
+ else
41
+ GRPC::Internal.new(message, metadata)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,3 +1,3 @@
1
1
  module GrpcRest
2
- VERSION = '0.1.21'
2
+ VERSION = '0.1.24'
3
3
  end
@@ -63,7 +63,7 @@ class {{.ControllerName}}Controller < ActionController::Base
63
63
  rescue_from GRPC::BadStatus do |e|
64
64
  render json: GrpcRest.error_msg(e), status: GrpcRest.grpc_http_status(e.code)
65
65
  end
66
- rescue_from Google::Protobuf::TypeError do |e|
66
+ rescue_from ActionDispatch::Http::Parameters::ParseError, Google::Protobuf::TypeError do |e|
67
67
  render json: GrpcRest.error_msg(e), status: :bad_request
68
68
  end
69
69
  METHOD_PARAM_MAP = {
@@ -102,20 +102,22 @@ func ProcessService(service *descriptorpb.ServiceDescriptorProto, pkg string) (F
102
102
  return FileResult{}, routes, err
103
103
  }
104
104
  restOpts, err := ExtractRestOptions(m)
105
- if err != nil { return FileResult{}, routes, err }
105
+ if err != nil {
106
+ return FileResult{}, routes, err
107
+ }
106
108
  httpMethod, path, err := MethodAndPath(opts.Pattern)
107
109
  pathInfo, err := ParsedPath(path)
108
110
  if err != nil {
109
111
  return FileResult{}, routes, err
110
112
  }
111
113
  controllerMethod := method{
112
- Name: strcase.ToSnake(m.GetName()),
113
- RequestType: Classify(m.GetInputType()),
114
- Path: path,
115
- RestOptions: rubyRestOptions(restOpts),
116
- HttpMethod: httpMethod,
117
- Body: opts.Body,
118
- PathInfo: pathInfo,
114
+ Name: strcase.ToSnake(m.GetName()),
115
+ RequestType: Classify(m.GetInputType()),
116
+ Path: path,
117
+ RestOptions: rubyRestOptions(restOpts),
118
+ HttpMethod: httpMethod,
119
+ Body: opts.Body,
120
+ PathInfo: pathInfo,
119
121
  }
120
122
  data.Methods = append(data.Methods, controllerMethod)
121
123
  routes = append(routes, Route{
@@ -11,9 +11,10 @@ class MyServiceController < ActionController::Base
11
11
  rescue_from GRPC::BadStatus do |e|
12
12
  render json: GrpcRest.error_msg(e), status: GrpcRest.grpc_http_status(e.code)
13
13
  end
14
- rescue_from Google::Protobuf::TypeError do |e|
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
+
17
18
  METHOD_PARAM_MAP = {
18
19
 
19
20
  "test" => [
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './spec_helper'
4
+ require 'src/proto/grpc/testing/test_services_pb'
5
+
6
+ RSpec.describe GrpcRest::BaseInterceptor, type: :class do
7
+ let(:rpc_service) { Grpc::Testing::TestService::Service.new }
8
+ let(:rpc_desc) { Grpc::Testing::TestService::Service.rpc_descs.values.first}
9
+ let(:message) { Grpc::Testing::SimpleRequest.new }
10
+
11
+ describe '#fail!' do
12
+ let(:error_message) { 'some message' }
13
+ let(:error_code) { :invalid_argument }
14
+
15
+ it 'intercepts and raises the error' do
16
+ request = Gruf::Controllers::Request.new(
17
+ method_key: :UnaryCall,
18
+ service: rpc_service,
19
+ rpc_desc: rpc_desc,
20
+ active_call: nil,
21
+ message: message)
22
+ interceptor = GrpcRest::BaseInterceptor.new(request, Gruf::Error.new)
23
+
24
+ expect{ interceptor.fail!(error_code, error_code, error_message) }.to raise_error(GRPC::InvalidArgument) do |error|
25
+ expect(error.message).to match(error_message)
26
+ expect(error.code).to eq(GRPC::Core::StatusCodes::INVALID_ARGUMENT)
27
+ end
28
+ end
29
+ end
30
+ end
data/spec/spec_helper.rb CHANGED
@@ -17,6 +17,7 @@ loader.inflector.inflect('protoc-gen-openapiv2' => 'ProtocGenOpenapiv2')
17
17
  loader.ignore("#{Rails.root}/spec/test_service_pb.rb")
18
18
  loader.setup
19
19
  require "#{Rails.root}/spec/test_service_pb.rb"
20
+ require "#{Rails.root}/lib/base_interceptor.rb"
20
21
 
21
22
  $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
22
23
 
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.21
4
+ version: 0.1.24
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-09-12 00:00:00.000000000 Z
11
+ date: 2024-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: grpc
@@ -81,6 +81,7 @@ files:
81
81
  - Gemfile.lock
82
82
  - README.md
83
83
  - grpc-rest.gemspec
84
+ - lib/base_interceptor.rb
84
85
  - lib/grpc_rest.rb
85
86
  - lib/grpc_rest/version.rb
86
87
  - protoc-gen-rails/.goreleaser.yml
@@ -101,6 +102,7 @@ files:
101
102
  - protoc-gen-rails/testdata/no_service/.keep
102
103
  - protoc-gen-rails/testdata/test.proto
103
104
  - protoc-gen-rails/testdata/test_service.proto
105
+ - spec/base_interceptor_spec.rb
104
106
  - spec/grpc_rest_spec.rb
105
107
  - spec/gruf_spec.rb
106
108
  - spec/protoc-gen-openapiv2/options/annotations_pb.rb
@@ -132,6 +134,7 @@ signing_key:
132
134
  specification_version: 4
133
135
  summary: Generate Rails controllers and routes from gRPC definitions.
134
136
  test_files:
137
+ - spec/base_interceptor_spec.rb
135
138
  - spec/grpc_rest_spec.rb
136
139
  - spec/gruf_spec.rb
137
140
  - spec/protoc-gen-openapiv2/options/annotations_pb.rb