Created
November 5, 2009 20:57
-
-
Save thinkerbot/227373 to your computer and use it in GitHub Desktop.
A session wrapper for curb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'curb' | |
class Session | |
# The internal Curl::Easy instance | |
attr_reader :curb | |
# The last response, or nil | |
attr_reader :last | |
def initialize | |
@curb ||= Curl::Easy.new | |
@curb.enable_cookies = true | |
@last = nil | |
end | |
# Make a get request using the query and headers. The query may be a query | |
# string, a hash, or an array of arrays. Yields curb to the block, if | |
# given, before the request is made. | |
# | |
# Returns a Response. | |
def get(url, query={}, headers={}) | |
unless query.kind_of?(String) | |
query = query.collect do |key, value| | |
"#{curb.escape(key.to_s)}=#{curb.escape(value.to_s)}" | |
end.join('&') | |
end | |
curb.url = query.empty? ? url : "#{url}?#{build_query(query)}" | |
curb.headers = headers | |
yield(curb) if block_given? | |
curb.http_get | |
@last = Response.new(curb) | |
end | |
# Make a post request using the query and headers. The query may be a query | |
# string, a hash, or an array of arrays. Yields curb and the post fields to | |
# the block, if given, before submitting the request. | |
# | |
# If a query value is a File, then the file contents will be uploaded using | |
# 'multipart/formdata'. Otherwise the content type will be | |
# 'application/x-www-form-urlencoded'. | |
# | |
# Returns a Response. | |
def post(url, query={}, headers={}) | |
curb.url = url | |
curb.headers = headers | |
curb.multipart_form_post = false | |
fields = [] | |
query.each do |key, value| | |
case value | |
when File | |
curb.multipart_form_post = true | |
# it is not very efficient to close the file and re-open it | |
# for the post, but the block form does not appear to work | |
# | |
# Curl::PostField.file(key, value.path) { value.read } | |
fields << Curl::PostField.file(key, value.path) | |
value.close | |
else | |
fields << Curl::PostField.content(key, value) | |
end | |
end | |
yield(curb, fields) if block_given? | |
curb.http_post(*fields) | |
@last = Response.new(curb) | |
end | |
class Response | |
def initialize(curb) | |
@curb = curb | |
reset | |
end | |
# Returns the status line of the response. | |
def status_line | |
@status_line || parse_header(false) | |
end | |
# Returns a hash of the headers. | |
def headers | |
@headers || parse_header(true) | |
end | |
# Returns the response body. | |
def body | |
@curb.body_str | |
end | |
# Returns the response code. | |
def code | |
@curb.response_code | |
end | |
# Returns a hash of cookies in the header. | |
def cookies | |
cookies = {} | |
headers["Set-Cookie"].to_s.split(/;\s*/).each do |cookie| | |
key, value = cookie.split("=", 2) | |
cookies[key] = value | |
end | |
cookies | |
end | |
# Returns true if the response code == 302 | |
def redirect? | |
code == 302 | |
end | |
# Returns the redirect location. | |
def redirect_location | |
headers["Location"] | |
end | |
# Performs an HTTP get for the redirect_location and refreshes self to | |
# reflect the new response. The current state of self is overwritten. | |
def follow_redirect! | |
@curb.url = redirect_location | |
@curb.http_get | |
reset | |
self | |
end | |
private | |
# resets self so the status_line and headers will be re-parsed | |
def reset # :nodoc: | |
@status_line = nil | |
@headers = nil | |
end | |
# parses the headers and status_line, returns headers if return_headers is | |
# true and status_line otherwise | |
def parse_header(return_headers) # :nodoc: | |
lines = @curb.header_str.split(/\r\n/) | |
@status_line = lines.shift | |
@headers = {} | |
lines.each do |line| | |
key, value = line.split(/:\s*/, 2) | |
@headers[key] = value | |
end | |
return_headers ? @headers : @status_line | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment