api_valve 0.6.0 → 0.6.1
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/lib/api_valve.rb +3 -6
- data/lib/api_valve/middleware.rb +43 -0
- data/lib/api_valve/middleware/error_handling.rb +15 -17
- data/lib/api_valve/middleware/logging.rb +1 -1
- data/lib/api_valve/middleware/router.rb +15 -0
- data/lib/api_valve/proxy.rb +16 -13
- data/lib/api_valve/{router.rb → route_set.rb} +15 -18
- data/lib/api_valve/runner.rb +9 -0
- metadata +6 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 8f4cba9301dc5313a548d0d0be717b8bbc0af686c5da846bac838547e08dd8e3
         | 
| 4 | 
            +
              data.tar.gz: 42d48117b5969d38f5125bfa4fbbde0633fbde1214b738de1efd607007cbb978
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 537cfb673ad5a8eeb6ec9f0871a0a85d6b61206326e0c9f0f4731414f341f60c45b595feab392f86ab4ea00c64819f83c3b7b98c2650a40e318e22bf1e812a64
         | 
| 7 | 
            +
              data.tar.gz: f7e6538270b6d444c1bdf4b1fe06f9d86864c61ca1d9738201d21f9eb06c6349888e4141756ef5db7afdc63a9c427985a64d8d7c306d783d9740ad04d8934743
         | 
    
        data/lib/api_valve.rb
    CHANGED
    
    | @@ -17,17 +17,14 @@ module ApiValve | |
| 17 17 | 
             
              autoload :Error,          'api_valve/error'
         | 
| 18 18 | 
             
              autoload :ErrorResponder, 'api_valve/error_responder'
         | 
| 19 19 | 
             
              autoload :Forwarder,      'api_valve/forwarder'
         | 
| 20 | 
            +
              autoload :Middleware,     'api_valve/middleware'
         | 
| 20 21 | 
             
              autoload :Logger,         'api_valve/logger'
         | 
| 21 22 | 
             
              autoload :Proxy,          'api_valve/proxy'
         | 
| 22 | 
            -
              autoload : | 
| 23 | 
            +
              autoload :RouteSet,       'api_valve/route_set'
         | 
| 24 | 
            +
              autoload :Runner,         'api_valve/runner'
         | 
| 23 25 |  | 
| 24 26 | 
             
              include ActiveSupport::Configurable
         | 
| 25 27 |  | 
| 26 | 
            -
              module Middleware
         | 
| 27 | 
            -
                autoload :ErrorHandling, 'api_valve/middleware/error_handling'
         | 
| 28 | 
            -
                autoload :Logging,       'api_valve/middleware/logging'
         | 
| 29 | 
            -
              end
         | 
| 30 | 
            -
             | 
| 31 28 | 
             
              config_accessor :logger do
         | 
| 32 29 | 
             
                Logger.new(STDOUT)
         | 
| 33 30 | 
             
              end
         | 
| @@ -0,0 +1,43 @@ | |
| 1 | 
            +
            module ApiValve
         | 
| 2 | 
            +
              class Middleware
         | 
| 3 | 
            +
                autoload :ErrorHandling, 'api_valve/middleware/error_handling'
         | 
| 4 | 
            +
                autoload :Logging,       'api_valve/middleware/logging'
         | 
| 5 | 
            +
                autoload :Router,        'api_valve/middleware/router'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                Item = Struct.new(:klass, :proc)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def initialize
         | 
| 10 | 
            +
                  @registry = []
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def insert_after(other, middleware, *args, &block)
         | 
| 14 | 
            +
                  @registry.insert position(other) + 1, to_item(middleware, *args, &block)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def insert_before(other, middleware, *args, &block)
         | 
| 18 | 
            +
                  @registry.insert position(other), to_item(middleware, *args, &block)
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def to_app(root_app)
         | 
| 22 | 
            +
                  @registry.reverse.inject(root_app) { |memo, obj| obj.proc.call memo }
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def to_s
         | 
| 26 | 
            +
                  @registry.map(&:klass).join("\n")
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def use(middleware, *args, &block)
         | 
| 30 | 
            +
                  @registry << to_item(middleware, *args, &block)
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                private
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def position(klass)
         | 
| 36 | 
            +
                  @registry.index { |item| item.klass == klass }
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def to_item(middleware, *args, &block)
         | 
| 40 | 
            +
                  Item.new(middleware, proc { |app| middleware.new(app, *args, &block) })
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
            end
         | 
| @@ -1,23 +1,21 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
               | 
| 3 | 
            -
                 | 
| 4 | 
            -
                   | 
| 5 | 
            -
             | 
| 6 | 
            -
                  end
         | 
| 1 | 
            +
            class ApiValve::Middleware
         | 
| 2 | 
            +
              class ErrorHandling
         | 
| 3 | 
            +
                def initialize(app)
         | 
| 4 | 
            +
                  @app = app
         | 
| 5 | 
            +
                end
         | 
