diff --git a/CHANGELOG b/CHANGELOG index 928fb13..853b53b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## UNRELEASED +- Feature: Support gruf Interceptors. + # 0.1.20 - 2024-09-10 - Fix: Repeated float values weren't being treated as arrays and were crashing. diff --git a/Gemfile.lock b/Gemfile.lock index e0fd507..ba19079 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -91,8 +91,18 @@ GEM grpc (1.62.0-x86_64-linux) google-protobuf (~> 3.25) googleapis-common-protos-types (~> 1.0) + grpc-tools (1.64.0) + gruf (2.20.0) + activesupport (> 4) + concurrent-ruby (> 1) + grpc (~> 1.10) + grpc-tools (~> 1.10) + json (>= 2.3) + slop (>= 4.6) + zeitwerk (>= 2) i18n (1.14.4) concurrent-ruby (~> 1.0) + json (2.7.2) loofah (2.22.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) @@ -169,6 +179,7 @@ GEM rspec-mocks (~> 3.13) rspec-support (~> 3.13) rspec-support (3.13.1) + slop (4.10.1) thor (1.3.1) timeout (0.4.1) tzinfo (2.0.6) @@ -184,6 +195,7 @@ PLATFORMS DEPENDENCIES grpc-rest! + gruf rspec-rails BUNDLED WITH diff --git a/README.md b/README.md index 1681573..6e49abe 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,10 @@ service MyService { } ``` +## Gruf Interceptors + +grpc-rest supports [gruf](https://github.com/bigcommerce/gruf) Interceptors. As long as you're not using a custom interceptor +registry, your interceptors will be called normally around the controller. ## To Do diff --git a/grpc-rest.gemspec b/grpc-rest.gemspec index 27afd40..9c9c2ed 100644 --- a/grpc-rest.gemspec +++ b/grpc-rest.gemspec @@ -22,4 +22,5 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency('rails', '>= 6.0') spec.add_development_dependency('rspec-rails') + spec.add_development_dependency('gruf') end diff --git a/lib/grpc_rest.rb b/lib/grpc_rest.rb index 62d2fce..28fd3a2 100644 --- a/lib/grpc_rest.rb +++ b/lib/grpc_rest.rb @@ -203,7 +203,18 @@ def send_gruf_request(klass, service_obj, method, request) active_call: nil, message: request ) - handler.send(method.to_sym) + Gruf::Interceptors::Context.new(gruf_interceptors(request)).intercept! do + handler.send(method.to_sym) + end + end + + # @param request [Google::Protobuf::AbstractMessage] + # @return [Array] + def gruf_interceptors(request) + error = Gruf::Error.new + interceptors = Gruf.interceptors.prepare(request, error) + interceptors.delete_if { |k| k.class.name.split('::').first == 'Gruf' } + interceptors end def send_grpc_request(service, method, request) diff --git a/spec/gruf_spec.rb b/spec/gruf_spec.rb new file mode 100644 index 0000000..ed5d3ce --- /dev/null +++ b/spec/gruf_spec.rb @@ -0,0 +1,51 @@ +require_relative './spec_helper' +require_relative './test_service_services_pb' +require 'gruf' + +class GrufServerImpl < Gruf::Controllers::Base + + bind ::Testdata::MyService::Service + + def test + Testdata::TestResponse.new(some_int: 1, full_response: request.message.to_json) + end + + def test_2 + Testdata::TestResponse.new(some_int: 2, full_response: request.message.to_json) + end + + def test_3 + Testdata::TestResponse.new(some_int: 3, full_response: request.message.to_json) + end + + def test_4 + Testdata::TestResponse.new(some_int: 4, full_response: request.message.to_json) + end + + cattr_accessor :intercepted +end + +class TestInterceptor < ::Gruf::Interceptors::ServerInterceptor + def call + GrufServerImpl.intercepted = true + yield + end +end + +Gruf::Server.new.add_interceptor(TestInterceptor, option_foo: 'value 123') + +RSpec.describe MyServiceController, type: :request do + describe 'using get' do + it 'should be successful and call interceptors' do + GrufServerImpl.intercepted = false + get "/test/blah/xyz?test_id=abc" + expect(response).to be_successful + expect(response.parsed_body).to eq({ + 'someInt' => 1, + 'fullResponse' => %({"testId":"abc","foobar":"xyz"}), + "ignoredKey" => '' + }) + expect(GrufServerImpl.intercepted).to eq(true) + end + end +end