Class: Rack::Prerender

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

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of Prerender.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/prerender_rails.rb', line 5

def initialize(app, options={})
  # googlebot, yahoo, and bingbot are not in this list because
  # we support _escaped_fragment_ instead of checking user
  # agent for those crawlers
  @crawler_user_agents = [
    # 'googlebot',
    # 'yahoo',
    # 'bingbot',
    'baiduspider',
    'facebookexternalhit'
  ]

  @extensions_to_ignore = [
    '.js',
    '.css',
    '.less',
    '.png',
    '.jpg',
    '.jpeg',
    '.gif',
    '.pdf',
    '.doc',
    '.txt',
    '.zip',
    '.mp3',
    '.rar',
    '.exe',
    '.wmv',
    '.doc',
    '.avi',
    '.ppt',
    '.mpg',
    '.mpeg',
    '.tif',
    '.wav',
    '.mov',
    '.psd',
    '.ai',
    '.xls',
    '.mp4',
    '.m4a',
    '.swf',
    '.dat',
    '.dmg',
    '.iso',
    '.flv',
    '.m4v',
    '.torrent'
  ]

  @options = options
  @options[:whitelist] = [@options[:whitelist]] if @options[:whitelist].is_a? String
  @options[:blacklist] = [@options[:blacklist]] if @options[:blacklist].is_a? String
  @app = app
end

Instance Method Details

#build_api_url(env) ⇒ Object



117
118
119
120
121
122
# File 'lib/prerender_rails.rb', line 117

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

#call(env) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/prerender_rails.rb', line 61

def call(env)

  if should_show_prerendered_page(env)
    prerendered_response = get_prerendered_page_response(env)

    if prerendered_response && prerendered_response.is_a?(Net::HTTPSuccess)
      response = Rack::Response.new(prerendered_response.body, 200, [])
      return response.finish
    end
  end

  @app.call(env)  
end

#get_prerender_service_url ⇒ Object



124
125
126
# File 'lib/prerender_rails.rb', line 124

def get_prerender_service_url
  ENV['PRERENDER_SERVICE_URL'] || 'http://prerender.herokuapp.com/'
end

#get_prerendered_page_response(env) ⇒ Object



109
110
111
112
113
114
115
# File 'lib/prerender_rails.rb', line 109

def get_prerendered_page_response(env)
  begin
    Net::HTTP.get_response(URI.parse(build_api_url(env)))
  rescue
    nil
  end
end

#should_show_prerendered_page(env) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/prerender_rails.rb', line 75

def should_show_prerendered_page(env)
  user_agent = env['HTTP_USER_AGENT']
  return false if !user_agent

  request = Rack::Request.new(env)

  return true if request.query_string.include? '_escaped_fragment_'
  
  #if it is not a bot...dont prerender
  return false if @crawler_user_agents.all? { |crawler_user_agent| !user_agent.downcase.include?(crawler_user_agent.downcase) }

  #if it is a bot and is requesting a resource...dont prerender
  return false if @extensions_to_ignore.any? { |extension| request.path.include? extension }

  #if it is a bot and not requesting a resource and is not whitelisted...dont prerender
  return false if @options[:whitelist].is_a?(Array) && @options[:whitelist].all? { |whitelisted| !Regexp.new(whitelisted).match(request.path) }

  #if it is a bot and not requesting a resource and is not blacklisted(url or referer)...dont prerender
  if @options[:blacklist].is_a?(Array) && @options[:blacklist].any? { |blacklisted|
      blacklistedUrl = false
      blacklistedReferer = false
      regex = Regexp.new(blacklisted)

      blacklistedUrl = !!regex.match(request.path)
      blacklistedReferer = !!regex.match(request.referer) if request.referer

      blacklistedUrl || blacklistedReferer
    }
    return false
  end 

  return true
end