Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

133 lines (119 sloc) 4.326 kb
require 'net/http'
require 'net/https'
require 'copycopter_client/errors'
module CopycopterClient
# Communicates with the Copycopter server. This class is used to actually
# download and upload blurbs, as well as issuing deploys.
#
# A client is usually instantiated when {Configuration#apply} is called, and
# the application will not need to interact with it directly.
class Client
# These errors will be rescued when connecting Copycopter.
HTTP_ERRORS = [Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
Net::ProtocolError]
# Usually instantiated from {Configuration#apply}. Copies options.
# @param options [Hash]
# @option options [String] :api_key API key of the project to connect to
# @option options [Fixnum] :port the port to connect to
# @option options [Boolean] :public whether to download draft or published content
# @option options [Fixnum] :http_read_timeout how long to wait before timing out when reading data from the socket
# @option options [Fixnum] :http_open_timeout how long to wait before timing out when opening the socket
# @option options [Boolean] :secure whether to use SSL
# @option options [Logger] :logger where to log transactions
# @option options [String] :ca_file path to root certificate file for ssl verification
def initialize(options)
[:api_key, :host, :port, :public, :http_read_timeout,
:http_open_timeout, :secure, :logger, :ca_file].each do |option|
instance_variable_set("@#{option}", options[option])
end
end
# Downloads all blurbs for the given api_key.
#
# If the +public+ option was set to +true+, this will use published blurbs.
# Otherwise, draft content is fetched.
#
# The client tracks ETags between download requests, and will return
# without yielding anything if the server returns a not modified response.
#
# @yield [Hash] downloaded blurbs
# @raise [ConnectionError] if the connection fails
def download
connect do |http|
request = Net::HTTP::Get.new(uri(download_resource))
request['If-None-Match'] = @etag
response = http.request(request)
if check(response)
log("Downloaded translations")
yield JSON.parse(response.body)
else
log("No new translations")
end
@etag = response['ETag']
end
end
# Uploads the given hash of blurbs as draft content.
# @param data [Hash] the blurbs to upload
# @raise [ConnectionError] if the connection fails
def upload(data)
connect do |http|
response = http.post(uri("draft_blurbs"), data.to_json)
check(response)
log("Uploaded missing translations")
end
end
# Issues a deploy, marking all draft content as published for this project.
# @raise [ConnectionError] if the connection fails
def deploy
connect do |http|
response = http.post(uri("deploys"), "")
check(response)
log("Deployed")
end
end
private
attr_reader :host, :port, :api_key, :http_read_timeout,
:http_open_timeout, :secure, :logger, :ca_file
def public?
@public
end
def uri(resource)
"/api/v2/projects/#{api_key}/#{resource}"
end
def download_resource
if public?
"published_blurbs"
else
"draft_blurbs"
end
end
def connect
http = Net::HTTP.new(host, port)
http.open_timeout = http_open_timeout
http.read_timeout = http_read_timeout
http.use_ssl = secure
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.ca_file = ca_file
begin
yield(http)
rescue *HTTP_ERRORS => exception
raise ConnectionError, "#{exception.class.name}: #{exception.message}"
end
end
def check(response)
case response
when Net::HTTPNotFound
raise InvalidApiKey, "Invalid API key: #{api_key}"
when Net::HTTPNotModified
false
when Net::HTTPSuccess
true
else
raise ConnectionError, "#{response.code}: #{response.body}"
end
end
def log(message)
logger.info(message)
end
end
end
Jump to Line
Something went wrong with that request. Please try again.