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

ちょっとわかるrack

 ちょっとわかるrack

初心者向けrackの簡単な紹介
・rackとは何か
・rackアプリの作り方
・rack middlewareの作り方・使い方

※2012/5/14の会社内LTで使用した資料

Leonard Chin

May 24, 2012
Tweet

More Decks by Leonard Chin

Other Decks in Programming

Transcript

  1. ͪΐͬͱΘ͔Δ

    View Slide

  2. Web Server
    App Server
    IUUQ
    DBMMSVCZ
    DBMMBQQ
    Your App

    View Slide

  3. Web Server
    App Server
    IUUQ
    DBMMSVCZ
    DBMMBQQ
    Your App
    BQBDIFOHJOYFUD
    QBTTFOHFSNPOHSFMUIJOFUD

    View Slide

  4. Web Server
    App Server
    IUUQ
    DBMMSVCZ
    DBMMBQQ
    Your App
    BQBDIFOHJOYFUD
    QBTTFOHFSNPOHSFMUIJOFUD
    ͜ͷ*'ɺͲ͏͢Δʁ

    View Slide

  5. Web Server
    App Server
    IUUQ
    DBMMSVCZ
    DBMMBQQ
    Your App
    BQBDIFOHJOYFUD
    QBTTFOHFSNPOHSFMUIJOFUD
    ڞ௨*'3BDL
    3BDL"QQMJDBUJPO

    View Slide

  6. call(env)

    View Slide

  7. def call(env)
    ...
    end
    3FRVFTUΛ౉͞ΕΔ
    3FTQPOTFΛฦ͢
    [status, headers, response_body]

    View Slide

  8. ৄࡉ͸41&$Ͱ
    http://rack.rubyforge.org/doc/SPEC.html

    View Slide

  9. 4JOBUSBͷ৔߹

    View Slide

  10. # Rack call interface.
    def call(env)
    dup.call!(env)
    end
    attr_accessor :env, :request, :response, :params
    def call!(env) # :nodoc:
    @env = env
    @request = Request.new(env)
    @response = Response.new
    @params = indifferent_params(@request.params)
    template_cache.clear if settings.reload_templates
    force_encoding(@params)
    @response['Content-Type'] = nil
    invoke { dispatch! }
    invoke { error_block!(response.status) }
    unless @response['Content-Type']
    if Array === body and body[0].respond_to? :content_type
    content_type body[0].content_type
    else
    content_type :html
    end
    end
    @response.finish
    end

    View Slide

  11. SBDLVQ

    View Slide

  12. rackup config.ru
    ΞϓϦͷೖΓޱΛఆٛ
    Rack::Builder.new { }.to_app
    ʹ౉͢

    View Slide

  13. #config.ru
    require ‘rack’
    require ‘myapp’
    run MyApp.new
    3BDL"QQMJDBUJPO
    JFJNQMFNFOUTcall(env)

    View Slide

  14. # Minimum config.ru
    require ‘rack’
    run lambda { |env|
    [200, { "Content-Type" => "text/plain" }, ["OK"] ]
    }
    TUBUVT IFBEFST CPEZ

    View Slide

  15. 3BDL.JEEMFXBSF

    View Slide

  16. Web Server
    App Server
    IUUQ
    DBMMSVCZ
    Your App
    BQBDIFOHJOYFUD
    QBTTFOHFSNPOHSFMUIJOFUD
    3BDL*'
    3BDL"QQMJDBUJPO
    Middleware
    Middleware
    3BDL*'
    3BDL*'
    .JEEMFXBSFΛૠೖ
    ^

    View Slide

  17. w $43'
    w 3FEJSFDUJPO
    w -PHHJOH
    w 4FTTJPO.BOBHFNFOU
    w "VUIFOUJDBUJPO
    w &NCFE(PPHMF"OBMZUJDT
    FUD

    View Slide

  18. class Middleware
    def initialize(app)
    @app = app
    end
    def call(env)
    # do something
    response = @app.call(env)
    # do something
    end
    end
    ࣍ʹݺͿ"QQ.JEEMFXBSF
    3FRVFTUΛ͍͡Δ
    3FTQPOTFΛ͍͡Δ

    View Slide

  19. View Slide

  20. def call(env)
    unless env['rack.session']
    raise SessionUnavailable.new('Rack::Csrf depends on session middleware')
    end
    self.class.token(env)
    req = Rack::Request.new(env)
    untouchable = skip_checking(req) ||
    [email protected]_methods.include?(req.request_method) ||
    req.params[self.class.field] == env['rack.session'][self.class.key] ||
    req.env[self.class.rackified_header] == env['rack.session'][self.class.key]
    if untouchable
    @app.call(env)
    else
    raise InvalidCsrfToken if @raisable
    [403, {'Content-Type' => 'text/html', 'Content-Length' => '0'}, []]
    end
    end
    $43'νΣοΫࣦഊͨ͠Βɺ
    ͙͢ʹ3FTQPOTFฦ͢
    3FRVFTUʹ$43'ରࡦUPLFOΛνΣοΫ
    ௨ͬͨΒɺͦͷ··࣍΁

    View Slide

  21. 6TJOH.JEEMFXBSF

    View Slide

  22. #config.ru
    require ‘rack’
    require ‘myapp’
    class Middleware
    def initialize(app)
    @app = app
    end
    def call(env)
    env["rack.some_header"] = "setting an
    example"
    @app.call(env)
    end
    end
    use Middleware
    run MyApp.new
    3BDL಺෦Ͱ!VTF഑ྻʹૠೖ
    3BDL#VJMEFSʹCJOE͞ΕͯΔ

    View Slide