diff --git a/lib/remote_storage/swift.rb b/lib/remote_storage/swift.rb index fbab446..2593fde 100644 --- a/lib/remote_storage/swift.rb +++ b/lib/remote_storage/swift.rb @@ -139,10 +139,10 @@ module RemoteStorage url = url_for_key(user, directory, key) if required_match = server.env["HTTP_IF_MATCH"] - server.halt 412 unless required_match == %Q("#{existing_metadata["e"]}") + server.halt 412, "Precondition Failed" unless required_match == %Q("#{existing_metadata["e"]}") end if server.env["HTTP_IF_NONE_MATCH"] == "*" - server.halt 412 unless existing_metadata.empty? + server.halt 412, "Precondition Failed" unless existing_metadata.empty? end res = do_put_request(url, data, content_type) @@ -178,7 +178,7 @@ module RemoteStorage existing_metadata = redis.hgetall "rs:m:#{user}:#{directory}/#{key}" if required_match = server.env["HTTP_IF_MATCH"] - server.halt 412 unless required_match == %Q("#{existing_metadata["e"]}") + server.halt 412, "Precondition Failed" unless required_match == %Q("#{existing_metadata["e"]}") end do_delete_request(url) diff --git a/spec/swift/app_spec.rb b/spec/swift/app_spec.rb index ecb0e4f..298ab29 100644 --- a/spec/swift/app_spec.rb +++ b/spec/swift/app_spec.rb @@ -165,7 +165,82 @@ describe "App" do last_response.status.must_equal 400 end end + + describe "If-Match header" do + before do + put_stub = OpenStruct.new(headers: { + etag: "oldetag", + last_modified: "Fri, 04 Mar 2016 12:20:18 GMT" + }) + + RestClient.stub :put, put_stub do + put "/phil/food/aguacate", "si" + end + end + + it "allows the request if the header matches the current ETag" do + header "If-Match", "\"oldetag\"" + + put_stub = OpenStruct.new(headers: { + etag: "newetag", + last_modified: "Fri, 04 Mar 2016 12:20:18 GMT" + }) + + RestClient.stub :put, put_stub do + put "/phil/food/aguacate", "aye" + end + + last_response.status.must_equal 200 + last_response.headers["Etag"].must_equal "\"newetag\"" + end + + it "fails the request if the header does not match the current ETag" do + header "If-Match", "someotheretag" + + put "/phil/food/aguacate", "aye" + + last_response.status.must_equal 412 + last_response.body.must_equal "Precondition Failed" + end + end + + describe "If-None-Match header set to '*'" do + it "succeeds when the document doesn't exist yet" do + put_stub = OpenStruct.new(headers: { + etag: "someetag", + last_modified: "Fri, 04 Mar 2016 12:20:18 GMT" + }) + + header "If-None-Match", "*" + + RestClient.stub :put, put_stub do + put "/phil/food/aguacate", "si" + end + + last_response.status.must_equal 200 + end + + it "fails the request if the document already exsits" do + put_stub = OpenStruct.new(headers: { + etag: "someetag", + last_modified: "Fri, 04 Mar 2016 12:20:18 GMT" + }) + + RestClient.stub :put, put_stub do + put "/phil/food/aguacate", "si" + end + + header "If-None-Match", "*" + RestClient.stub :put, put_stub do + put "/phil/food/aguacate", "si" + end + + last_response.status.must_equal 412 + last_response.body.must_equal "Precondition Failed" + end + end end + end describe "DELETE requests" do @@ -273,6 +348,27 @@ describe "App" do last_response.status.must_equal 404 last_response.body.must_equal "Not Found" end + + describe "If-Match header" do + it "succeeds when the header matches the current ETag" do + header "If-Match", "\"bla\"" + + RestClient.stub :delete, "" do + delete "/phil/food/aguacate" + end + + last_response.status.must_equal 200 + end + + it "fails the request if it does not match the current ETag" do + header "If-Match", "someotheretag" + + delete "/phil/food/aguacate" + + last_response.status.must_equal 412 + last_response.body.must_equal "Precondition Failed" + end + end end end