Class: Heroku::Nav::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/heroku/nav.rb

Direct Known Subclasses

Footer, Header, Internal, Provider

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ Base

Returns a new instance of Base.



8
9
10
11
12
13
14
# File 'lib/heroku/nav.rb', line 8

def initialize(app, options={})
  @app     = app
  @options = options
  @options[:except] = [@options[:except]] unless @options[:except].is_a?(Array)
  @options[:status] ||= [200]
  refresh
end

Class Method Details

.api_urlObject



62
63
64
# File 'lib/heroku/nav.rb', line 62

def api_url
  ENV['API_URL'] || ENV['HEROKU_NAV_URL'] || "https://nav.heroku.com"
end

.fetch(format = 'application/json') ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/heroku/nav.rb', line 36

def fetch(format = 'application/json')
  uri = URI.parse(resource_url)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true if uri.scheme == 'https'
  request = Net::HTTP::Get.new(uri.request_uri)
  request['Accept'] = format
  timeout = (ENV['HEROKU_NAV_TIMEOUT'] || 10).to_i
  response = Timeout.timeout(timeout) do
    retry_upto(timeout, :interval => 0.5) do
      http.request(request)
    end
  end
  format == 'application/json' ? OkJson.decode(response.body) : response.body
rescue Timeout::Error, StandardError => e
  $stderr.puts "Failed to fetch the Heroku #{resource}: #{e.class.name} - #{e.message}"
  {}
end

.htmlObject

for non-rack use



67
68
69
# File 'lib/heroku/nav.rb', line 67

def html
  @@body ||= fetch['html']
end

.resourceObject



54
55
56
# File 'lib/heroku/nav.rb', line 54

def resource
  name.split('::').last.downcase
end

.resource_urlObject



58
59
60
# File 'lib/heroku/nav.rb', line 58

def resource_url
  [api_url, '/', resource].join
end

.retry_upto(max_retries = 1, opts = {}) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
# File 'lib/heroku/nav.rb', line 71

def retry_upto(max_retries = 1, opts = {})
  yield
rescue Timeout::Error, StandardError
  attempt = attempt ? attempt+1 : 1
  raise if (attempt == max_retries)
  if interval = opts[:interval]
    secs = interval.respond_to?(:call) ? interval.call(attempt) : interval
    sleep(secs)
  end
  retry
end

Instance Method Details

#call(env) ⇒ Object



16
17
18
19
20
21
22
# File 'lib/heroku/nav.rb', line 16

def call(env)
  @status, @headers, @body = @app.call(env)
  @body.extend(Enumerable)
  @body = @body.to_a.join
  insert! if can_insert?(env)
  [@status, @headers, [@body]]
end

#can_insert?(env) ⇒ Boolean

Returns:

  • (Boolean)


24
25
26
27
28
29
# File 'lib/heroku/nav.rb', line 24

def can_insert?(env)
  return unless @options[:status].include?(@status)
  return unless @headers['Content-Type'] =~ /text\/html/ || @headers['content-type'] =~ /text\/html/
  return if @options[:except].any? { |route| env['PATH_INFO'] =~ route }
  true
end

#refreshObject



31
32
33
# File 'lib/heroku/nav.rb', line 31

def refresh
  @nav = self.class.fetch
end