diff --git a/lib/remote_storage/riak.rb b/lib/remote_storage/riak.rb index 503d452..0804b60 100644 --- a/lib/remote_storage/riak.rb +++ b/lib/remote_storage/riak.rb @@ -73,14 +73,18 @@ module RemoteStorage server.halt 404 end + def get_head_directory_listing(user, directory) + directory_object = directory_bucket.get("#{user}:#{directory}") + set_directory_response_headers(directory_object) + server.halt 200 + rescue ::Riak::HTTPFailedRequest + server.halt 404 + end + def get_directory_listing(user, directory) directory_object = directory_bucket.get("#{user}:#{directory}") - timestamp = directory_object.data.to_i - timestamp /= 1000 if timestamp.to_s.length == 13 - server.headers["Content-Type"] = "application/json" - server.headers["Last-Modified"] = Time.at(timestamp).to_s(:rfc822) - server.headers["ETag"] = directory_object.etag + set_directory_response_headers(directory_object) server.halt 304 if server.env["HTTP_IF_NONE_MATCH"] == directory_object.etag @@ -164,6 +168,14 @@ module RemoteStorage server.headers["Content-Length"] = object_size(object) end + def set_directory_response_headers(directory_object) + timestamp = directory_object.data.to_i + timestamp /= 1000 if timestamp.to_s.length == 13 + server.headers["Content-Type"] = "application/json" + server.headers["Last-Modified"] = Time.at(timestamp).to_s(:rfc822) + server.headers["ETag"] = directory_object.etag + end + def extract_category(directory) if directory.match(/^public\//) "public/#{directory.split('/')[1]}" diff --git a/liquor-cabinet.rb b/liquor-cabinet.rb index fbddcdb..2e4601f 100644 --- a/liquor-cabinet.rb +++ b/liquor-cabinet.rb @@ -91,6 +91,10 @@ class LiquorCabinet < Sinatra::Base get path do storage.get_directory_listing(@user, @directory) end + + head path do + storage.get_head_directory_listing(@user, @directory) + end end private diff --git a/spec/directories_spec.rb b/spec/directories_spec.rb index 035586f..9a7f191 100644 --- a/spec/directories_spec.rb +++ b/spec/directories_spec.rb @@ -13,6 +13,56 @@ describe "Directories" do header "Authorization", "Bearer 123" end + describe "HEAD listing" do + before do + put "/jimmy/tasks/foo", "do the laundry" + put "/jimmy/tasks/http%3A%2F%2F5apps.com", "prettify design" + + head "/jimmy/tasks/" + end + + it "has an empty body" do + last_response.status.must_equal 200 + last_response.body.must_equal "" + end + + it "has a Last-Modifier 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 + + # check that ETag stays the same + etag = last_response.headers["ETag"] + get "/jimmy/tasks/" + last_response.headers["ETag"].must_equal etag + end + + it "has CORS headers set" do + last_response.status.must_equal 200 + last_response.headers["Access-Control-Allow-Origin"].must_equal "*" + last_response.headers["Access-Control-Allow-Methods"].must_equal "GET, PUT, DELETE" + last_response.headers["Access-Control-Allow-Headers"].must_equal "Authorization, Content-Type, Origin, If-Match, If-None-Match" + last_response.headers["Access-Control-Expose-Headers"].must_equal "ETag" + end + + context "for an empty or absent directory" do + it "responds with 404" do + head "/jimmy/documents/" + + last_response.status.must_equal 404 + end + end + end + describe "GET listing" do before do put "/jimmy/tasks/foo", "do the laundry"