headless-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: 3430eeda993cfbe14e78e0db458e45ffcff310f7
4
- data.tar.gz: aaacaea9451a308e118149656d1b7b7bf7e994f2
3
+ metadata.gz: f8f528076eccde288b3cec6d1fe33dcbddbea353
4
+ data.tar.gz: 0ac9c6ce2bb2856dd14b8c24588d4fd546e0408d
5
5
  SHA512:
6
- metadata.gz: f15c29d05d3386ef1c52c9212d20d938958afc61014b6db81f87941d978e5d7eb890b4580112d1e08074418a9cd1f86aa27fd54b8a675258749dbb247d74d616
7
- data.tar.gz: 366451b773dd444f436e02af981271c39bcc5e0a9489c8c69fb8c6cc71abcd1a3005b22cdb6e7df70d2937dbb214e0c8d38c638b93dfea81b2400cea21db0a97
6
+ metadata.gz: 4ec9616d598293f33e8876f5649e14b5bbfaee4fa7da824bd6b0990cb701025ed26799c9171c91b476cd57e68bad63b3ece0b2cbc7b63b6737b0df041d9614f9
7
+ data.tar.gz: ab7267fdb39ab4699200ccc3ca0cb0943697209c2c95eb0ba5d55c7970ce9c38b6bfc5106d1452f48b54dc44e3abc43dd6ba645026e29401cadc7821964e83fb
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Headless::Rails
2
2
 
