From c0450c6888c6234bfbd324672ddcedb33901d21e Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 30 Dec 2008 18:38:48 -0800 Subject: [PATCH] Don't let size(key) get tricked by non-200 OK responses We never checked the HTTP status code when making the HEAD request. All this HTTP stuff should probably be moved to HTTPFile --- lib/mogilefs/mogilefs.rb | 16 ++++++++++++---- test/test_mogilefs.rb | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/mogilefs/mogilefs.rb b/lib/mogilefs/mogilefs.rb index 95d44f6..5c76bfa 100644 --- a/lib/mogilefs/mogilefs.rb +++ b/lib/mogilefs/mogilefs.rb @@ -20,6 +20,10 @@ class MogileFS::MogileFS < MogileFS::Client attr_accessor :get_file_data_timeout ## + # internal Regexp for matching an "HTTP 200 OK" head response + HTTP_200_OK = %r{\AHTTP/\d+\.\d+\s+200\s+}.freeze + + ## # Creates a new MogileFS::MogileFS instance. +args+ must include a key # :domain specifying the domain of this client. @@ -207,14 +211,18 @@ class MogileFS::MogileFS < MogileFS::Client "HEAD #{url.request_uri} HTTP/1.0\r\n\r\n", @get_file_data_timeout) res = s.recv(4096, 0) - - if cl = /^Content-Length:\s*(\d+)/i.match(res) - return cl[1].to_i + if res =~ HTTP_200_OK + head, body = res.split(/\r\n\r\n/, 2) + if head =~ /^Content-Length:\s*(\d+)/i + return $1.to_i + end end next rescue MogileFS::Timeout, Errno::ECONNREFUSED, EOFError, SystemCallError next + ensure + s.close rescue nil end else next unless File.exist? path @@ -264,7 +272,7 @@ class MogileFS::MogileFS < MogileFS::Client @get_file_data_timeout) buf = sock.recv(4096, Socket::MSG_PEEK) head, body = buf.split(/\r\n\r\n/, 2) - if head =~ %r{\AHTTP/\d+\.\d+\s+200\s+} + if head =~ HTTP_200_OK sock.recv(head.size + 4, 0) return sock end diff --git a/test/test_mogilefs.rb b/test/test_mogilefs.rb index 2fd7a46..32f9b6b 100644 --- a/test/test_mogilefs.rb +++ b/test/test_mogilefs.rb @@ -259,6 +259,25 @@ class TestMogileFS__MogileFS < TestMogileFS assert_equal 1, accept_nr end + def test_bad_size_http + accept_nr = 0 + t = TempServer.new(Proc.new do |serv,port| + client, client_addr = serv.accept + client.sync = true + readed = client.recv(4096, 0) rescue nil + assert_equal "HEAD /path HTTP/1.0\r\n\r\n", readed + client.send("HTTP/1.0 404 Not Found\r\nContent-Length: 5\r\n\r\n", 0) + accept_nr += 1 + client.close + end) + + path = "http://127.0.0.1:#{t.port}/path" + @backend.get_paths = { 'paths' => 1, 'path1' => path } + + assert_nil @client.size('key') + assert_equal 1, accept_nr + end + def test_store_content_http received = '' expected = "PUT /path HTTP/1.0\r\nContent-Length: 4\r\n\r\ndata" -- 2.11.4.GIT