Using Etags With Open-uri #
If you just joined us, we’re fawning over Tanaka-san’s code lately. He’s the author of an entire repository of red magic. One of his masterpieces is open-uri, a library that in now enshrined in Ruby 1.8.0.
With open-uri, you can access a file over FTP or HTTP and read from like it was any other IO handle (using read.) For HTTP resources, you can access headers through the meta accessor:
require 'open-uri' open( "http://redhanded.hobix.com/index.xml" ) do |feed| p feed.last_modified p feed.meta['etag'] end
The ETag header is great, as it offers a unique hash for the content being served. If your web server returns an ETag, you can issue a conditional GET.
Especially common in RSS feed readers. This technique was also used in the old RAA-Install to check if the RAA feed had changed since the last install. You just send the web server the old etag under the If-None-Match header. The web server will send you a 304 status unless the file is new. This prevents the whole file from being sent if it is old.
require 'open-uri'
# 1st request -- save the ETag
etag = nil
open( "http://redhanded.hobix.com/index.xml" ) do |feed|
etag = feed.meta['etag']
end
# 2nd request -- only retrieve the file if it has changed
begin
open( "http://redhanded.hobix.com/index.xml",
"If-None-Match" => etag ) do |feed|
puts "File has changed: #{ feed.read.length } bytes read"
end
rescue OpenURI::HTTPError
puts "No file available or file has not changed."
end
You can also use the modification time, with the help of the Time#rfc2822 method which formats dates for HTTP.
require 'open-uri'
# 1st request -- save the modification time
mtime = nil
open( "http://redhanded.hobix.com/index.xml" ) do |feed|
mtime = feed.last_modified
end
# 2nd request -- only retrieve the file if it has changed
begin
open( "http://redhanded.hobix.com/index.xml",
"If-Modified-Since" => mtime.rfc2822 ) do |feed|
puts "File has changed: #{ feed.read.length } bytes read"
end
rescue OpenURI::HTTPError
puts "No file available or file has not changed."
end


memmove
Woah, that’s groovy. I just made a mental note try out open-uri. I just love Ruby…
...still having trouble “sneaking Ruby through the system” however. As in, here at work. I’m giving a talk on “Getting Started With Ruby” this Friday. Wish me luck or, maybe, do a little dance, or, whatever.
sleeper
...do a little dance,....
You mean the hamster dance ?
_why cult follower
Shouldn’t that be duck dance ?
Robert McGovern
Agreed, definitly a duck dance. Come on lets all do the waddle.
Daniel Berger
So, “open” is a global def? Ought to be URI .open, or have some namespace attached. Tsk, tsk.
why
Good question, Daniel. For convenience,
open-urialiases and replacesKernel::opento allow opening of files, pipes, URIs from a single method.However, you can use
OpenURI.open_uriif you know you’ll be accessing a URI .You can also access
open-uripower through aURIobject:Look at these options. It’s all so well thought out and neatly aligned.
_why cult follower cult follower
Very ha, _why cult follower.
Daniel Berger
Shame on me for not looking closer. Thanks _why.
Tyler
Why isn’t this stuff in the Ruby Docs? I have been looking forever to find this stuff. Not very fun…
Dan Kubb
Instead of using
mtime.rfc2822wouldn’t you want to usemtime.httpdateComments are closed for this entry.