| 7 6 |  | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 7 | 
            +
                def call(env)
         | 
| 8 | 
            +
                  @app.call(env)
         | 
| 9 | 
            +
                rescue Exception => e # rubocop:disable Lint/RescueException
         | 
| 10 | 
            +
                  log_error e
         | 
| 11 | 
            +
                  self.class.const_get(ApiValve.error_responder).new(e).call
         | 
| 12 | 
            +
                end
         | 
| 14 13 |  | 
| 15 | 
            -
             | 
| 14 | 
            +
                private
         | 
| 16 15 |  | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
                  end
         | 
| 16 | 
            +
                def log_error(error)
         | 
| 17 | 
            +
                  ApiValve.logger.error { "#{error.class}: #{error.message}" }
         | 
| 18 | 
            +
                  ApiValve.logger.error { error.backtrace.join("\n") }
         | 
| 21 19 | 
             
                end
         | 
| 22 20 | 
             
              end
         | 
| 23 21 | 
             
            end
         | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            class ApiValve::Middleware
         | 
| 2 | 
            +
              class Router
         | 
| 3 | 
            +
                def initialize(app, routeset)
         | 
| 4 | 
            +
                  @app = app
         | 
| 5 | 
            +
                  @routeset = routeset
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def call(env)
         | 
| 9 | 
            +
                  route, match_data = @routeset.match env
         | 
| 10 | 
            +
                  env['api_valve.router.route'] = route
         | 
| 11 | 
            +
                  env['api_valve.router.match_data'] = match_data
         | 
| 12 | 
            +
                  @app.call(env)
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
            end
         | 
    
        data/lib/api_valve/proxy.rb
    CHANGED
    
    | @@ -64,22 +64,25 @@ module ApiValve | |
| 64 64 | 
             
                  end
         | 
| 65 65 | 
             
                end
         | 
| 66 66 |  | 
| 67 | 
            -
                attr_reader :request, :forwarder, : | 
| 67 | 
            +
                attr_reader :request, :forwarder, :middleware, :route_set
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                alias router route_set
         | 
| 68 70 |  | 
| 69 71 | 
             
                def initialize(forwarder)
         | 
| 70 72 | 
             
                  @forwarder = forwarder
         | 
| 71 | 
            -
                  @ | 
| 72 | 
            -
                  @ | 
| 73 | 
            +
                  @route_set = RouteSet.new
         | 
| 74 | 
            +
                  @middleware = Middleware.new
         | 
| 75 | 
            +
                  use Middleware::Router, route_set
         | 
| 73 76 | 
             
                end
         | 
| 74 77 |  | 
| 75 78 | 
             
                def call(env)
         | 
| 76 | 
            -
                   | 
| 77 | 
            -
                  stack.call(env)
         | 
| 79 | 
            +
                  to_app.call(env)
         | 
| 78 80 | 
             
                rescue ApiValve::Error::Client, ApiValve::Error::Server => e
         | 
| 79 81 | 
             
                  render_error e
         | 
| 80 82 | 
             
                end
         | 
| 81 83 |  | 
| 82 | 
            -
                delegate :add_route, to: : | 
| 84 | 
            +
                delegate :add_route, to: :route_set
         | 
| 85 | 
            +
                delegate :use, to: :middleware
         | 
| 83 86 |  | 
| 84 87 | 
             
                def build_routes_from_config(routes_config)
         | 
| 85 88 | 
             
                  return forward_all unless routes_config
         | 
| @@ -97,32 +100,32 @@ module ApiValve | |
| 97 100 |  | 
| 98 101 | 
             
                def forward(methods, path_regexp = nil, request_override = {})
         | 
| 99 102 | 
             
                  Array.wrap(methods).each do |method|
         | 
| 100 | 
            -
                     | 
| 103 | 
            +
                    route_set.public_send(method, path_regexp, proc { |request, match_data|
         | 
| 101 104 | 
             
                      forwarder.call request, {'match_data' => match_data}.merge(request_override || {})
         | 
| 102 105 | 
             
                    })
         | 
| 103 106 | 
             
                  end
         | 
| 104 107 | 
             
                end
         | 
| 105 108 |  | 
| 106 109 | 
             
                def forward_all
         | 
| 107 | 
            -
                   | 
| 110 | 
            +
                  route_set.any do |request, match_data|
         | 
| 108 111 | 
             
                    forwarder.call request, 'match_data' => match_data
         | 
| 109 112 | 
             
                  end
         | 
| 110 113 | 
             
                end
         | 
| 111 114 |  | 
| 112 115 | 
             
                def deny(methods, path_regexp = nil, with: 'Error::Forbidden')
         | 
| 113 116 | 
             
                  Array.wrap(methods).each do |method|
         | 
| 114 | 
            -
                     | 
| 117 | 
            +
                    route_set.public_send(method, path_regexp, ->(*_args) { raise ApiValve.const_get(with) })
         | 
| 115 118 | 
             
                  end
         | 
| 116 119 | 
             
                end
         | 
