2010-07-20 7 views
9

Ich schreibe eine Rack-Middleware-Komponente für eine Rails-App, die Cookies gesetzt werden muss. Ich versuche gerade herauszufinden, Cookies zu setzen. Von googlen um scheint es wie dies funktionieren sollte:Wie setze ich einen Cookie mit einer (Ruby) Rack Middleware Komponente?

class RackApp 
    def initialize(app) 
    @app = app 
    end 

    def call(env) 
    @status, @headers, @response = @app.call(env) 
    @response.set_cookie("foo", {:value => "bar", :path => "/", :expires => Time.now+24*60*60}) 
    [@status, @headers, @response] 
    end 
end 

die keine Fehler gibt, aber auch kein Cookie gesetzt. Was mache ich falsch?

Antwort

23

Wenn Sie die Response-Klasse verwenden möchten, müssen Sie sie aus den Ergebnissen des Aufrufs der Middlewareschicht weiter unten im Stapel instanziieren. Auch brauchen Sie keine Instanzvariablen für eine Middleware wie diese und wahrscheinlich nicht wollen, sie auf diese Weise verwenden (@ Status, usw. in der Middleware-Instanz bleiben würde um nach der Anfrage serviert wird)

class RackApp 
    def initialize(app) 
    @app = app 
    end 

    def call(env) 
    status, headers, body = @app.call(env) 
    # confusingly, response takes its args in a different order 
    # than rack requires them to be passed on 
    # I know it's because most likely you'll modify the body, 
    # and the defaults are fine for the others. But, it still bothers me. 

    response = Rack::Response.new body, status, headers 

    response.set_cookie("foo", {:value => "bar", :path => "/", :expires => Time.now+24*60*60}) 
    response.finish # finish writes out the response in the expected format. 
    end 
end 

Wenn Sie wissen, was Sie tun, können Sie den Cookie-Header direkt ändern, wenn Sie ein neues Objekt nicht instanziieren möchten.

+0

Ehrfürchtig. Das funktioniert perfekt für mich. Das klarste Beispiel, das ich bisher gesehen habe. – phaedryx

+0

Danke! Fünf Jahre später war dieser Ausschnitt genau das, wonach ich suchte. – Anurag

+0

@BaroqueBobcat Es wäre wirklich nützlich, wenn Sie angeben, wie Sie den Cookie direkt ändern können. Danke für die tolle Antwort! – thesecretmaster

13

Sie können auch die Bibliothek Rack::Utils verwenden, um Header festzulegen und zu löschen, ohne ein Rack :: Response-Objekt zu erstellen.

class RackApp 
    def initialize(app) 
    @app = app 
    end 

    def call(env) 
    status, headers, body = @app.call(env) 

    Rack::Utils.set_cookie_header!(headers, "foo", {:value => "bar", :path => "/"}) 

    [status, headers, body] 
    end 
end