class Server

Copyright
Author

Class to be able to handle server details as comparable objects.

Constants

CLOUD_PATH

Cloud service.

DA_HEADER_PREFIX

Headers.

ESSENTIAL_HEADERS

A list of headers from the end user to pass to DeviceAtlas Cloud. These help with detection, especially if a third party browser or a proxy changes the original user-agent.

ESSENTIAL_USER_AGENT_HEADERS

A list of headers which may contain the original user agent. These headers are sent to cloud server beside ESSENTIAL_HEADERS.

EXTRA_HEADERS

A list of additional headers to send to DeviceAtlas. These are not sent by default. These headers can be used for carrier detection and geoip.

Attributes

host[R]

Public class attributes to be handled from a Client instance.

latency_avg[R]

Public class attributes to be handled from a Client instance.

port[R]

Public class attributes to be handled from a Client instance.

socket[R]

Public class attributes to be handled from a Client instance.

works[R]

Public class attributes to be handled from a Client instance.

Public Class Methods

new(host, port, latency_avg = 0) click to toggle source

Constructor.

host: String with the endpoint host. port: Integer with the port host. latency_avg: Float with the latency average.

# File server.rb, line 85
def initialize(host, port, latency_avg = 0)
        @host = host
        @port = port
        @latency_avg = (latency_avg.nil?)?0:latency_avg
        @works = true
end

Public Instance Methods

<(server) click to toggle source

Server object comparator. It let us sort a Server object list by the server availability and latency average.

server

Server object to compare with.

return

Boolean result after comparing.

# File server.rb, line 100
def <(server)

        # If both work, compare latency avg
        if @works == server.works                     
                return @latency_avg < server.latency_avg
        end

        # If one of them does not work, the one that works will be put higher
        this_works = (@works)?1:0
        that_works = (server.works)?1:0

        return this_works < that_works

end
connect(headers, timeout) click to toggle source

Get the Cloud response based on the given headers.

headers

Array of headers.

timeout

Maximum time we are able to wait to get the response.

return

Hash with the response.

# File server.rb, line 140
def connect(headers, timeout)

        if @socket.nil?                       
                
                # Open a new socket
                begin
                        error_message = 'Error fetching DeviceAtlas data from Cloud'

                        @socket = connect_to(@host, @port, timeout)
                        
                        if !@socket
                                return false
                        end

                rescue Errno::ECONNREFUSED
                        raise(Exception, error_message + ' (Connection refused).')
                rescue Errno::EHOSTUNREACH
                        raise(Exception, error_message + ' (Host unreached).')
                end

        end
        
        result = ''

        if @socket
                
                @socket.write headers

                while response = @socket.gets
                        result = result + response
                end

                if result.include? "404 Not Found"
                        result = false
                end

                @socket.close
                @socket = nil

        end

        result
end
request_headers(licence_key, user_agent, cookie = nil, latency_checker = false, send_extra_headers = false, client_headers = nil) click to toggle source

Get the string of headers we need to make the request.

latency_key

String with the user licence key.

user_agent

String with the User-Agent that identifies the user device.

cookie

String of the properties detected from the client side.

latency_checker

Boolean value to know whether we only want to get

headers to make a request to measure latency.

send_extra_headers

Boolean value to also return extra-headers.

client_headers

Array of client headers

return

String of headers.

# File server.rb, line 220
        def request_headers(licence_key, user_agent, cookie = nil, latency_checker = 
                        false, send_extra_headers = false, client_headers = nil)

                # Get API version from the gem specs
#               api_version = Gem.loaded_specs['deviceatlas_cloud_client'].version.version
                api_version = DeviceAtlasCloudClient::API_VERSION

                # Prepare headers
                path = CLOUD_PATH % [licence_key, CGI.escape(user_agent)]
                # URI.escape has been deprecated in Ruby 1.9.2
                headers = "GET " + path + " HTTP/1.0\r\n" + 
                        "Host: " + @host + ":" + @port.to_s + "\r\n" + 
                        "Accept: application/json\r\n" +
                        "User-Agent: ruby\r\n" + 
                        DA_HEADER_PREFIX + "Version: " + api_version + "\r\n"

                # add the device data cookie created by JS
                if cookie
                        headers += DA_HEADER_PREFIX + CLIENT_COOKIE_HEADER + ": " + 
                                cookie.gsub(/\A[ \n\r\"]+\Z/, "") + "\r\n"
                end

                # latency checker
                if latency_checker
                        headers += DA_HEADER_PREFIX + "Latency-Checker: 1\r\n"
                end

                # add any client headers to be forward to DA
                if !client_headers.nil?

                        # add "essential" headers
                        essential_headers = ESSENTIAL_HEADERS | ESSENTIAL_USER_AGENT_HEADERS
                        essential_headers.each do |header|
                                if client_headers.has_key?(header)
                                        headers += meta_to_header(header) + ": " + client_headers[header] + 
                                                "\r\n"
                                end
                        end

                        # add any Opera or any other special headers as these may contain extra
                        # device information
                        client_headers.each do |header, val|
                                if header.include?'opera'
                                        headers += meta_to_header(header) + ": " + val + "\r\n"
                                end
                        end

                        # add extra "optional" headers
                        if send_extra_headers
                                EXTRA_HEADERS.each do |header|
                                        if client_headers.has_key?(header)
                                                headers += meta_to_header(header) + ": " + client_headers[header] + 
                                                        "\r\n"
                                        end
                                end
                        end

                end

                headers = headers + "Connection: Close\r\n\r\n"
                headers
        end
to_hash() click to toggle source

Return the main server details in a hash.

return

Hash with server details.

# File server.rb, line 120
def to_hash
        { :host => @host, :port => @port, :latency_avg => @latency_avg }
end
update_latency_avg(licence_key, user_agent, num_requests, max_failures, timeout) click to toggle source

Check and update the server latency average.

latency_key

String with the user licence key.

user_agent

String with the User-Agent that identifies the user device.

num_requests

Number of times we need to measure the latency avg.

max_failures

Maximum number of failures we allow to measure.

timeout

Time we allow measure.

# File server.rb, line 193
def update_latency_avg(licence_key, user_agent, num_requests, max_failures, 
                timeout)

        latencies = get_latencies licence_key, user_agent, num_requests, 
                max_failures, timeout

        if latencies.empty? || latencies.include?(-1)
                @latency_avg = -1
        else
                latency_avg = latencies.inject {|sum,x| sum ? sum + x : x };
                @latency_avg = latency_avg / num_requests
        end

end