| 117 120 |  | 
| 118 | 
            -
                def use(middleware, *args, &block)
         | 
| 119 | 
            -
                  @middlewares << proc { |app| middleware.new(app, *args, &block) }
         | 
| 120 | 
            -
                end
         | 
| 121 | 
            -
             | 
| 122 121 | 
             
                protected
         | 
| 123 122 |  | 
| 124 123 | 
             
                def render_error(error)
         | 
| 125 124 | 
             
                  self.class.const_get(ApiValve.error_responder).new(error).call
         | 
| 126 125 | 
             
                end
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                def to_app
         | 
| 128 | 
            +
                  @to_app ||= @middleware.to_app(Runner.new)
         | 
| 129 | 
            +
                end
         | 
| 127 130 | 
             
              end
         | 
| 128 131 | 
             
            end
         | 
| @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            module ApiValve
         | 
| 2 | 
            -
              class  | 
| 2 | 
            +
              class RouteSet
         | 
| 3 3 | 
             
                METHODS = %i(get post put patch delete head).freeze
         | 
| 4 4 |  | 
| 5 5 | 
             
                Route = Struct.new(:regexp, :block) do
         | 
| @@ -16,8 +16,20 @@ module ApiValve | |
| 16 16 | 
             
                  reset_routes
         | 
| 17 17 | 
             
                end
         | 
| 18 18 |  | 
| 19 | 
            -
                def  | 
| 20 | 
            -
                   | 
| 19 | 
            +
                def match(env)
         | 
| 20 | 
            +
                  request = Rack::Request.new(env)
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  # For security reasons do not allow URLs that could break out of the proxy namespace on the
         | 
| 23 | 
            +
                  # server. Preferably an nxing/apache rewrite will kill these URLs before they hit us
         | 
| 24 | 
            +
                  raise 'URL not supported' if request.path_info.include?('/../')
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  match_data = nil
         | 
| 27 | 
            +
                  route = @routes && @routes[request.request_method.downcase.to_sym].find do |r|
         | 
| 28 | 
            +
                    (match_data = r.match(request.path_info))
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                  raise Error::NotRouted, 'Endpoint not found' unless route
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  [route, match_data]
         | 
| 21 33 | 
             
                end
         | 
| 22 34 |  | 
| 23 35 | 
             
                def delete(path = nil, prok = nil)
         | 
| @@ -65,20 +77,5 @@ module ApiValve | |
| 65 77 | 
             
                def reset_routes
         | 
| 66 78 | 
             
                  @routes = Hash[METHODS.map { |v| [v, []] }].freeze
         | 
| 67 79 | 
             
                end
         | 
| 68 | 
            -
             | 
| 69 | 
            -
                private
         | 
| 70 | 
            -
             | 
| 71 | 
            -
                def match(request)
         | 
| 72 | 
            -
                  # For security reasons do not allow URLs that could break out of the proxy namespace on the
         | 
| 73 | 
            -
                  # server. Preferably an nxing/apache rewrite will kill these URLs before they hit us
         | 
| 74 | 
            -
                  raise 'URL not supported' if request.path_info.include?('/../')
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                  @routes && @routes[request.request_method.downcase.to_sym].each do |route|
         | 
| 77 | 
            -
                    if (match_data = route.match(request.path_info))
         | 
| 78 | 
            -
                      return route.call request, match_data
         | 
| 79 | 
            -
                    end
         | 
| 80 | 
            -
                  end
         | 
| 81 | 
            -
                  raise Error::NotRouted, 'Endpoint not found'
         | 
| 82 | 
            -
                end
         | 
| 83 80 | 
             
              end
         | 
| 84 81 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: api_valve
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.6. | 
| 4 | 
            +
              version: 0.6.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - mkon
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2018-12- | 
| 11 | 
            +
            date: 2018-12-18 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: activesupport
         | 
| @@ -202,10 +202,13 @@ files: | |
| 202 202 | 
             
            - lib/api_valve/forwarder/request.rb
         | 
| 203 203 | 
             
            - lib/api_valve/forwarder/response.rb
         | 
| 204 204 | 
             
            - lib/api_valve/logger.rb
         | 
| 205 | 
            +
            - lib/api_valve/middleware.rb
         | 
| 205 206 | 
             
            - lib/api_valve/middleware/error_handling.rb
         | 
| 206 207 | 
             
            - lib/api_valve/middleware/logging.rb
         | 
| 208 | 
            +
            - lib/api_valve/middleware/router.rb
         | 
| 207 209 | 
             
            - lib/api_valve/proxy.rb
         | 
| 208 | 
            -
            - lib/api_valve/ | 
| 210 | 
            +
            - lib/api_valve/route_set.rb
         | 
| 211 | 
            +
            - lib/api_valve/runner.rb
         | 
| 209 212 | 
             
            homepage: https://github.com/mkon/api_valve
         | 
| 210 213 | 
             
            licenses:
         | 
| 211 214 | 
             
            - MIT
         |