Upgrade to Pro — share decks privately, control downloads, hide ads and more …

思考middleware

 思考middleware

覃明圆

May 26, 2015
Tweet

More Decks by 覃明圆

Other Decks in Technology

Transcript

  1. 主要内容 • 什么是 rack-middleware - middleware 的⺫⽬目的 - middleware 单个实现

    - middleware 如何协同⼯工作 • rack-middleware 模拟实现 - module + 函数式编程 - include + super(ancestors)
  2. class ContentLength
 
 def initialize(app)
 @app = app
 end
 


    def call(env)
 status, headers, body = @app.call(env)
 
 headers[CONTENT_LENGTH] = body.length.to_s
 
 [status, headers, body]
 end
 
 end
  3. # File lib/rack/builder.rb, line 81
 def use(middleware, *args, &block)
 if

    @map
 mapping, @map = @map, nil
 @use << proc { |app| generate_map app, mapping }
 end
 @use << proc { |app| middleware.new(app, *args, &block) }
 end 初始化所有middleware
  4. #<Rack::Lock:0x007fa65a8ab828>
 #<Daifu::Application:0x007fa653dfc720>
 #<Rack::Sendfile:0x007fa659a3eb50>
 #<ActionDispatch::Static:0x007fa659a3edd0>
 #<Rack::Lock:0x007fa659a3ee48>
 #<Rack::Runtime:0x007fa659a3ee98>
 #<Rack::MethodOverride:0x007fa659a3eec0>
 #<Rails::Rack::Logger:0x007fa659a3ef10>
 #<ActionDispatch::ShowExceptions:0x007fa659a3ef38>
 #<ActionDispatch::DebugExceptions:0x007fa659a3ef60>


    #<ActionDispatch::RemoteIp:0x007fa659a3ef88>
 #<ActionDispatch::Reloader:0x007fa659a3efb0>
 #<ActionDispatch::Callbacks:0x007fa659a3efd8>
 #<ActiveRecord::Migration::CheckPending:0x007fa659a3f000>
 #<ActiveRecord::ConnectionAdapters::ConnectionManagement:0x007fa659a3f140>
 #<ActiveRecord::QueryCache:0x007fa659a3f280>
 #<ActionDispatch::Cookies:0x007fa659a3f398>
 #<ActionDispatch::Session::CookieStore:0x007fa659a3f438>
 #<ActionDispatch::Flash:0x007fa659a3f460>
 #<ActionDispatch::ParamsParser:0x007fa659a3f528>
 #<Rack::Head:0x007fa659a3f550>
 #<Rack::ConditionalGet:0x007fa659a3f578>
 #<Rack::ETag:0x007fa659a3f5a0>
 #<ActionDispatch::Routing::RouteSet:0x007fa657658538>
  5. def call(env)
 status, headers, body = @app.call(env)
 
 # 对拿到返回的response进⾏行加⼯工


    headers['Content-Length'] = body.size 
 [status, headers, body]
 end 下⼀一个 middleware Rack::Lock 当前middleware Rack::ContentLength
  6. def call(env)
 old, env[FLAG] = env[FLAG], false
 @mutex.lock
 response =

    @app.call(env)
 body = BodyProxy.new(response[2]) { @mutex.unlock }
 response[2] = body
 response
 end 下⼀一个 middleware Rails::Application 当前middleware Rack::Lock
  7. 
 def call(env)
 status, headers, body = @app.call(env)
 if body.respond_to?(:to_path)


    if type == 'X-Sendfile'
 path = F.expand_path(body.to_path)
 headers[CONTENT_LENGTH] = '0'
 headers[type] = path
 obody = body
 body = Rack::BodyProxy.new([]) do
 obody.close if obody.respond_to?(:close)
 end
 end
 end
 [status, headers, body]
 end 当前 middleware Rack::Sendfile 下⼀一个 middleware ……
  8. def call(env)
 status, headers, body = @app.call(env)
 
 if etag_status?(status)


    headers[ETAG_STRING] = %(W/"#{digest}") if digest
 end
 
 unless headers[CACHE_CONTROL]
 headers[CACHE_CONTROL] = @cache_control if @cache_control
 end
 
 [status, headers, body]
 end 当前 middleware Rack::ETag 下⼀一个 middleware ActionDispatch::Routing::RouteSet
  9. def call(env)
 req = request_class.new(env)
 req.path_info = Journey::Router::Utils.normalize_path(req.path_info)
 @router.serve(req)
 end

    当前 middleware ActionDispatch::Routing::RouteSet 下⼀一个 middleware? ActionDispatch::Journey::Router
  10. def serve(req)
 find_routes(req).each do |match, parameters, route|
 set_params = req.path_parameters


    path_info = req.path_info
 script_name = req.script_name
 
 unless route.path.anchored
 req.script_name = (script_name.to_s + match.to_s).chomp('/')
 req.path_info = match.post_match
 req.path_info = "/" + req.path_info unless req.path_info.start_with? "/"
 end
 
 req.path_parameters = set_params.merge parameters
 
 status, headers, body = route.app.serve(req)
 
 if 'pass' == headers['X-Cascade']
 req.script_name = script_name
 req.path_info = path_info
 req.path_parameters = set_params
 next
 end
 
 return [status, headers, body]
 end
 
 return [404, {'X-Cascade' => 'pass'}, ['Not Found']]
 end ActionDispatch::Journey::Router