]> git.donarmstrong.com Git - dsa-puppet.git/blobdiff - 3rdparty/modules/aviator/feature/faraday/rack_builder.rb
add aimonb/aviator to 3rdparty
[dsa-puppet.git] / 3rdparty / modules / aviator / feature / faraday / rack_builder.rb
diff --git a/3rdparty/modules/aviator/feature/faraday/rack_builder.rb b/3rdparty/modules/aviator/feature/faraday/rack_builder.rb
new file mode 100644 (file)
index 0000000..204ce41
--- /dev/null
@@ -0,0 +1,212 @@
+module Faraday
+  # A Builder that processes requests into responses by passing through an inner
+  # middleware stack (heavily inspired by Rack).
+  #
+  #   Faraday::Connection.new(:url => 'http://sushi.com') do |builder|
+  #     builder.request  :url_encoded  # Faraday::Request::UrlEncoded
+  #     builder.adapter  :net_http     # Faraday::Adapter::NetHttp
+  #   end
+  class RackBuilder
+    attr_accessor :handlers
+
+    # Error raised when trying to modify the stack after calling `lock!`
+    class StackLocked < RuntimeError; end
+
+    # borrowed from ActiveSupport::Dependencies::Reference &
+    # ActionDispatch::MiddlewareStack::Middleware
+    class Handler
+      @@constants_mutex = Mutex.new
+      @@constants = Hash.new { |h, k|
+        value = k.respond_to?(:constantize) ? k.constantize : Object.const_get(k)
+        @@constants_mutex.synchronize { h[k] = value }
+      }
+
+      attr_reader :name
+
+      def initialize(klass, *args, &block)
+        @name = klass.to_s
+        if klass.respond_to?(:name)
+          @@constants_mutex.synchronize { @@constants[@name] = klass }
+        end
+        @args, @block = args, block
+      end
+
+      def klass() @@constants[@name] end
+      def inspect() @name end
+
+      def ==(other)
+        if other.is_a? Handler
+          self.name == other.name
+        elsif other.respond_to? :name
+          klass == other
+        else
+          @name == other.to_s
+        end
+      end
+
+      def build(app)
+        klass.new(app, *@args, &@block)
+      end
+    end
+
+    def initialize(handlers = [])
+      @handlers = handlers
+      if block_given?
+        build(&Proc.new)
+      elsif @handlers.empty?
+        # default stack, if nothing else is configured
+        self.request :url_encoded
+        self.adapter Faraday.default_adapter
+      end
+    end
+
+    def build(options = {})
+      raise_if_locked
+      @handlers.clear unless options[:keep]
+      yield(self) if block_given?
+    end
+
+    def [](idx)
+      @handlers[idx]
+    end
+
+    # Locks the middleware stack to ensure no further modifications are possible.
+    def lock!
+      @handlers.freeze
+    end
+
+    def locked?
+      @handlers.frozen?
+    end
+
+    def use(klass, *args, &block)
+      if klass.is_a? Symbol
+        use_symbol(Faraday::Middleware, klass, *args, &block)
+      else
+        raise_if_locked
+        @handlers << self.class::Handler.new(klass, *args, &block)
+      end
+    end
+
+    def request(key, *args, &block)
+      use_symbol(Faraday::Request, key, *args, &block)
+    end
+
+    def response(key, *args, &block)
+      use_symbol(Faraday::Response, key, *args, &block)
+    end
+
+    def adapter(key, *args, &block)
+      use_symbol(Faraday::Adapter, key, *args, &block)
+    end
+
+    ## methods to push onto the various positions in the stack:
+
+    def insert(index, *args, &block)
+      raise_if_locked
+      index = assert_index(index)
+      handler = self.class::Handler.new(*args, &block)
+      @handlers.insert(index, handler)
+    end
+
+    alias_method :insert_before, :insert
+
+    def insert_after(index, *args, &block)
+      index = assert_index(index)
+      insert(index + 1, *args, &block)
+    end
+
+    def swap(index, *args, &block)
+      raise_if_locked
+      index = assert_index(index)
+      @handlers.delete_at(index)
+      insert(index, *args, &block)
+    end
+
+    def delete(handler)
+      raise_if_locked
+      @handlers.delete(handler)
+    end
+
+    # Processes a Request into a Response by passing it through this Builder's
+    # middleware stack.
+    #
+    # connection - Faraday::Connection
+    # request    - Faraday::Request
+    #
+    # Returns a Faraday::Response.
+    def build_response(connection, request)
+      app.call(build_env(connection, request))
+    end
+
+    # The "rack app" wrapped in middleware. All requests are sent here.
+    #
+    # The builder is responsible for creating the app object. After this,
+    # the builder gets locked to ensure no further modifications are made
+    # to the middleware stack.
+    #
+    # Returns an object that responds to `call` and returns a Response.
+    def app
+      @app ||= begin
+        lock!
+        to_app(lambda { |env|
+          response = Response.new
+          response.finish(env) unless env.parallel?
+          env.response = response
+        })
+      end
+    end
+
+    def to_app(inner_app)
+      # last added handler is the deepest and thus closest to the inner app
+      @handlers.reverse.inject(inner_app) { |app, handler| handler.build(app) }
+    end
+
+    def ==(other)
+      other.is_a?(self.class) && @handlers == other.handlers
+    end
+
+    def dup
+      self.class.new(@handlers.dup)
+    end
+
+    # ENV Keys
+    # :method - a symbolized request method (:get, :post)
+    # :body   - the request body that will eventually be converted to a string.
+    # :url    - URI instance for the current request.
+    # :status           - HTTP response status code
+    # :request_headers  - hash of HTTP Headers to be sent to the server
+    # :response_headers - Hash of HTTP headers from the server
+    # :parallel_manager - sent if the connection is in parallel mode
+    # :request - Hash of options for configuring the request.
+    #   :timeout      - open/read timeout Integer in seconds
+    #   :open_timeout - read timeout Integer in seconds
+    #   :proxy        - Hash of proxy options
+    #     :uri        - Proxy Server URI
+    #     :user       - Proxy server username
+    #     :password   - Proxy server password
+    # :ssl - Hash of options for configuring SSL requests.
+    def build_env(connection, request)
+      Env.new(request.method, request.body,
+        connection.build_exclusive_url(request.path, request.params),
+        request.options, request.headers, connection.ssl,
+        connection.parallel_manager)
+    end
+
+    private
+
+    def raise_if_locked
+      raise StackLocked, "can't modify middleware stack after making a request" if locked?
+    end
+
+    def use_symbol(mod, key, *args, &block)
+      use(mod.lookup_middleware(key), *args, &block)
+    end
+
+    def assert_index(index)
+      idx = index.is_a?(Integer) ? index : @handlers.index(index)
+      raise "No such handler: #{index.inspect}" unless idx
+      idx
+    end
+  end
+end