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

思考middleware

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

 思考middleware

Avatar for 覃明圆

覃明圆

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