# frozen_string_literal: truerequire'faraday/adapter_registry'moduleFaraday# A Builder that processes requests into responses by passing through an inner# middleware stack (heavily inspired by Rack).## @example# Faraday::Connection.new(url: 'http://httpbingo.org') do |builder|# builder.request :url_encoded # Faraday::Request::UrlEncoded# builder.adapter :net_http # Faraday::Adapter::NetHttp# endclassRackBuilder# Used to detect missing argumentsNO_ARGUMENT=Object.newLOCK_ERR="can't modify middleware stack after making a request"MISSING_ADAPTER_ERROR="An attempt to run a request with a Faraday::Connection without adapter has been made.\n"\"Please set Faraday.default_adapter or provide one when initializing the connection.\n"\'For more info, check https://lostisland.github.io/faraday/usage/.'attr_accessor:handlers# Error raised when trying to modify the stack after calling `lock!`classStackLocked<RuntimeError;end# borrowed from ActiveSupport::Dependencies::Reference &# ActionDispatch::MiddlewareStack::MiddlewareclassHandlerREGISTRY=Faraday::AdapterRegistry.newattr_reader:namedefinitialize(klass,*args,**kwargs,&block)@name=klass.to_sREGISTRY.set(klass)ifklass.respond_to?(:name)@args=args@kwargs=kwargs@block=blockenddefklassREGISTRY.get(@name)enddefinspect@nameenddef==(other)ifother.is_a?Handlername==other.nameelsifother.respond_to?:nameklass==otherelse@name==other.to_sendenddefbuild(app=nil)klass.new(app,*@args,**@kwargs,&@block)endenddefinitialize(&block)@adapter=nil@handlers=[]build(&block)enddefinitialize_dup(original)super@adapter=original.adapter@handlers=original.handlers.dupenddefbuildraise_if_lockedblock_given??yield(self):request(:url_encoded)adapter(Faraday.default_adapter,**Faraday.default_adapter_options)unless@adapterenddef[](idx)@handlers[idx]end# Locks the middleware stack to ensure no further modifications are made.deflock!@handlers.freezeenddeflocked?@handlers.frozen?enddefuse(klass,...)ifklass.is_a?Symboluse_symbol(Faraday::Middleware,klass,...)elseraise_if_lockedraise_if_adapter(klass)@handlers<<self.class::Handler.new(klass,...)endenddefrequest(key,...)use_symbol(Faraday::Request,key,...)enddefresponse(...)use_symbol(Faraday::Response,...)enddefadapter(klass=NO_ARGUMENT,*args,**kwargs,&block)return@adapterifklass==NO_ARGUMENT||klass.nil?klass=Faraday::Adapter.lookup_middleware(klass)ifklass.is_a?(Symbol)@adapter=self.class::Handler.new(klass,*args,**kwargs,&block)end## methods to push onto the various positions in the stack:definsert(index,...)raise_if_lockedindex=assert_index(index)handler=self.class::Handler.new(...)@handlers.insert(index,handler)endaliasinsert_beforeinsertdefinsert_after(index,...)index=assert_index(index)insert(index+1,...)enddefswap(index,...)raise_if_lockedindex=assert_index(index)@handlers.delete_at(index)insert(index,...)enddefdelete(handler)raise_if_locked@handlers.delete(handler)end# Processes a Request into a Response by passing it through this Builder's# middleware stack.## @param connection [Faraday::Connection]# @param request [Faraday::Request]## @return [Faraday::Response]defbuild_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.defapp@app||=beginlock!ensure_adapter!to_appendenddefto_app# last added handler is the deepest and thus closest to the inner app# adapter is always the last one@handlers.reverse.inject(@adapter.build)do|app,handler|handler.build(app)endenddef==(other)other.is_a?(self.class)&&@handlers==other.handlers&&@adapter==other.adapterend# ENV Keys# :http_method - a symbolized request HTTP 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.defbuild_env(connection,request)exclusive_url=connection.build_exclusive_url(request.path,request.params,request.options.params_encoder)Env.new(request.http_method,request.body,exclusive_url,request.options,request.headers,connection.ssl,connection.parallel_manager)endprivatedefraise_if_lockedraiseStackLocked,LOCK_ERRiflocked?enddefraise_if_adapter(klass)returnunlessklass<=Faraday::Adapterraise'Adapter should be set using the `adapter` method, not `use`'enddefensure_adapter!raiseMISSING_ADAPTER_ERRORunless@adapterenddefadapter_set?!@adapter.nil?enddefuse_symbol(mod,key,...)use(mod.lookup_middleware(key),...)enddefassert_index(index)idx=index.is_a?(Integer)?index:@handlers.index(index)raise"No such handler: #{index.inspect}"unlessidxidxendendend