Class | NFSN::Manager |
In: |
nfsn-api.rb
|
Parent: | Object |
The main entry point for using this API. Use this to access all the other components of the API.
The login parameter should be your NFSN membership login name. api_key is your NFSN-issued API key. Setting the optional debug parameter to true will increase the log verbosity.
# File nfsn-api.rb, line 88 def initialize(login, api_key, debug = false) @login = login @api_key = api_key @debug = debug @logger = Logger.new(NFSN::LogDevice.new($stderr)) @logger.datetime_format = "%d %b %Y %H:%M:%S" @logger.level = @debug ? Logger::DEBUG : Logger::INFO @hostname = "api.nearlyfreespeech.net" @server_error = @error = nil @error_response = nil @timestamp = nil # Timestamp of last request generated @time_nudge = 0 end
Returns an NFSN::Account object.
# File nfsn-api.rb, line 219 def accountHandle(account_id) NFSN::Account.new(self, account_id) end
# File nfsn-api.rb, line 153 def describeError fail "no error yet!" unless @error and @error_response @error_response.each_capitalized { |key, val| $stderr.puts "\t#{key}: #{val}" } require "pp"; pp @error end
method should be one of :GET, :PUT, :POST, indicating the type of API call. For :GET, data is ignored. For :PUT, data should be the data to store. For :POST, data should be a Hash of attributes.
This should only be called from NFSN::APIObject or a descendent.
# File nfsn-api.rb, line 168 def doOp(method, uri, data = nil) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = (uri.scheme == "https") http.verify_mode = OpenSSL::SSL::VERIFY_NONE req = nil if method == :GET req = Net::HTTP::Get.new(uri.request_uri) elsif method == :PUT req = Net::HTTP::Put.new(uri.request_uri) req.body = data.to_s elsif method == :POST req = Net::HTTP::Post.new(uri.path) req.form_data = data else fail "Bad HTTP method '#{method}'!" end auth_str = genAuthHeader(uri, req.body || "") req["Host"] = @hostname req["X-NFSN-Authentication"] = auth_str @logger.debug "#{method} #{uri}" #@logger.debug "X-NFSN-Authentication: #{auth_str}" data = begin response = http.start { |http| http.request(req) } if response.kind_of? Net::HTTPSuccess response.body else response.error! end rescue Net::HTTPServerException @server_error = "#{$!}" @error = JSON.parse(response.body) @error_response = response @logger.debug "Server returned: #{@server_error}" if response.code =~ /40\d/ handle40x(response) end fail $! # fallback end if (not data.nil?) and (data.size > 0) @logger.debug "Got #{data.size} bytes" return data end @logger.debug "Got empty return value" return nil end
Returns an NFSN::Email object.
# File nfsn-api.rb, line 239 def emailHandle(hostname) NFSN::Email.new(self, hostname) end
Returns an NFSN::Member object.
# File nfsn-api.rb, line 229 def memberHandle(login = nil) NFSN::Member.new(self, login || @login) end
# File nfsn-api.rb, line 105 def setTimeNudge(time_nudge) # TODO: sanity checking @time_nudge = time_nudge end
Returns an NFSN::Site object.
# File nfsn-api.rb, line 234 def siteHandle(shortname) NFSN::Site.new(self, shortname) end
Generate the X-NFSN-Authentication HTTP header.
# File nfsn-api.rb, line 118 def genAuthHeader(uri, body = "") @timestamp = (Time.now + @time_nudge).to_i salt = genSalt #@logger.debug "body: #{body}" body_hash = Digest::SHA1.hexdigest(body) check_str = [@login, @timestamp.to_s, salt, @api_key, uri.request_uri, body_hash].join(";") #@logger.debug "check_str: #{check_str}" hash = Digest::SHA1.hexdigest(check_str) auth_str = [@login, @timestamp.to_s, salt, hash].join(";") auth_str end
Generate a random 16-character salt.
# File nfsn-api.rb, line 111 def genSalt charset = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a return (1..16).map { charset[rand(charset.size)] }.join end
Throws an appropriate NFSN::Error exception.
# File nfsn-api.rb, line 135 def handle40x(response) code = response.code @logger.debug "Got a #{code}! (msg=#{response.message})" if code == "401" and @error["debug"] =~ /timestamp/ hdr = response["WWW-Authenticate"] delta = hdr.scan(/time=(\d+)/)[0] delta = (delta[0].to_i - @timestamp) if delta raise NFSN::BadTimestampError.new(@error, delta) elsif code == "401" and @error["debug"] =~ /authentication hash/ raise NFSN::BadAuthenticationError.new(@error) elsif code == "404" and @error["error"] =~ /API.*not valid/ raise NFSN::NotImplementedError.new(@error) else raise NFSN::Error.new("Unknown error!", @error) end end