tshield 0.11.10.0 → 0.11.16.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/Gemfile +0 -1
- data/README.md +37 -6
- data/Rakefile +1 -1
- data/bin/tshield +2 -11
- data/config/tshield.yml +7 -0
- data/lib/tshield.rb +1 -1
- data/lib/tshield/configuration.rb +5 -0
- data/lib/tshield/controllers/requests.rb +3 -3
- data/lib/tshield/extensions/string_extensions.rb +8 -0
- data/lib/tshield/grpc.rb +73 -0
- data/lib/tshield/grpc/vcr.rb +70 -0
- data/lib/tshield/server.rb +18 -1
- data/lib/tshield/version.rb +1 -1
- data/spec/spec_helper.rb +0 -5
- data/spec/tshield/configuration_spec.rb +19 -0
- data/spec/tshield/fixtures/config/tshield-without-grpc.yml +17 -0
- data/spec/tshield/fixtures/config/tshield.yml +2 -0
- data/spec/tshield/fixtures/proto/test_services_pb.rb +13 -0
- data/spec/tshield/grpc_spec.rb +24 -0
- data/tshield.gemspec +5 -1
- metadata +96 -9
- data/lib/tshield/simple_tcp_server.rb +0 -28
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 6430dfd31f893ec3e51fc02ad401ea29f9dbcfa09c9b34a30ef4e23b7b9a3216
         | 
| 4 | 
            +
              data.tar.gz: 1f021ab7cc8688ee6ab077140d34dd239a76a578c0c738b639a974d36d91d48d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: b86bd18dc24834098e199e179d33a92b74b29a55fa495685e2939196c6f4be9558a324ee7b63590363bf3c0ec5deb512073c172ac828a2eea6f19f3ed842d77d
         | 
| 7 | 
            +
              data.tar.gz: 597db12ad099b8024841fd6f6e9d5b9eb2954750d617382c95654a930273558b44c18fc4f8a3ea67b3d9d66a7820b1dc2ddfe462b2eac591de67683db3c213f3
         | 
    
        data/Gemfile
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -13,9 +13,10 @@ TShield is an open source proxy for mocks API responses. | |
| 13 13 | 
             
            *   REST
         | 
| 14 14 | 
             
            *   SOAP
         | 
| 15 15 | 
             
            *   Session manager to separate multiple scenarios (success, error, sucess variation, ...)
         | 
| 16 | 
            +
                gRPC [EXPERIMENTAL]
         | 
| 16 17 | 
             
            *   Lightweight
         | 
| 17 18 | 
             
            *   MIT license
         | 
| 18 | 
            -
             | 
| 19 | 
            +
             | 
| 19 20 | 
             
            ## Table of Contents
         | 
| 20 21 |  | 
| 21 22 | 
             
            *   [Basic Usage](#basic-usage)
         | 
| @@ -26,7 +27,7 @@ TShield is an open source proxy for mocks API responses. | |
| 26 27 | 
             
            *   [Features](#features)
         | 
| 27 28 | 
             
            *   [Examples](#examples)
         | 
| 28 29 | 
             
            *   [Contributing](#contributing)
         | 
| 29 | 
            -
             | 
| 30 | 
            +
             | 
| 30 31 | 
             
            ## Basic Usage
         | 
| 31 32 | 
             
            ### Install
         | 
| 32 33 |  | 
| @@ -37,7 +38,7 @@ TShield is an open source proxy for mocks API responses. | |
| 37 38 | 
             
            To run server execute this command
         | 
| 38 39 |  | 
| 39 40 | 
             
                tshield
         | 
| 40 | 
            -
             | 
| 41 | 
            +
             | 
| 41 42 | 
             
            Default port is `4567`
         | 
| 42 43 |  | 
| 43 44 | 
             
            #### Command Line Options
         | 
| @@ -102,7 +103,7 @@ To register stub into a session create an object with following attributes: | |
| 102 103 | 
             
            *   **session**: name of session.
         | 
| 103 104 | 
             
            *   **stubs**: an array with objects described above.
         | 
| 104 105 |  | 
| 105 | 
            -
            ### Example of matching configuration
         | 
| 106 | 
            +
            ### Example of HTTP matching configuration
         | 
| 106 107 |  | 
| 107 108 | 
             
            ```json
         | 
| 108 109 | 
             
            [
         | 
| @@ -163,7 +164,7 @@ To register stub into a session create an object with following attributes: | |
| 163 164 | 
             
            ]
         | 
| 164 165 | 
             
            ```
         | 
| 165 166 |  | 
| 166 | 
            -
            ## Config options for VCR
         | 
| 167 | 
            +
            ## Config options for HTTP VCR
         | 
| 167 168 | 
             
            ```yaml
         | 
| 168 169 | 
             
            request:
         | 
| 169 170 | 
             
              timeout: 8
         | 
| @@ -227,7 +228,7 @@ You can use TShield sessions to separate multiple scenarios for your mocks | |
| 227 228 | 
             
            By default TShield save request/response into 
         | 
| 228 229 |  | 
| 229 230 | 
             
                requests/<<domain_name>>/<<resource_with_param>>/<<http_verb>>/<<index_based.content and json>>
         | 
| 230 | 
            -
             | 
| 231 | 
            +
             | 
| 231 232 | 
             
            If you start a session a folder with de **session_name** will be placed between **"requests/"** and **"<<domain_name>>"**
         | 
| 232 233 |  | 
| 233 234 | 
             
            ### Start TShield session
         | 
| @@ -249,6 +250,36 @@ _DELETE_ to http://localhost:4567/sessions | |
| 249 250 | 
             
            curl -X DELETE \
         | 
| 250 251 | 
             
              http://localhost:4567/sessions
         | 
| 251 252 | 
             
            ```
         | 
| 253 | 
            +
            ## [Experimental] Config options for gRPC
         | 
| 254 | 
            +
             | 
| 255 | 
            +
            ```yaml
         | 
| 256 | 
            +
            grpc:
         | 
| 257 | 
            +
              port: 5678
         | 
| 258 | 
            +
              proto_dir: 'proto'
         | 
| 259 | 
            +
              services:
         | 
| 260 | 
            +
                'helloworld_services_pb': 
         | 
| 261 | 
            +
                  module: 'Helloworld::Greeter'
         | 
| 262 | 
            +
                  hostname: '0.0.0.0:50051'
         | 
| 263 | 
            +
            ```
         | 
| 264 | 
            +
             | 
| 265 | 
            +
             | 
| 266 | 
            +
            ### Not Implemented Yet 
         | 
| 267 | 
            +
             | 
| 268 | 
            +
            - Sessions
         | 
| 269 | 
            +
            - Matching
         | 
| 270 | 
            +
             | 
| 271 | 
            +
            ### Configuration
         | 
| 272 | 
            +
             | 
| 273 | 
            +
            First, generate ruby files from proto files. Use `grpc_tools_ruby_protoc`
         | 
| 274 | 
            +
            present in the gem `grpc-tools`. Example:
         | 
| 275 | 
            +
             | 
| 276 | 
            +
            `grpc_tools_ruby_protoc -I proto --ruby_out=proto --grpc_out=proto proto/<INPUT>.proto`
         | 
| 277 | 
            +
             | 
| 278 | 
            +
            Call example in component_tests using [grpcurl](https://github.com/fullstorydev/grpcurl):
         | 
| 279 | 
            +
             | 
| 280 | 
            +
            `grpcurl -plaintext -import-path component_tests/proto -proto helloworld.proto  -d '{"name": "teste"}' localhost:5678 helloworld.Greeter/SayHello`
         | 
| 281 | 
            +
             | 
| 282 | 
            +
            ### Using in VCR mode
         | 
| 252 283 |  | 
| 253 284 | 
             
            ## Custom controllers
         | 
| 254 285 |  | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/bin/tshield
    CHANGED
    
    | @@ -5,14 +5,5 @@ require 'tshield/options' | |
| 5 5 | 
             
            TShield::Options.init
         | 
| 6 6 |  | 
| 7 7 | 
             
            require 'tshield'
         | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
            configuration = TShield::Configuration.load_configuration
         | 
| 11 | 
            -
            (configuration.tcp_servers || []).each do |tcp_server|
         | 
| 12 | 
            -
              puts "initializing #{tcp_server['name']}"
         | 
| 13 | 
            -
              require "./servers/#{tcp_server['file']}"
         | 
| 14 | 
            -
              klass = Object.const_get(tcp_server['name'])
         | 
| 15 | 
            -
              Thread.new { klass.new.listen(tcp_server['port']) }
         | 
| 16 | 
            -
            end
         | 
| 17 | 
            -
             | 
| 18 | 
            -
            tshield.join
         | 
| 8 | 
            +
            Thread.new { TShield::Server.run! }
         | 
| 9 | 
            +
            TShield::Grpc.run!
         | 
    
        data/config/tshield.yml
    CHANGED
    
    
    
        data/lib/tshield.rb
    CHANGED
    
    
| @@ -103,6 +103,11 @@ module TShield | |
| 103 103 | 
             
                  session_path || '/sessions'
         | 
| 104 104 | 
             
                end
         | 
| 105 105 |  | 
| 106 | 
            +
                def grpc
         | 
| 107 | 
            +
                  defaults = { 'port' => 5678, 'proto_dir' => 'proto', 'services' => {} }
         | 
| 108 | 
            +
                  defaults.merge(@grpc || {})
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
             | 
| 106 111 | 
             
                def self.get_url_for_domain_by_path(path, config)
         | 
| 107 112 | 
             
                  config['paths'].select { |pattern| path =~ Regexp.new(pattern) }[0]
         | 
| 108 113 | 
             
                end
         | 
| @@ -65,7 +65,7 @@ module TShield | |
| 65 65 | 
             
                      api_response = TShield::RequestMatching.new(path, options.clone).match_request
         | 
| 66 66 |  | 
| 67 67 | 
             
                      unless api_response
         | 
| 68 | 
            -
                        add_headers( | 
| 68 | 
            +
                        add_headers(options, path)
         | 
| 69 69 |  | 
| 70 70 | 
             
                        api_response ||= TShield::RequestVCR.new(path, options.clone).response
         | 
| 71 71 | 
             
                        api_response.headers.reject! do |key, _v|
         | 
| @@ -85,9 +85,9 @@ module TShield | |
| 85 85 | 
             
                      body api_response.body
         | 
| 86 86 | 
             
                    end
         | 
| 87 87 |  | 
| 88 | 
            -
                    def add_headers( | 
| 88 | 
            +
                    def add_headers(options, path)
         | 
| 89 89 | 
             
                      (configuration.get_headers(domain(path)) || {}).each do |source, destiny|
         | 
| 90 | 
            -
                        headers[destiny] = request.env[source] if request.env[source]
         | 
| 90 | 
            +
                        options[:headers][destiny] = request.env[source] if request.env[source]
         | 
| 91 91 | 
             
                      end
         | 
| 92 92 | 
             
                    end
         | 
| 93 93 |  | 
| @@ -5,6 +5,14 @@ module StringExtensions | |
| 5 5 | 
             
              def to_rack_name
         | 
| 6 6 | 
             
                "HTTP_#{upcase.tr('-', '_')}"
         | 
| 7 7 | 
             
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              def underscore
         | 
| 10 | 
            +
                gsub(/::/, '/')
         | 
| 11 | 
            +
                  .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
         | 
| 12 | 
            +
                  .gsub(/([a-z\d])([A-Z])/, '\1_\2')
         | 
| 13 | 
            +
                  .tr('-', '_')
         | 
| 14 | 
            +
                  .downcase
         | 
| 15 | 
            +
              end
         | 
| 8 16 | 
             
            end
         | 
| 9 17 |  | 
| 10 18 | 
             
            String.include StringExtensions
         | 
    
        data/lib/tshield/grpc.rb
    ADDED
    
    | @@ -0,0 +1,73 @@ | |
| 1 | 
            +
            # frozen_string_literal: false
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'grpc'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require 'tshield/configuration'
         | 
| 6 | 
            +
            require 'tshield/sessions'
         | 
| 7 | 
            +
            require 'tshield/grpc/vcr'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            module TShield
         | 
| 10 | 
            +
              module Grpc
         | 
| 11 | 
            +
                module RequestHandler
         | 
| 12 | 
            +
                  include TShield::Grpc::VCR
         | 
| 13 | 
            +
                  def handler(method_name, request)
         | 
| 14 | 
            +
                    options = self.class.options
         | 
| 15 | 
            +
                    handler_in_vcr_mode(method_name, request, options)
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
                def self.run!
         | 
| 19 | 
            +
                  @configuration = TShield::Configuration.singleton.grpc
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  lib_dir = File.join(Dir.pwd, @configuration['proto_dir'])
         | 
| 22 | 
            +
                  $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  TShield.logger.info("loading proto files from #{lib_dir}")
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  bind = "0.0.0.0:#{@configuration['port']}"
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  server = GRPC::RpcServer.new
         | 
| 29 | 
            +
                  server.add_http2_port(bind, :this_port_is_insecure)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  services = load_services(@configuration['services'])
         | 
| 32 | 
            +
                  services.each do |class_service|
         | 
| 33 | 
            +
                    class_service.include RequestHandler
         | 
| 34 | 
            +
                    server.handle(class_service)
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  server.run_till_terminated_or_interrupted([1, 'int', 'SIGQUIT']) unless services.empty?
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                def self.load_services(services)
         | 
| 41 | 
            +
                  handlers = []
         | 
| 42 | 
            +
                  number_of_handlers = 0
         | 
| 43 | 
            +
                  services.each do |file, options|
         | 
| 44 | 
            +
                    require file
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    base = Object.const_get("#{options['module']}::Service")
         | 
| 47 | 
            +
                    number_of_handlers += 1
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    implementation = build_handler(base, base.rpc_descs, number_of_handlers, options)
         | 
| 50 | 
            +
                    handlers << implementation
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                  handlers
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                def self.build_handler(base, descriptions, number_of_handlers, options)
         | 
| 56 | 
            +
                  handler = Class.new(base) do
         | 
| 57 | 
            +
                    class << self
         | 
| 58 | 
            +
                      attr_writer :options
         | 
| 59 | 
            +
                      attr_reader :options
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
                    descriptions.each do |service_name, description|
         | 
| 62 | 
            +
                      puts description
         | 
| 63 | 
            +
                      method_name = service_name.to_s.underscore.to_sym
         | 
| 64 | 
            +
                      define_method(method_name) do |request, _unused_call|
         | 
| 65 | 
            +
                        handler(__method__, request)
         | 
| 66 | 
            +
                      end
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
                  handler.options = options
         | 
| 70 | 
            +
                  TShield::Grpc.const_set "GrpcService#{number_of_handlers}", handler
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
            end
         | 
| @@ -0,0 +1,70 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module TShield
         | 
| 4 | 
            +
              module Grpc
         | 
| 5 | 
            +
                module VCR
         | 
| 6 | 
            +
                  def handler_in_vcr_mode(method_name, request, options)
         | 
| 7 | 
            +
                    module_name = options['module']
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    response = saved_response(module_name, method_name, request)
         | 
| 10 | 
            +
                    return response if response
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    client_class = Object.const_get("#{module_name}::Stub")
         | 
| 13 | 
            +
                    client_instance = client_class.new(options['hostname'], :this_channel_is_insecure)
         | 
| 14 | 
            +
                    response = client_instance.send(method_name, request)
         | 
| 15 | 
            +
                    save_request_and_response(request, response)
         | 
| 16 | 
            +
                    response
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  def saved_response(module_name, method_name, request)
         | 
| 20 | 
            +
                    create_destiny(module_name, method_name, request)
         | 
| 21 | 
            +
                    response_file = File.join(@complete_path, 'response')
         | 
| 22 | 
            +
                    return false unless File.exist? response_file
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    content = JSON.parse File.open(response_file).read
         | 
| 25 | 
            +
                    response_class = File.open(File.join(@complete_path, 'response_class')).read.strip
         | 
| 26 | 
            +
                    Kernel.const_get(response_class).new(content)
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  def save_request_and_response(request, response)
         | 
| 30 | 
            +
                    save_request(request)
         | 
| 31 | 
            +
                    save_response(response)
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  def save_request(request)
         | 
| 35 | 
            +
                    file = File.open(File.join(@complete_path, 'original_request'), 'w')
         | 
| 36 | 
            +
                    file.puts request.to_json
         | 
| 37 | 
            +
                    file.close
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def save_response(response)
         | 
| 41 | 
            +
                    file = File.open(File.join(@complete_path, 'response'), 'w')
         | 
| 42 | 
            +
                    file.puts response.to_json
         | 
| 43 | 
            +
                    file.close
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    response_class = File.open(File.join(@complete_path, 'response_class'), 'w')
         | 
| 46 | 
            +
                    response_class.puts response.class.to_s
         | 
| 47 | 
            +
                    response_class.close
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  def complete_path(module_name, method_name, request)
         | 
| 51 | 
            +
                    return @complete_path if @complete_path
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    @complete_path = ['requests', 'grpc', module_name, method_name.to_s, hexdigest(request)]
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  def create_destiny(module_name, method_name, request)
         | 
| 57 | 
            +
                    current_path = []
         | 
| 58 | 
            +
                    complete_path(module_name, method_name, request).each do |path|
         | 
| 59 | 
            +
                      current_path << path
         | 
| 60 | 
            +
                      destiny = File.join current_path
         | 
| 61 | 
            +
                      Dir.mkdir destiny unless File.exist? destiny
         | 
| 62 | 
            +
                    end
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  def hexdigest(request)
         | 
| 66 | 
            +
                    Digest::SHA1.hexdigest request.to_json
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
            end
         | 
    
        data/lib/tshield/server.rb
    CHANGED
    
    | @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            # frozen_string_literal: false
         | 
| 2 2 |  | 
| 3 3 | 
             
            require 'sinatra'
         | 
| 4 | 
            +
            require 'sinatra/cross_origin'
         | 
| 4 5 |  | 
| 5 6 | 
             
            require 'tshield/options'
         | 
| 6 7 | 
             
            require 'tshield/controllers/requests'
         | 
| @@ -16,6 +17,23 @@ module TShield | |
| 16 17 | 
             
                set :views, File.join(File.dirname(__FILE__), 'views')
         | 
| 17 18 | 
             
                set :bind, '0.0.0.0'
         | 
| 18 19 | 
             
                set :port, TShield::Options.instance.port
         | 
| 20 | 
            +
                set :server, :puma
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                configure do
         | 
| 23 | 
            +
                  enable :cross_origin
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                before do
         | 
| 27 | 
            +
                  response.headers['Access-Control-Allow-Origin'] = '*'
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                options '*' do
         | 
| 31 | 
            +
                  response.headers['Allow'] = 'GET, PUT, POST, DELETE, OPTIONS'
         | 
| 32 | 
            +
                  response.headers['Access-Control-Allow-Headers'] = 'Authorization, Content-Type,
         | 
| 33 | 
            +
                                                                    Accept, X-User-Email, X-Auth-Token'
         | 
| 34 | 
            +
                  response.headers['Access-Control-Allow-Origin'] = '*'
         | 
| 35 | 
            +
                  200
         | 
| 36 | 
            +
                end
         | 
| 19 37 |  | 
| 20 38 | 
             
                def self.register_resources
         | 
| 21 39 | 
             
                  load_controllers
         | 
| @@ -39,7 +57,6 @@ module TShield | |
| 39 57 |  | 
| 40 58 | 
             
                def self.run!
         | 
| 41 59 | 
             
                  register_resources
         | 
| 42 | 
            -
                  require 'byebug'
         | 
| 43 60 | 
             
                  super
         | 
| 44 61 | 
             
                end
         | 
| 45 62 | 
             
              end
         | 
    
        data/lib/tshield/version.rb
    CHANGED
    
    
    
        data/spec/spec_helper.rb
    CHANGED
    
    
| @@ -35,6 +35,12 @@ describe TShield::Configuration do | |
| 35 35 | 
             
                    )
         | 
| 36 36 | 
             
                  end
         | 
| 37 37 |  | 
| 38 | 
            +
                  context 'on grpc configuration' do
         | 
| 39 | 
            +
                    it 'recover server port' do
         | 
| 40 | 
            +
                      expect(@configuration.grpc['port']).to(eq(5678))
         | 
| 41 | 
            +
                    end
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 38 44 | 
             
                  context 'on load filters' do
         | 
| 39 45 | 
             
                    it 'recover filters for a domain' do
         | 
| 40 46 | 
             
                      expect(@configuration.get_filters('example.org')).to eq([ExampleFilter])
         | 
| @@ -72,4 +78,17 @@ describe TShield::Configuration do | |
| 72 78 | 
             
                  expect { TShield::Configuration.singleton }.to raise_error RuntimeError
         | 
| 73 79 | 
             
                end
         | 
| 74 80 | 
             
              end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
              context 'on config exists without grpc entry' do
         | 
| 83 | 
            +
                before :each do
         | 
| 84 | 
            +
                  options_instance = double
         | 
| 85 | 
            +
                  allow(options_instance).to receive(:configuration_file)
         | 
| 86 | 
            +
                    .and_return('spec/tshield/fixtures/config/tshield-without-grpc.yml')
         | 
| 87 | 
            +
                  allow(TShield::Options).to receive(:instance).and_return(options_instance)
         | 
| 88 | 
            +
                  @configuration = TShield::Configuration.singleton
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
                it 'should set default value for port' do
         | 
| 91 | 
            +
                  expect(@configuration.grpc).to eql('port' => 5678, 'proto_dir' => 'proto', 'services' => {})
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
              end
         | 
| 75 94 | 
             
            end
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            request:
         | 
| 3 | 
            +
              timeout: 0
         | 
| 4 | 
            +
            domains:
         | 
| 5 | 
            +
              'example.org':
         | 
| 6 | 
            +
                name: 'example.org'
         | 
| 7 | 
            +
                filters:
         | 
| 8 | 
            +
                  - 'ExampleFilter'
         | 
| 9 | 
            +
                paths:
         | 
| 10 | 
            +
                  - '/api/one'
         | 
| 11 | 
            +
                  - '/api/two'
         | 
| 12 | 
            +
                skip_query_params:
         | 
| 13 | 
            +
                  - 'a'
         | 
| 14 | 
            +
              'example.com':
         | 
| 15 | 
            +
                name: 'example.com'
         | 
| 16 | 
            +
                paths:
         | 
| 17 | 
            +
                  - '/api/three'
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'spec_helper'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require 'tshield/grpc'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            describe TShield::Grpc do
         | 
| 8 | 
            +
              context 'on load services' do
         | 
| 9 | 
            +
                before :each do
         | 
| 10 | 
            +
                  lib_dir = File.join(__dir__, 'fixtures/proto')
         | 
| 11 | 
            +
                  $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  @services = {
         | 
| 14 | 
            +
                    'test_services_pb' => { 'module' => 'TestServices', 'hostname' => '0.0.0.0:5678' }
         | 
| 15 | 
            +
                  }
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                it 'should implement a service from options' do
         | 
| 19 | 
            +
                  implementation = TShield::Grpc.load_services(@services).first
         | 
| 20 | 
            +
                  instance = implementation.new
         | 
| 21 | 
            +
                  expect(instance.respond_to?(:service_method)).to be_truthy
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
            end
         | 
    
        data/tshield.gemspec
    CHANGED
    
    | @@ -25,14 +25,18 @@ Gem::Specification.new do |s| | |
| 25 25 | 
             
              s.required_ruby_version = '>= 2.3'
         | 
| 26 26 |  | 
| 27 27 | 
             
              s.add_dependency('byebug', '~> 11.0', '>= 11.0.1')
         | 
| 28 | 
            +
              s.add_dependency('grpc', '~> 1.28', '>= 1.28.0')
         | 
| 29 | 
            +
              s.add_dependency('grpc-tools', '~> 1.28', '>= 1.28.0')
         | 
| 28 30 | 
             
              s.add_dependency('httparty', '~> 0.14', '>= 0.14.0')
         | 
| 29 31 | 
             
              s.add_dependency('json', '~> 2.0', '>= 2.0')
         | 
| 32 | 
            +
              s.add_dependency('puma', '~> 4.3', '>= 4.3.3')
         | 
| 30 33 | 
             
              s.add_dependency('sinatra', '~> 1.4', '>= 1.4.0')
         | 
| 34 | 
            +
              s.add_dependency('sinatra-cross_origin', '~> 0.4.0', '>= 0.4')
         | 
| 31 35 | 
             
              s.add_development_dependency('coveralls')
         | 
| 32 36 | 
             
              s.add_development_dependency('cucumber', '~> 3.1', '>= 3.1.2')
         | 
| 33 37 | 
             
              s.add_development_dependency('guard', '~> 2.15', '>= 2.15.0')
         | 
| 34 38 | 
             
              s.add_development_dependency('guard-rspec', '~> 4.7', '>= 4.7.3')
         | 
| 35 | 
            -
              s.add_development_dependency('rake', ' | 
| 39 | 
            +
              s.add_development_dependency('rake', '>= 10.0', '~> 13.0')
         | 
| 36 40 | 
             
              s.add_development_dependency('rdoc', '~> 6.0', '>= 6.0')
         | 
| 37 41 | 
             
              s.add_development_dependency('reek', '~> 5.4.0', '>= 5.4.0')
         | 
| 38 42 | 
             
              s.add_development_dependency('rspec', '~> 3.5', '>= 3.5.0')
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: tshield
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.11. | 
| 4 | 
            +
              version: 0.11.16.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Diego Rubin
         | 
| @@ -9,7 +9,7 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2020- | 
| 12 | 
            +
            date: 2020-07-08 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: byebug
         | 
| @@ -31,6 +31,46 @@ dependencies: | |
| 31 31 | 
             
                - - ">="
         | 
| 32 32 | 
             
                  - !ruby/object:Gem::Version
         | 
| 33 33 | 
             
                    version: 11.0.1
         | 
| 34 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 35 | 
            +
              name: grpc
         | 
| 36 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - ">="
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: 1.28.0
         | 
| 41 | 
            +
                - - "~>"
         | 
| 42 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 43 | 
            +
                    version: '1.28'
         | 
| 44 | 
            +
              type: :runtime
         | 
| 45 | 
            +
              prerelease: false
         | 
| 46 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 47 | 
            +
                requirements:
         | 
| 48 | 
            +
                - - ">="
         | 
| 49 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 50 | 
            +
                    version: 1.28.0
         | 
| 51 | 
            +
                - - "~>"
         | 
| 52 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 53 | 
            +
                    version: '1.28'
         | 
| 54 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 55 | 
            +
              name: grpc-tools
         | 
| 56 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 57 | 
            +
                requirements:
         | 
| 58 | 
            +
                - - ">="
         | 
| 59 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 60 | 
            +
                    version: 1.28.0
         | 
| 61 | 
            +
                - - "~>"
         | 
| 62 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 63 | 
            +
                    version: '1.28'
         | 
| 64 | 
            +
              type: :runtime
         | 
| 65 | 
            +
              prerelease: false
         | 
| 66 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 67 | 
            +
                requirements:
         | 
| 68 | 
            +
                - - ">="
         | 
| 69 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 70 | 
            +
                    version: 1.28.0
         | 
| 71 | 
            +
                - - "~>"
         | 
| 72 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 73 | 
            +
                    version: '1.28'
         | 
| 34 74 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 35 75 | 
             
              name: httparty
         | 
| 36 76 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -71,6 +111,26 @@ dependencies: | |
| 71 111 | 
             
                - - "~>"
         | 
| 72 112 | 
             
                  - !ruby/object:Gem::Version
         | 
| 73 113 | 
             
                    version: '2.0'
         | 
| 114 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 115 | 
            +
              name: puma
         | 
| 116 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 117 | 
            +
                requirements:
         | 
| 118 | 
            +
                - - "~>"
         | 
| 119 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 120 | 
            +
                    version: '4.3'
         | 
| 121 | 
            +
                - - ">="
         | 
| 122 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 123 | 
            +
                    version: 4.3.3
         | 
| 124 | 
            +
              type: :runtime
         | 
| 125 | 
            +
              prerelease: false
         | 
| 126 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 127 | 
            +
                requirements:
         | 
| 128 | 
            +
                - - "~>"
         | 
| 129 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 130 | 
            +
                    version: '4.3'
         | 
| 131 | 
            +
                - - ">="
         | 
| 132 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 133 | 
            +
                    version: 4.3.3
         | 
| 74 134 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 75 135 | 
             
              name: sinatra
         | 
| 76 136 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -91,6 +151,26 @@ dependencies: | |
| 91 151 | 
             
                - - "~>"
         | 
| 92 152 | 
             
                  - !ruby/object:Gem::Version
         | 
| 93 153 | 
             
                    version: '1.4'
         | 
| 154 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 155 | 
            +
              name: sinatra-cross_origin
         | 
| 156 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 157 | 
            +
                requirements:
         | 
| 158 | 
            +
                - - ">="
         | 
| 159 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 160 | 
            +
                    version: '0.4'
         | 
| 161 | 
            +
                - - "~>"
         | 
| 162 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 163 | 
            +
                    version: 0.4.0
         | 
| 164 | 
            +
              type: :runtime
         | 
| 165 | 
            +
              prerelease: false
         | 
| 166 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 167 | 
            +
                requirements:
         | 
| 168 | 
            +
                - - ">="
         | 
| 169 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 170 | 
            +
                    version: '0.4'
         | 
| 171 | 
            +
                - - "~>"
         | 
| 172 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 173 | 
            +
                    version: 0.4.0
         | 
| 94 174 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 95 175 | 
             
              name: coveralls
         | 
| 96 176 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -174,7 +254,7 @@ dependencies: | |
| 174 254 | 
             
                    version: '10.0'
         | 
| 175 255 | 
             
                - - "~>"
         | 
| 176 256 | 
             
                  - !ruby/object:Gem::Version
         | 
| 177 | 
            -
                    version: ' | 
| 257 | 
            +
                    version: '13.0'
         | 
| 178 258 | 
             
              type: :development
         | 
| 179 259 | 
             
              prerelease: false
         | 
| 180 260 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| @@ -184,7 +264,7 @@ dependencies: | |
| 184 264 | 
             
                    version: '10.0'
         | 
| 185 265 | 
             
                - - "~>"
         | 
| 186 266 | 
             
                  - !ruby/object:Gem::Version
         | 
| 187 | 
            -
                    version: ' | 
| 267 | 
            +
                    version: '13.0'
         | 
| 188 268 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 189 269 | 
             
              name: rdoc
         | 
| 190 270 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -347,6 +427,8 @@ files: | |
| 347 427 | 
             
            - lib/tshield/controllers/sessions.rb
         | 
| 348 428 | 
             
            - lib/tshield/counter.rb
         | 
| 349 429 | 
             
            - lib/tshield/extensions/string_extensions.rb
         | 
| 430 | 
            +
            - lib/tshield/grpc.rb
         | 
| 431 | 
            +
            - lib/tshield/grpc/vcr.rb
         | 
| 350 432 | 
             
            - lib/tshield/logger.rb
         | 
| 351 433 | 
             
            - lib/tshield/matching/filters.rb
         | 
| 352 434 | 
             
            - lib/tshield/options.rb
         | 
| @@ -356,15 +438,17 @@ files: | |
| 356 438 | 
             
            - lib/tshield/response.rb
         | 
| 357 439 | 
             
            - lib/tshield/server.rb
         | 
| 358 440 | 
             
            - lib/tshield/sessions.rb
         | 
| 359 | 
            -
            - lib/tshield/simple_tcp_server.rb
         | 
| 360 441 | 
             
            - lib/tshield/version.rb
         | 
| 361 442 | 
             
            - spec/spec_helper.rb
         | 
| 362 443 | 
             
            - spec/tshield/after_filter_spec.rb
         | 
| 363 444 | 
             
            - spec/tshield/configuration_spec.rb
         | 
| 364 445 | 
             
            - spec/tshield/controllers/requests_spec.rb
         | 
| 446 | 
            +
            - spec/tshield/fixtures/config/tshield-without-grpc.yml
         | 
| 365 447 | 
             
            - spec/tshield/fixtures/config/tshield.yml
         | 
| 366 448 | 
             
            - spec/tshield/fixtures/filters/example_filter.rb
         | 
| 367 449 | 
             
            - spec/tshield/fixtures/matching/example.json
         | 
| 450 | 
            +
            - spec/tshield/fixtures/proto/test_services_pb.rb
         | 
| 451 | 
            +
            - spec/tshield/grpc_spec.rb
         | 
| 368 452 | 
             
            - spec/tshield/options_spec.rb
         | 
| 369 453 | 
             
            - spec/tshield/request_matching_spec.rb
         | 
| 370 454 | 
             
            - spec/tshield/request_vcr_spec.rb
         | 
| @@ -388,18 +472,21 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 388 472 | 
             
                - !ruby/object:Gem::Version
         | 
| 389 473 | 
             
                  version: '0'
         | 
| 390 474 | 
             
            requirements: []
         | 
| 391 | 
            -
            rubygems_version: 3.0. | 
| 475 | 
            +
            rubygems_version: 3.0.8
         | 
| 392 476 | 
             
            signing_key: 
         | 
| 393 477 | 
             
            specification_version: 4
         | 
| 394 478 | 
             
            summary: Proxy for mocks API responses
         | 
| 395 479 | 
             
            test_files:
         | 
| 396 480 | 
             
            - spec/spec_helper.rb
         | 
| 397 | 
            -
            - spec/tshield/ | 
| 481 | 
            +
            - spec/tshield/request_matching_spec.rb
         | 
| 482 | 
            +
            - spec/tshield/grpc_spec.rb
         | 
| 398 483 | 
             
            - spec/tshield/configuration_spec.rb
         | 
| 399 484 | 
             
            - spec/tshield/request_vcr_spec.rb
         | 
| 400 485 | 
             
            - spec/tshield/controllers/requests_spec.rb
         | 
| 486 | 
            +
            - spec/tshield/options_spec.rb
         | 
| 401 487 | 
             
            - spec/tshield/after_filter_spec.rb
         | 
| 402 | 
            -
            - spec/tshield/fixtures/config/tshield.yml
         | 
| 403 488 | 
             
            - spec/tshield/fixtures/matching/example.json
         | 
| 489 | 
            +
            - spec/tshield/fixtures/proto/test_services_pb.rb
         | 
| 404 490 | 
             
            - spec/tshield/fixtures/filters/example_filter.rb
         | 
| 405 | 
            -
            - spec/tshield/ | 
| 491 | 
            +
            - spec/tshield/fixtures/config/tshield.yml
         | 
| 492 | 
            +
            - spec/tshield/fixtures/config/tshield-without-grpc.yml
         | 
| @@ -1,28 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            require 'socket'
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            module TShield
         | 
| 6 | 
            -
              class SimpleTCPServer
         | 
| 7 | 
            -
                def initialize
         | 
| 8 | 
            -
                  @running = true
         | 
| 9 | 
            -
                end
         | 
| 10 | 
            -
             | 
| 11 | 
            -
                def on_connect(_client)
         | 
| 12 | 
            -
                  raise 'should implement method on_connect'
         | 
| 13 | 
            -
                end
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                def close
         | 
| 16 | 
            -
                  @running = false
         | 
| 17 | 
            -
                end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                def listen(port)
         | 
| 20 | 
            -
                  puts "listening #{port}"
         | 
| 21 | 
            -
                  @server = TCPServer.new(port)
         | 
| 22 | 
            -
                  while @running
         | 
| 23 | 
            -
                    client = @server.accept
         | 
| 24 | 
            -
                    on_connect(client)
         | 
| 25 | 
            -
                  end
         | 
| 26 | 
            -
                end
         | 
| 27 | 
            -
              end
         | 
| 28 | 
            -
            end
         |