diff --git a/lib/remote_storage/riak.rb b/lib/remote_storage/riak.rb index e5c129d..503d452 100644 --- a/lib/remote_storage/riak.rb +++ b/lib/remote_storage/riak.rb @@ -23,7 +23,7 @@ module RemoteStorage request_method = server.env["REQUEST_METHOD"] if directory.split("/").first == "public" - return true if request_method == "GET" && !listing + return true if ["GET", "HEAD"].include?(request_method) && !listing end authorizations = auth_bucket.get("#{user}:#{token}").data @@ -37,13 +37,18 @@ module RemoteStorage server.halt 401 end + def get_head(user, directory, key) + object = data_bucket.get("#{user}:#{directory}:#{key}") + set_object_response_headers(object) + server.halt 200 + rescue ::Riak::HTTPFailedRequest + server.halt 404 + end + def get_data(user, directory, key) object = data_bucket.get("#{user}:#{directory}:#{key}") - server.headers["Content-Type"] = object.content_type - server.headers["Last-Modified"] = last_modified_date_for(object) - server.headers["ETag"] = object.etag - server.headers["Content-Length"] = object_size(object) + set_object_response_headers(object) server.halt 304 if server.env["HTTP_IF_NONE_MATCH"] == object.etag @@ -152,6 +157,13 @@ module RemoteStorage private + def set_object_response_headers(object) + server.headers["Content-Type"] = object.content_type + server.headers["Last-Modified"] = last_modified_date_for(object) + server.headers["ETag"] = object.etag + server.headers["Content-Length"] = object_size(object) + end + def extract_category(directory) if directory.match(/^public\//) "public/#{directory.split('/')[1]}" diff --git a/liquor-cabinet.rb b/liquor-cabinet.rb index 1175ddd..fbddcdb 100644 --- a/liquor-cabinet.rb +++ b/liquor-cabinet.rb @@ -66,6 +66,10 @@ class LiquorCabinet < Sinatra::Base storage.get_data(@user, @directory, @key) end + head path do + storage.get_head(@user, @directory, @key) + end + put path do data = request.body.read diff --git a/spec/riak_spec.rb b/spec/riak_spec.rb index 406ffc1..b9db15c 100644 --- a/spec/riak_spec.rb +++ b/spec/riak_spec.rb @@ -7,6 +7,42 @@ describe "App with Riak backend" do purge_all_buckets end + describe "HEAD public data" do + before do + object = data_bucket.new("jimmy:public:foo") + object.content_type = "text/plain" + object.data = "some text data" + object.store + + head "/jimmy/public/foo" + end + + it "returns an empty body" do + last_response.status.must_equal 200 + last_response.body.must_equal "" + end + + it "has a Last-Modified header set" do + last_response.status.must_equal 200 + last_response.headers["Last-Modified"].wont_be_nil + + now = Time.now + last_modified = DateTime.parse(last_response.headers["Last-Modified"]) + last_modified.year.must_equal now.year + last_modified.day.must_equal now.day + end + + it "has an ETag header set" do + last_response.status.must_equal 200 + last_response.headers["ETag"].wont_be_nil + end + + it "has a Content-Length header set" do + last_response.status.must_equal 200 + last_response.headers["Content-Length"].must_equal 14 + end + end + describe "GET public data" do before do object = data_bucket.new("jimmy:public:foo") @@ -80,6 +116,37 @@ describe "App with Riak backend" do auth.store end + describe "HEAD" do + before do + header "Authorization", "Bearer 123" + head "/jimmy/documents/foo" + end + + it "returns an empty body" do + last_response.status.must_equal 200 + last_response.body.must_equal "" + end + + it "has an ETag header set" do + last_response.status.must_equal 200 + last_response.headers["ETag"].wont_be_nil + end + + it "has a Content-Length header set" do + last_response.status.must_equal 200 + last_response.headers["Content-Length"].must_equal 22 + end + end + + describe "HEAD nonexisting key" do + it "returns a 404" do + header "Authorization", "Bearer 123" + head "/jimmy/documents/somestupidkey" + + last_response.status.must_equal 404 + end + end + describe "GET" do before do header "Authorization", "Bearer 123"