Class: Rack::Prerender::Fetcher

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/prerender/fetcher.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Fetcher

Returns a new instance of Fetcher.



6
7
8
# File 'lib/rack/prerender/fetcher.rb', line 6

def initialize(options = {})
  @options = options
end

Instance Attribute Details

#envObject (readonly)

Returns the value of attribute env.



4
5
6
# File 'lib/rack/prerender/fetcher.rb', line 4

def env
  @env
end

#optionsObject (readonly)

Returns the value of attribute options.



4
5
6
# File 'lib/rack/prerender/fetcher.rb', line 4

def options
  @options
end

Instance Method Details

#after_render(env, response) ⇒ Object



93
94
95
# File 'lib/rack/prerender/fetcher.rb', line 93

def after_render(env, response)
  (callback = options[:after_render]) && callback.call(env, response)
end

#api_url(env) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/rack/prerender/fetcher.rb', line 59

def api_url(env)
  new_env = env
  if env['CF-VISITOR']
    match = /"scheme":"(http|https)"/.match(env['CF-VISITOR'])
    new_env['HTTPS'] = true and new_env['rack.url_scheme'] = "https" and new_env['SERVER_PORT'] = 443 if (match && match[1] == 'https')
    new_env['HTTPS'] = false and new_env['rack.url_scheme'] = "http" and new_env['SERVER_PORT'] = 80 if (match && match[1] == 'http')
  end

  if env['X-FORWARDED-PROTO']
    new_env['HTTPS'] = true and new_env['rack.url_scheme'] = "https" and new_env['SERVER_PORT'] = 443 if env["X-FORWARDED-PROTO"].split(',')[0] == 'https'
    new_env['HTTPS'] = false and new_env['rack.url_scheme'] = "http" and new_env['SERVER_PORT'] = 80 if env["X-FORWARDED-PROTO"].split(',')[0] == 'http'
  end

  if options[:protocol]
    new_env['HTTPS'] = true and new_env['rack.url_scheme'] = "https" and new_env['SERVER_PORT'] = 443 if options[:protocol] == 'https'
    new_env['HTTPS'] = false and new_env['rack.url_scheme'] = "http" and new_env['SERVER_PORT'] = 80 if options[:protocol] == 'http'
  end

  url = Rack::Request.new(new_env).url
  prerender_url = prerender_service_url()
  forward_slash = prerender_url[-1, 1] == '/' ? '' : '/'
  "#{prerender_url}#{forward_slash}#{url}"
end

#before_render(env) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/rack/prerender/fetcher.rb', line 22

def before_render(env)
  return unless callback = options[:before_render]

  cached_render = callback.call(env)

  if cached_render && cached_render.is_a?(String)
    Rack::Response.new(cached_render, 200, { 'Content-Type' => 'text/html; charset=utf-8' })
  elsif cached_render && cached_render.is_a?(Rack::Response)
    cached_render
  else
    nil
  end
end

#build_rack_response_from_prerender(prerendered_response) ⇒ Object



87
88
89
90
91
# File 'lib/rack/prerender/fetcher.rb', line 87

def build_rack_response_from_prerender(prerendered_response)
  response = Rack::Response.new(prerendered_response.body, prerendered_response.code, prerendered_response)
  options[:build_rack_response_from_prerender].call(response, prerendered_response) if options[:build_rack_response_from_prerender]
  response
end

#call(env) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
# File 'lib/rack/prerender/fetcher.rb', line 10

def call(env)
  cached_response = before_render(env)
  return cached_response.finish if cached_response

  if prerendered_response = fetch(env)
    response = build_rack_response_from_prerender(prerendered_response)
    after_render(env, prerendered_response)
    return response.finish
  end
  nil
end

#fetch(env) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/rack/prerender/fetcher.rb', line 36

def fetch(env)
  url = URI.parse(api_url(env))
  headers = {
    'User-Agent'      => env['HTTP_USER_AGENT'],
    'Accept-Encoding' => 'gzip'
  }
  headers['X-Prerender-Token'] = ENV['PRERENDER_TOKEN'] if ENV['PRERENDER_TOKEN']
  headers['X-Prerender-Token'] = options[:prerender_token] if options[:prerender_token]
  req = Net::HTTP::Get.new(url.request_uri, headers)
  req.basic_auth(ENV['PRERENDER_USERNAME'], ENV['PRERENDER_PASSWORD']) if options[:basic_auth]
  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true if url.scheme == 'https'
  response = http.request(req)
  if response['Content-Encoding'] == 'gzip'
    response.body = ActiveSupport::Gzip.decompress(response.body)
    response['Content-Length'] = response.body.bytesize
    response.delete('Content-Encoding')
  end
  response
rescue
  nil
end

#prerender_service_urlObject



83
84
85
# File 'lib/rack/prerender/fetcher.rb', line 83

def prerender_service_url
  options[:prerender_service_url] || ENV['PRERENDER_SERVICE_URL'] || 'http://service.prerender.io/'
end