3
+ [![Build Status](https://travis-ci.org/headlessapp/headless-rails.png?branch=master)](https://travis-ci.org/headlessapp/headless-rails)
4
+
3
5
  API wrapper for the headlessapp.com service.
4
6
 
5
7
  Seamlessly integrate AJAX webcrawler support into your javascript application.
@@ -0,0 +1,32 @@
1
+ module Headless
2
+ module AjaxCrawler
3
+ class RequestMatcher< Struct.new(:request)
4
+
5
+ def self.call(request)
6
+ new(request).match?
7
+ end
8
+
9
+ def match?
10
+ is_get? && has_escaped_fragment?
11
+ end
12
+
13
+ private
14
+
15
+ def is_get?
16
+ request.get?
17
+ end
18
+
19
+ def has_escaped_fragment?
20
+ get_params.has_key?(escaped_fragment_key)
21
+ end
22
+
23
+ def escaped_fragment_key
24
+ ::Headless::AjaxCrawler::ESCAPED_FRAGMENT_KEY
25
+ end
26
+
27
+ def get_params
28
+ request.GET
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,24 +1,26 @@
1
1
  require 'rack/utils'
2
2
 
3
3
  module Headless
4
- module Rails
5
- class EscapedFragmentExtractor < Struct.new(:request)
4
+ module AjaxCrawler
5
+ class UrlExtractor < Struct.new(:request)
6
6
 
7
7
  def self.call(request)
8
8
  new(request).call
9
9
  end
10
10
 
11
11
  def call
12
- url = "#{protocol}#{host_with_port}#{path}"
13
- url << "?#{query_string}" unless query_string.empty?
14
- url << "##{hash_string}" unless hash_string.empty?
12
+ url = "#{scheme}://#{host_with_port}#{path}"
13
+ url << "?#{query_string}" unless query_string.empty?
14
+ url << "##{escaped_fragment}" unless escaped_fragment.nil? || escaped_fragment.empty?
15
15
  url
16
16
  end
17
17
 
18
18
  private
19
19
 
20
- def protocol
21
- request.protocol
20
+ # delegate to request
21
+
22
+ def scheme
23
+ request.scheme
22
24
  end
23
25
 
24
26
  def host_with_port
@@ -29,22 +31,24 @@ module Headless
29
31
  request.path
30
32
  end
31
33
 
32
- def hash_string
33
- escaped_fragment
34
+ def get_params
35
+ request.GET
34
36
  end
35
37
 
38
+ # extract the fragment
39
+
36
40
  def escaped_fragment
37
- request.GET[escaped_fragment_key]
41
+ get_params[escaped_fragment_key]
38
42
  end
39
43
 
40
44
  def params_without_fragment
41
- without = request.GET.dup
45
+ without = get_params.dup
42
46
  without.delete(escaped_fragment_key)
43
47
  without
44
48
  end
45
49
 
46
50
  def escaped_fragment_key
47
- ::Headless::Rails::ESCAPED_FRAGMENT_KEY
51
+ ::Headless::AjaxCrawler::ESCAPED_FRAGMENT_KEY
48
52
  end
49
53
 
50
54
  def query_string
@@ -0,0 +1,8 @@
1
+ require 'headless/ajax_crawler/request_matcher'
2
+ require 'headless/ajax_crawler/url_extractor'
3
+
4
+ module Headless
5
+ module AjaxCrawler
6
+ ESCAPED_FRAGMENT_KEY = "_escaped_fragment_".freeze
7
+ end
8
+ end
@@ -1,5 +1,5 @@
1
1
  module Headless
2
2
  module Rails
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
@@ -1,17 +1,15 @@
1
1
  require "headless/rails/version"
2
- require "headless/rails/escaped_fragment_extractor"
2
+ require "headless/ajax_crawler"
3
3
  require "headless/api_client"
4
4
 
5
5
  module Headless
6
6
  module Rails
7
7
 
8
- ESCAPED_FRAGMENT_KEY = "_escaped_fragment_".freeze
9
-
10
8
  def respond_to_ajax_crawlers
11
- if params.has_key?(ESCAPED_FRAGMENT_KEY)
12
- url = ::Headless::Rails::EscapedFragmentExtractor.call(request)
9
+ if ::Headless::AjaxCrawler::RequestMatcher.call(request)
10
+ url = ::Headless::AjaxCrawler::UrlExtractor.call(request)
13
11
  crawled = ::Headless::APIClient.crawl(url)
14
- render text: crawled.content if crawled.success?
12
+ render :text => crawled.content if crawled.success?
15
13
  end
16
14
  end
17
15
 
@@ -0,0 +1,37 @@
1
+ require "spec_helper"
2
+ require "headless/ajax_crawler/request_matcher"
3
+
4
+ RSpec.describe Headless::AjaxCrawler::RequestMatcher do
5
+
6
+ describe "call" do
7
+
8
+ it "returns false with no fragment" do
9
+ request = request_for_uri("/user/matthewrudy")
10
+ expect(call(request)).to be_false
11
+ end
12
+
13
+ it "returns false with no fragment and some params" do
14
+ request = request_for_uri("/user/matthewrudy?foo=bar")
15
+ expect(call(request)).to be_false
16
+ end
17
+
18
+ it "returns true with an empty escaped_fragment" do
19
+ request = request_for_uri("/user/matthewrudy?_escaped_fragment_=")
20
+ expect(call(request)).to be_true
21
+ end
22
+
23
+ it "returns true with an escaped_fragment" do
24
+ request = request_for_uri("/user/matthewrudy?foo=bar&_escaped_fragment_=/show/twitter")
25
+ expect(call(request)).to be_true
26
+ end
27
+
28
+ it "returns false for a POST request, even with an escaped_fragment" do
29
+ request = post_request_for_uri("/user/matthewrudy?foo=bar&_escaped_fragment_=/show/twitter")
30
+ expect(call(request)).to be_false
31
+ end
32
+
33
+ def call(request)
34
+ described_class.call(request)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+ require 'rack/request'
3
+
4
+ RSpec.describe Headless::AjaxCrawler::UrlExtractor do
5
+
6
+ describe "call" do
7
+
8
+ let(:request) { request_for_uri(uri) }
9
+
10
+ subject do
11
+ described_class.call(request)
12
+ end
13
+
14
+ context "with no escaped_fragment" do
15
+
16
+ let(:uri) { "/user/matthewrudy" }
17
+
18
+ it "returns a full url" do
19
+ expect(subject).to eq "http://localhost:3000/user/matthewrudy"
20
+ end
21
+ end
22
+
23
+ context "with some params" do
24
+
25
+ let(:uri) { "/user/matthewrudy?foo=bar" }
26
+
27
+ it "keeps the params intact" do
28
+ expect(subject).to eq "http://localhost:3000/user/matthewrudy?foo=bar"
29
+ end
30
+ end
31
+
32
+ context "with an empty escaped_fragment" do
33
+
34
+ let(:uri) { "/user/matthewrudy?_escaped_fragment_=" }
35
+
36
+ it "returns a full url with the escaped fragment removed" do
37
+ expect(subject).to eq "http://localhost:3000/user/matthewrudy"
38
+ end
39
+ end
40
+
41
+ context "with an escaped_fragment" do
42
+
43
+ let(:uri) { "/user/matthewrudy?_escaped_fragment_=/show/twitter" }
44
+
45
+ it "returns the full url with an anchor appended" do
46
+ expect(subject).to eq "http://localhost:3000/user/matthewrudy#/show/twitter"
47
+ end
48
+ end
49
+
50
+ context "with an escaped_fragment and some params" do
51
+
52
+ let(:uri) { "/user/matthewrudy?foo=bar&_escaped_fragment_=/show/twitter" }
53
+
54
+ it "returns the full url with an anchor appended" do
55
+ expect(subject).to eq "http://localhost:3000/user/matthewrudy?foo=bar#/show/twitter"
56
+ end
57
+ end
58
+ end
59
+ end
@@ -9,11 +9,11 @@ RSpec.describe Headless::Rails do
9
9
  double(:controller,
10
10
  :request => request,
11
11
  :params => {},
12
- :render => nil,
12
+ :render => nil
13
13
  )
14
14
  end
15
15
 
16
- let(:request) { double(:request) }
16
+ let(:request) { request_for_uri("/user/matthewrudy?foo=bar") }
17
17
  let(:headless_response) { double(:headless_response, :success? => true, :content => :headless_content) }
18
18
 
19
19
  describe "respond_to_ajax_crawlers" do
@@ -22,6 +22,9 @@ RSpec.describe Headless::Rails do
22
22
  end
23
23
 
24
24
  context "with no escaped_fragment" do
25
+
26
+ let(:request) { request_for_uri("/user/matthewrudy?foo=bar") }
27
+
25
28
  before do
26
29
  controller.stub(:params).and_return({})
27
30
  end
@@ -39,11 +42,11 @@ RSpec.describe Headless::Rails do
39
42
  end
40
43
 
41
44
  context "with an escaped fragment" do
42
- before do
43
- controller.stub(:params).and_return({"_escaped_fragment_" => "something"})
44
45
 
45
- expect(Headless::Rails::EscapedFragmentExtractor).to receive(:call).with(request).and_return(:a_url)
46
- expect(Headless::APIClient).to receive(:crawl).with(:a_url).and_return(headless_response)
46
+ let(:request) { request_for_uri("/user/matthewrudy?foo=bar&_escaped_fragment_=/show/twitter") }
47
+
48
+ before do
49
+ expect(Headless::APIClient).to receive(:crawl).with("http://localhost:3000/user/matthewrudy?foo=bar#/show/twitter").and_return(headless_response)
47
50
  end
48
51
 
49
52
  it "extracts the fragment, fetches content from the api, and renders its" do
data/spec/spec_helper.rb CHANGED
@@ -1,2 +1,7 @@
1
1
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
2
  require 'headless/rails'
3
+ require 'support/example_requests'
4
+
5
+ RSpec.configure do |c|
6
+ c.include ExampleRequests
7
+ end
@@ -0,0 +1,48 @@
1
+ module ExampleRequests
2
+
3
+ def request_env_for_uri(uri, http_verb="GET")
4
+ path, query = uri.split("?")
5
+
6
+ {
7
+ "SERVER_SOFTWARE" => "thin 1.5.1 codename Straight Razor",
8
+ "HTTP_VERSION" => "HTTP/1.1",
9
+ "HTTP_CONNECTION" => "keep-alive",
10
+ "HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
11
+ "HTTP_USER_AGENT" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36",
12
+ "HTTP_ACCEPT_ENCODING" => "gzip,deflate,sdch",
13
+ "HTTP_ACCEPT_LANGUAGE" => "en-GB,en;q=0.8,en-US;q=0.6,zh;q=0.4",
14
+ "HTTP_COOKIE" => "foo=bar",
15
+ "GATEWAY_INTERFACE" => "CGI/1.2",
16
+
17
+ "SCRIPT_NAME" => "",
18
+ "REMOTE_ADDR" => "127.0.0.1",
19
+
20
+ # http method
21
+ "REQUEST_METHOD" => http_verb,
22
+
23
+ # protocol
24
+ "SERVER_PROTOCOL" => "HTTP/1.1",
25
+ "rack.url_scheme" => "http",
26
+
27
+ # host and port
28
+ "SERVER_NAME" => "localhost",
29
+ "HTTP_HOST" => "localhost:3000",
30
+ "SERVER_PORT" => "3000",
31
+
32
+ # path and query string
33
+ "REQUEST_PATH" => path,
34
+ "PATH_INFO" => path,
35
+ "REQUEST_URI" => uri,
36
+ "QUERY_STRING" => query,
37
+ }
38
+ end
39
+
40
+ def request_for_uri(uri)
41
+ ::Rack::Request.new(request_env_for_uri(uri))
42
+ end
43
+
44
+ def post_request_for_uri(uri)
45
+ ::Rack::Request.new(request_env_for_uri(uri, "POST"))
46
+ end
47
+
48
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: headless-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
  - Matthew Rudy Jacobs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-11 00:00:00.000000000 Z
11
+ date: 2013-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -109,16 +109,20 @@ files:
109
109
  - README.md
110
110
  - Rakefile
111
111
  - headless-rails.gemspec
112
+ - lib/headless/ajax_crawler.rb
113
+ - lib/headless/ajax_crawler/request_matcher.rb
114
+ - lib/headless/ajax_crawler/url_extractor.rb
112
115
  - lib/headless/api_client.rb
113
116
  - lib/headless/api_response.rb
114
117
  - lib/headless/rails.rb
115
- - lib/headless/rails/escaped_fragment_extractor.rb
116
118
  - lib/headless/rails/version.rb
119
+ - spec/headless/ajax_crawler/request_matcher_spec.rb
120
+ - spec/headless/ajax_crawler/url_extractor_spec.rb
117
121
  - spec/headless/ap_response_spec.rb
118
122
  - spec/headless/api_client_spec.rb
119
- - spec/headless/rails/escaped_fragment_extractor_spec.rb
120
123
  - spec/headless/rails_spec.rb
121
124
  - spec/spec_helper.rb
125
+ - spec/support/example_requests.rb
122
126
  homepage: http://www.headlessapp.com
123
127
  licenses:
124
128
  - MIT
@@ -144,8 +148,10 @@ signing_key:
144
148
  specification_version: 4
145
149
  summary: API wrapper for the HeadlessApp.com
146
150
  test_files:
151
+ - spec/headless/ajax_crawler/request_matcher_spec.rb
152
+ - spec/headless/ajax_crawler/url_extractor_spec.rb
147
153
  - spec/headless/ap_response_spec.rb
148
154
  - spec/headless/api_client_spec.rb
149
- - spec/headless/rails/escaped_fragment_extractor_spec.rb
150
155
  - spec/headless/rails_spec.rb
151
156
  - spec/spec_helper.rb
157
+ - spec/support/example_requests.rb
@@ -1,38 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe Headless::Rails::EscapedFragmentExtractor do
4
-
5
- def request_with_fragment(escaped_fragment)
6
- double(:request,
7
- :protocol => "http://",
8
- :host_with_port => "localhost:3000",
9
- :path => "/user/matthewrudy",
10
- :GET => {
11
- "_escaped_fragment_" => escaped_fragment,
12
- }
13
- )
14
- end
15
-
16
- describe "call" do
17
-
18
- context "with an empty escaped_fragment" do
19
- subject do
20
- described_class.call(request_with_fragment(""))
21
- end
22
-
23
- it "returns a full url with the escaped fragment removed" do
24
- expect(subject).to eq "http://localhost:3000/user/matthewrudy"
25
- end
26
- end
27
-
28
- context "with an escaped_fragment" do
29
- subject do
30
- described_class.call(request_with_fragment("/show/twitter"))
31
- end
32
-
33
- it "returns the full url with an anchor appended" do
34
- expect(subject).to eq "http://localhost:3000/user/matthewrudy#/show/twitter"
35
- end
36
- end
37
- end
38
- end