prerender_rails 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9131d6f39c2dc688b5255b910007e5a434fe85a5
4
- data.tar.gz: fd614761588694380e2abbb6ec3c6a32c64d42f8
3
+ metadata.gz: 4e710c94d4517957a7198a878b74edb3d2ce599a
4
+ data.tar.gz: 3d61079a206b75b6ebf47d2acd64ed1774fa1b25
5
5
  SHA512:
6
- metadata.gz: cd0a338c2026fa5c6abd80bc97410619df877ff94b2dc44e283b6f7c6119959aebb9b8dd307deec5f42f9a88d019ca3977c74f748175071ae3a28c771b2a1d15
7
- data.tar.gz: 4fd993cf3da044b7a2fa60da6e09be5d83cd51cdcceeb855c3f47edf58564d41d0e7b7e63a6ce58f08c3baa9daca80b84ea53ecf536901e68cbef6370d163d37
6
+ metadata.gz: e2f1fd70277c97905a06b2e674ca4e882aea82700c8abdc65eb65e6b4f2a016392f1bb97482bcd8e7fc87269f26ef51ced69b8cdfb2e937abff8b85c209c9abe
7
+ data.tar.gz: d5f453676bf4373c2c6634713684ccd938ca1761cea76518ec29aff5b2f3a5ce5567fc8083befa2df2d6afe31dd8ba78c7f6191f1319df06246d548d415373b4
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
data/README.md CHANGED
@@ -1,46 +1,68 @@
1
- Prerender Rails
1
+ Prerender Rails [![Build Status](https://travis-ci.org/collectiveip/prerender_rails.png)](https://travis-ci.org/collectiveip/prerender_rails)
2
2
  ===========================
3
3
 
4
- This gem installs middleware that prerenders a javascript-rendered page and sends the HTML to a search engine crawler for SEO. It checks the agent string on the requesting browser for a crawler, and continues on to your normal routes if the requester is not a crawler.
4
+ Are you using backbone, angular, emberjs, etc, but you're unsure about the SEO implications?
5
5
 
6
- ## How it works
7
- * Check to make sure the request is from a crawler and we aren't requesting a resource (js, css, etc...)
8
- * Make a `GET` request to the [prerender service](https://github.com/collectiveip/prerender) for the page's prerendered HTML
9
- * Return that HTML to the crawler
10
-
11
- ## Installation
6
+ Use this gem to install rails middleware that prerenders a javascript-rendered page and returns the HTML to the search engine crawler for SEO.
12
7
 
13
8
  Add this line to your application's Gemfile:
14
9
 
15
10
  gem 'prerender_rails'
16
11
 
17
- And then execute:
12
+ And in `config/environment/production.rb`, add this line:
13
+
14
+ ```ruby
15
+ config.middleware.use Rack::Prerender
16
+ ```
18
17
 
19
- $ bundle
18
+ ## How it works
19
+ 1. Check to make sure we should show a prerendered page
20
+ 1. Check if the request is from a crawler (agent string)
21
+ 2. Check to make sure we aren't requesting a resource (js, css, etc...)
22
+ 3. (optional) Check to make sure the url is in the whitelist
23
+ 4. (optional) Check to make sure the url isn't in the blacklist
24
+ 2. Make a `GET` request to the [prerender service](https://github.com/collectiveip/prerender)(phantomjs server) for the page's prerendered HTML
25
+ 3. Return that HTML to the crawler
20
26
 
21
- Or install it yourself as:
27
+ ## Customization
22
28
 
23
- $ gem install prerender_rails
29
+ ### Whitelist
24
30
 
25
- ## Usage
31
+ Whitelist a single url path or multiple url paths. If a whitelist is supplied, only url's containing a whitelist path will be prerendered.
32
+ ```ruby
33
+ config.middleware.use Rack::Prerender, whitelist: '/search/tto'
34
+ ```
35
+ ```ruby
36
+ config.middleware.use Rack::Prerender, whitelist: ['/search', '/profile']
37
+ ```
26
38
 
27
- In `config/environment/production.rb`, add this line:
39
+ ### Blacklist
28
40
 
41
+ Blacklist a single url path or multiple url paths. If a blacklist is supplied, all url's will be prerendered except ones containing a blacklist path.
29
42
  ```ruby
30
- config.middleware.use Rack::Prerender
43
+ config.middleware.use Rack::Prerender, blacklist: '/search/tto'
31
44
  ```
45
+ ```ruby
46
+ config.middleware.use Rack::Prerender, blacklist: ['/search', '/profile']
47
+ ```
48
+
49
+ ### Using your own prerender service
50
+
51
+ If you've deployed the prerender service on your own, set the `PRERENDER_SERVICE_URL` environment variable so that this package points there instead. Otherwise, it will default to the service already deployed at `http://prerender.herokuapp.com`
32
52
 
33
- If you've deployed the prerender service on your own, set the `PRERENDER_URL` environment variable so that this gem points there instead. Otherwise, it will default to the service already deployed at `http://prerender.herokuapp.com`
53
+ $ export PRERENDER_SERVICE_URL=<new url>
34
54
 
35
- $ export PRERENDER_URL=<new url>
55
+ ## Testing
36
56
 
37
- ## Contributing
57
+ If you want to make sure your pages are rendering correctly:
38
58
 
39
- 1. Fork it
40
- 2. Create your feature branch (`git checkout -b my-new-feature`)
41
- 3. Commit your changes (`git commit -am 'Add some feature'`)
42
- 4. Push to the branch (`git push origin my-new-feature`)
43
- 5. Create new Pull Request
59
+ 1. Open the Developer Tools in Chrome (Cmd + Atl + J)
60
+ 2. Click the Settings gear in the bottom right corner.
61
+ 3. Click "Overrides" on the left side of the settings panel.
62
+ 4. Check the "User Agent" checkbox.
63
+ 6. Choose "Other..." from the User Agent dropdown.
64
+ 7. Type `googlebot` into the input box.
65
+ 8. Refresh the page (make sure to keep the developer tools open).
44
66
 
45
67
  ## License
46
68
 
data/Rakefile CHANGED
@@ -1 +1,12 @@
1
+ #!/usr/bin/env rake
1
2
  require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << 'lib/prerender_rails'
8
+ t.test_files = FileList['test/lib/prerender_rails.rb']
9
+ t.verbose = true
10
+ end
11
+
12
+ task :default => :test
@@ -1,10 +1,30 @@
1
- require "rack/version"
2
-
3
1
  module Rack
4
2
  class Prerender
5
3
  require 'net/http'
6
4
 
7
- def initialize(app)
5
+ def initialize(app, options={})
6
+ @crawler_user_agents = [
7
+ 'googlebot',
8
+ 'yahoo',
9
+ 'bingbot',
10
+ 'baiduspider'
11
+ ]
12
+
13
+ @extensions_to_ignore = [
14
+ '.js',
15
+ '.css',
16
+ '.less',
17
+ '.png',
18
+ '.jpg',
19
+ '.jpeg',
20
+ '.gif',
21
+ '.pdf',
22
+ '.doc'
23
+ ]
24
+
25
+ @options = options
26
+ @options[:whitelist] = [@options[:whitelist]] if @options[:whitelist].is_a? String
27
+ @options[:blacklist] = [@options[:blacklist]] if @options[:blacklist].is_a? String
8
28
  @app = app
9
29
  end
10
30
 
@@ -23,36 +43,53 @@ module Rack
23
43
  end
24
44
 
25
45
  def should_show_prerendered_page(env)
46
+ user_agent = env['HTTP_USER_AGENT']
47
+ return false if !user_agent
48
+
26
49
  request = Rack::Request.new(env)
27
- user_agent = env['HTTP_USER_AGENT'].downcase
28
50
 
29
- should_show_based_on_agent_string = user_agent == 'googlebot' ||
30
- user_agent == 'yahoo' ||
31
- user_agent == 'bingbot' ||
32
- user_agent == 'baiduspider'
51
+ #if it is not a bot...dont prerender
52
+ return false if !@crawler_user_agents.include?(user_agent.downcase)
53
+
54
+ #if it is a bot and is requesting a resource...dont prerender
55
+ return false if @extensions_to_ignore.any? { |extension| request.path.include? extension }
56
+
57
+ #if it is a bot and not requesting a resource and is not whitelisted...dont prerender
58
+ return false if @options[:whitelist].is_a?(Array) && @options[:whitelist].all? { |whitelisted| !request.path.include? whitelisted }
33
59
 
34
- return false if !should_show_based_on_agent_string #short circuit
60
+ #if it is a bot and not requesting a resource and is not blacklisted(url or referer)...dont prerender
61
+ if @options[:blacklist].is_a?(Array) && @options[:blacklist].any? { |blacklisted|
62
+ blacklistedUrl = false
63
+ blacklistedReferer = false
35
64
 
36
- should_show_based_on_extension = !request.path.include?('.js') &&
37
- !request.path.include?('.css') &&
38
- !request.path.include?('.less') &&
39
- !request.path.include?('.png') &&
40
- !request.path.include?('.jpg') &&
41
- !request.path.include?('.jpeg') &&
42
- !request.path.include?('.gif')
65
+ blacklistedUrl = request.path.include? blacklisted
66
+ blacklistedReferer = request.referer.include? blacklisted if request.referer
43
67
 
44
- should_show_based_on_agent_string && should_show_based_on_extension
68
+ blacklistedUrl || blacklistedReferer
69
+ }
70
+ return false
71
+ end
72
+
73
+ return true
45
74
  end
46
75
 
47
76
  def get_prerendered_page_response(env)
48
77
  begin
49
- url = Rack::Request.new(env).url
50
- prerender_url = ENV['PRERENDER_URL'] || 'http://prerender.herokuapp.com/'
51
- forward_slash = prerender_url[-1, 1] == '/' ? '' : '/'
52
- Net::HTTP.get_response(URI.parse("#{prerender_url}#{forward_slash}#{url}"))
78
+ Net::HTTP.get_response(URI.parse(build_api_url(env)))
53
79
  rescue
54
80
  nil
55
81
  end
56
82
  end
83
+
84
+ def build_api_url(env)
85
+ url = Rack::Request.new(env).url
86
+ prerender_url = get_prerender_service_url()
87
+ forward_slash = prerender_url[-1, 1] == '/' ? '' : '/'
88
+ "#{prerender_url}#{forward_slash}#{url}"
89
+ end
90
+
91
+ def get_prerender_service_url
92
+ ENV['PRERENDER_SERVICE_URL'] || 'http://prerender.herokuapp.com/'
93
+ end
57
94
  end
58
95
  end
@@ -1,13 +1,10 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'rack/version'
5
2
 
6
3
  Gem::Specification.new do |spec|
7
4
  spec.name = "prerender_rails"
8
- spec.version = PrerenderRails::VERSION
5
+ spec.version = "0.0.3"
9
6
  spec.authors = ["Todd Hooper"]
10
- spec.email = ["thoop3@gmail.com"]
7
+ spec.email = ["todd@collectiveip.com"]
11
8
  spec.description = %q{Rails middleware to prerender your javascript heavy pages on the fly by a phantomjs service}
12
9
  spec.summary = %q{Prerender your backbone/angular/javascript rendered application on the fly when search engines crawl}
13
10
  spec.homepage = "https://github.com/collectiveip/prerender_rails"
@@ -18,6 +15,9 @@ Gem::Specification.new do |spec|
18
15
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
16
  spec.require_paths = ["lib"]
20
17
 
18
+ spec.add_dependency 'rack', '>= 0'
19
+
21
20
  spec.add_development_dependency "bundler", "~> 1.3"
22
21
  spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "webmock"
23
23
  end
@@ -0,0 +1,97 @@
1
+ require_relative '../test_helper'
2
+
3
+ describe Rack::Prerender do
4
+
5
+ bot = 'googlebot'
6
+ user = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36'
7
+
8
+ before :each do
9
+ @app = lambda do |params|
10
+ [200, {}, ""]
11
+ end
12
+
13
+ @prerender = Rack::Prerender.new(@app)
14
+ end
15
+
16
+ it "should return a prerendered reponse for a crawler" do
17
+ request = Rack::MockRequest.env_for "/", "HTTP_USER_AGENT" => bot
18
+ stub_request(:get, @prerender.build_api_url(request)).to_return(:body => "<html></html>")
19
+ response = Rack::Prerender.new(@app).call(request)
20
+
21
+ assert_equal response[2].body, ["<html></html>"]
22
+ end
23
+
24
+ it "should continue to app routes if user is not a bot by checking agent string" do
25
+ request = Rack::MockRequest.env_for "/", "HTTP_USER_AGENT" => user
26
+ response = Rack::Prerender.new(@app).call(request)
27
+
28
+ assert_equal response[2], ""
29
+ end
30
+
31
+ it "should continue to app routes if user is a bot, but the bot is requesting a resource file" do
32
+ request = Rack::MockRequest.env_for "/main.js?anyQueryParam=true", "HTTP_USER_AGENT" => bot
33
+ response = Rack::Prerender.new(@app).call(request)
34
+
35
+ assert_equal response[2], ""
36
+ end
37
+
38
+ it "should continue to app routes if the url is not part of the whitelist" do
39
+ request = Rack::MockRequest.env_for "/profile/blah", "HTTP_USER_AGENT" => bot
40
+ response = Rack::Prerender.new(@app, whitelist: ['/search', '/help']).call(request)
41
+
42
+ assert_equal response[2], ""
43
+ end
44
+
45
+ it "should return a prerendered response if the url is part of the whitelist" do
46
+ request = Rack::MockRequest.env_for "/search/things?query=blah", "HTTP_USER_AGENT" => bot
47
+ stub_request(:get, @prerender.build_api_url(request)).to_return(:body => "<html></html>")
48
+ response = Rack::Prerender.new(@app, whitelist: ['/search', '/help']).call(request)
49
+
50
+ assert_equal response[2].body, ["<html></html>"]
51
+ end
52
+
53
+ it "should continue to app routes if the url is part of the blacklist" do
54
+ request = Rack::MockRequest.env_for "/search/things?query=blah", "HTTP_USER_AGENT" => bot
55
+ response = Rack::Prerender.new(@app, blacklist: ['/search', '/help']).call(request)
56
+
57
+ assert_equal response[2], ""
58
+ end
59
+
60
+ it "should return a prerendered response if the url is not part of the blacklist" do
61
+ request = Rack::MockRequest.env_for "/profile/blah", "HTTP_USER_AGENT" => bot
62
+ stub_request(:get, @prerender.build_api_url(request)).to_return(:body => "<html></html>")
63
+ response = Rack::Prerender.new(@app, blacklist: ['/search', '/help']).call(request)
64
+
65
+ assert_equal response[2].body, ["<html></html>"]
66
+ end
67
+
68
+ it "should continue to app routes if the referer is part of the blacklist" do
69
+ request = Rack::MockRequest.env_for "/api/results", "HTTP_USER_AGENT" => bot, "HTTP_REFERER" => '/search'
70
+ response = Rack::Prerender.new(@app, blacklist: ['/search', '/help']).call(request)
71
+
72
+ assert_equal response[2], ""
73
+ end
74
+
75
+ it "should return a prerendered response if the referer is not part of the blacklist" do
76
+ request = Rack::MockRequest.env_for "/api/results", "HTTP_USER_AGENT" => bot, "HTTP_REFERER" => '/search'
77
+ stub_request(:get, @prerender.build_api_url(request)).to_return(:body => "<html></html>")
78
+ response = Rack::Prerender.new(@app, blacklist: ['/profile', '/help']).call(request)
79
+
80
+ assert_equal response[2].body, ["<html></html>"]
81
+ end
82
+
83
+ describe '#buildApiUrl' do
84
+ it "should build the correct api url with the default url" do
85
+ request = Rack::MockRequest.env_for "https://google.com/search?q=javascript"
86
+ assert_equal @prerender.build_api_url(request), 'http://prerender.herokuapp.com/https://google.com/search?q=javascript'
87
+ end
88
+
89
+ it "should build the correct api url with an environment variable url" do
90
+ ENV['PRERENDER_SERVICE_URL'] = 'http://prerenderurl.com'
91
+ request = Rack::MockRequest.env_for "https://google.com/search?q=javascript"
92
+ assert_equal @prerender.build_api_url(request), 'http://prerenderurl.com/https://google.com/search?q=javascript'
93
+ ENV['PRERENDER_SERVICE_URL'] = nil
94
+ end
95
+ end
96
+
97
+ end
@@ -0,0 +1,4 @@
1
+ require 'minitest/autorun'
2
+ require 'webmock/minitest'
3
+ require 'rack'
4
+ require File.expand_path('../../lib/prerender_rails.rb', __FILE__)
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prerender_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Todd Hooper
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-27 00:00:00.000000000 Z
11
+ date: 2013-09-29 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,22 +52,38 @@ dependencies:
38
52
  - - '>='
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  description: Rails middleware to prerender your javascript heavy pages on the fly
42
70
  by a phantomjs service
43
71
  email:
44
- - thoop3@gmail.com
72
+ - todd@collectiveip.com
45
73
  executables: []
46
74
  extensions: []
47
75
  extra_rdoc_files: []
48
76
  files:
49
77
  - .gitignore
78
+ - .travis.yml
50
79
  - Gemfile
51
80
  - LICENSE.txt
52
81
  - README.md
53
82
  - Rakefile
54
83
  - lib/prerender_rails.rb
55
- - lib/rack/version.rb
56
84
  - prerender_rails.gemspec
85
+ - test/lib/prerender_rails.rb
86
+ - test/test_helper.rb
57
87
  homepage: https://github.com/collectiveip/prerender_rails
58
88
  licenses:
59
89
  - MIT
@@ -79,4 +109,6 @@ signing_key:
79
109
  specification_version: 4
80
110
  summary: Prerender your backbone/angular/javascript rendered application on the fly
81
111
  when search engines crawl
82
- test_files: []
112
+ test_files:
113
+ - test/lib/prerender_rails.rb
114
+ - test/test_helper.rb
data/lib/rack/version.rb DELETED
@@ -1,3 +0,0 @@
1
- module PrerenderRails
2
- VERSION = "0.0.2"
3
- end