Skip to content
This repository
Browse code

Draft Expectation Cascade

  • Loading branch information...
commit cfee6eefe8291d0aa3c70a12b3b2cc350ec09beb 1 parent 185fa26
Joshua Peek authored July 09, 2009
1  lib/rack/contrib.rb
@@ -13,6 +13,7 @@ def self.release
13 13
   autoload :CSSHTTPRequest,             "rack/contrib/csshttprequest"
14 14
   autoload :Deflect,                    "rack/contrib/deflect"
15 15
   autoload :ETag,                       "rack/contrib/etag"
  16
+  autoload :ExpectationCascade,         "rack/contrib/expectation_cascade"
16 17
   autoload :GarbageCollector,           "rack/contrib/garbagecollector"
17 18
   autoload :JSONP,                      "rack/contrib/jsonp"
18 19
   autoload :LighttpdScriptNameFix,      "rack/contrib/lighttpd_script_name_fix"
32  lib/rack/contrib/expectation_cascade.rb
... ...
@@ -0,0 +1,32 @@
  1
+module Rack
  2
+  class ExpectationCascade
  3
+    Expect = "Expect".freeze
  4
+    ContinueExpectation = "100-continue".freeze
  5
+
  6
+    ExpectationFailed = [417, {"Content-Type" => "text/html"}, []].freeze
  7
+    NotFound = [404, {"Content-Type" => "text/html"}, []].freeze
  8
+
  9
+    attr_reader :apps
  10
+
  11
+    def initialize
  12
+      @apps = []
  13
+      yield self if block_given?
  14
+    end
  15
+
  16
+    def call(env)
  17
+      set_expectation = env[Expect] != ContinueExpectation
  18
+      env[Expect] = ContinueExpectation if set_expectation
  19
+      @apps.each do |app|
  20
+        result = app.call(env)
  21
+        return result unless result[0].to_i == 417
  22
+      end
  23
+      set_expectation ? NotFound : ExpectationFailed
  24
+    ensure
  25
+      env.delete(Expect) if set_expectation
  26
+    end
  27
+
  28
+    def <<(app)
  29
+      @apps << app
  30
+    end
  31
+  end
  32
+end
72  test/spec_rack_expectation_cascade.rb
... ...
@@ -0,0 +1,72 @@
  1
+require 'test/spec'
  2
+require 'rack/mock'
  3
+require 'rack/contrib/expectation_cascade'
  4
+
  5
+context "Rack::ExpectationCascade" do
  6
+  specify "with no apps returns a 404 if no expectation header was set" do
  7
+    app = Rack::ExpectationCascade.new
  8
+    env = {}
  9
+    response = app.call(env)
  10
+    response[0].should.equal 404
  11
+    env.should.equal({})
  12
+  end
  13
+
  14
+  specify "with no apps returns a 417 if expectation header was set" do
  15
+    app = Rack::ExpectationCascade.new
  16
+    env = {"Expect" => "100-continue"}
  17
+    response = app.call(env)
  18
+    response[0].should.equal 417
  19
+    env.should.equal({"Expect" => "100-continue"})
  20
+  end
  21
+
  22
+  specify "returns first successful response" do
  23
+    app = Rack::ExpectationCascade.new do |cascade|
  24
+      cascade << lambda { |env| [417, {"Content-Type" => "text/plain"}, []] }
  25
+      cascade << lambda { |env| [200, {"Content-Type" => "text/plain"}, ["OK"]] }
  26
+    end
  27
+    response = app.call({})
  28
+    response[0].should.equal 200
  29
+    response[2][0].should.equal "OK"
  30
+  end
  31
+
  32
+  specify "expectation is set if it has not been already" do
  33
+    app = Rack::ExpectationCascade.new do |cascade|
  34
+      cascade << lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Expect: #{env["Expect"]}"]] }
  35
+    end
  36
+    response = app.call({})
  37
+    response[0].should.equal 200
  38
+    response[2][0].should.equal "Expect: 100-continue"
  39
+  end
  40
+
  41
+  specify "returns a 404 if no apps where matched and no expectation header was set" do
  42
+    app = Rack::ExpectationCascade.new do |cascade|
  43
+      cascade << lambda { |env| [417, {"Content-Type" => "text/plain"}, []] }
  44
+    end
  45
+    response = app.call({})
  46
+    response[0].should.equal 404
  47
+    response[2][0].should.equal nil
  48
+  end
  49
+
  50
+  specify "returns a 417 if no apps where matched and a expectation header was set" do
  51
+    app = Rack::ExpectationCascade.new do |cascade|
  52
+      cascade << lambda { |env| [417, {"Content-Type" => "text/plain"}, []] }
  53
+    end
  54
+    response = app.call({"Expect" => "100-continue"})
  55
+    response[0].should.equal 417
  56
+    response[2][0].should.equal nil
  57
+  end
  58
+
  59
+  specify "nests expectation cascades" do
  60
+    app = Rack::ExpectationCascade.new do |c1|
  61
+      c1 << Rack::ExpectationCascade.new do |c2|
  62
+        c2 << lambda { |env| [417, {"Content-Type" => "text/plain"}, []] }
  63
+      end
  64
+      c1 << Rack::ExpectationCascade.new do |c2|
  65
+        c2 << lambda { |env| [200, {"Content-Type" => "text/plain"}, ["OK"]] }
  66
+      end
  67
+    end
  68
+    response = app.call({})
  69
+    response[0].should.equal 200
  70
+    response[2][0].should.equal "OK"
  71
+  end
  72
+end

0 notes on commit cfee6ee

Please sign in to comment.
Something went wrong with that request. Please try again.