diff --git a/lib/remote_storage/swift.rb b/lib/remote_storage/swift.rb index 2fb5fa4..fb83f2f 100644 --- a/lib/remote_storage/swift.rb +++ b/lib/remote_storage/swift.rb @@ -52,7 +52,7 @@ module RemoteStorage set_response_headers(res) - none_match = (server.env["HTTP_IF_NONE_MATCH"] || "").split(",").map(&:strip) + none_match = (server.env["HTTP_IF_NONE_MATCH"] || "").gsub(/^W\//, "").split(",").map(&:strip) server.halt 304 if none_match.include? %Q("#{res.headers[:etag]}") return res.body @@ -71,7 +71,7 @@ module RemoteStorage server.headers["Content-Type"] = "application/ld+json" - none_match = (server.env["HTTP_IF_NONE_MATCH"] || "").split(",").map(&:strip) + none_match = (server.env["HTTP_IF_NONE_MATCH"] || "").gsub(/^W\//, "").split(",").map(&:strip) if etag server.halt 304 if none_match.include? %Q("#{etag}") @@ -139,7 +139,9 @@ module RemoteStorage url = url_for_key(user, directory, key) if required_match = server.env["HTTP_IF_MATCH"] - server.halt 412, "Precondition Failed" unless required_match == %Q("#{existing_metadata["e"]}") + unless required_match.gsub(/^W\//, "") == %Q("#{existing_metadata["e"]}") + server.halt 412, "Precondition Failed" + end end if server.env["HTTP_IF_NONE_MATCH"] == "*" server.halt 412, "Precondition Failed" unless existing_metadata.empty? @@ -185,7 +187,9 @@ module RemoteStorage existing_metadata = redis.hgetall "rs:m:#{user}:#{directory}/#{key}" if required_match = server.env["HTTP_IF_MATCH"] - server.halt 412, "Precondition Failed" unless required_match == %Q("#{existing_metadata["e"]}") + unless required_match.gsub(/^W\//, "") == %Q("#{existing_metadata["e"]}") + server.halt 412, "Precondition Failed" + end end begin diff --git a/spec/swift/app_spec.rb b/spec/swift/app_spec.rb index 2e632e7..8cfe170 100644 --- a/spec/swift/app_spec.rb +++ b/spec/swift/app_spec.rb @@ -249,6 +249,22 @@ describe "App" do last_response.headers["Etag"].must_equal "\"newetag\"" end + it "allows the request if the header contains a weak ETAG matching the current ETag" do + header "If-Match", "W/\"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" @@ -473,6 +489,16 @@ describe "App" do last_response.status.must_equal 200 end + it "succeeds when the header contains a weak ETAG matching the current ETag" do + header "If-Match", "W/\"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" @@ -562,6 +588,40 @@ describe "App" do last_response.body.must_equal "Not Found" end + it "responds with 304 when IF_NONE_MATCH header contains the ETag" do + header "If-None-Match", "\"0815etag\"" + + get_stub = OpenStruct.new(body: "si", headers: { + etag: "0815etag", + last_modified: "Fri, 04 Mar 2016 12:20:18 GMT", + content_type: "text/plain; charset=utf-8", + content_length: 2 + }) + + RestClient.stub :get, get_stub do + get "/phil/food/aguacate" + end + + last_response.status.must_equal 304 + end + + it "responds with 304 when IF_NONE_MATCH header contains weak ETAG matching the current ETag" do + header "If-None-Match", "W/\"0815etag\"" + + get_stub = OpenStruct.new(body: "si", headers: { + etag: "0815etag", + last_modified: "Fri, 04 Mar 2016 12:20:18 GMT", + content_type: "text/plain; charset=utf-8", + content_length: 2 + }) + + RestClient.stub :get, get_stub do + get "/phil/food/aguacate" + end + + last_response.status.must_equal 304 + end + end describe "directory listings" do @@ -587,6 +647,13 @@ describe "App" do last_response.status.must_equal 304 end + it "responds with 304 when IF_NONE_MATCH header contains weak ETAG matching the ETag" do + header "If-None-Match", "W/\"f9f85fbf5aa1fa378fd79ac8aa0a457d\"" + get "/phil/food/" + + last_response.status.must_equal 304 + end + it "contains all items in the directory" do get "/phil/food/"