open_graphy 1.0.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 37f58ad61b985b57779656bf55788c7225cf4888
4
+ data.tar.gz: 600252251fcbdfe00fbec7b5749cda00b9f8aed2
5
+ SHA512:
6
+ metadata.gz: 2de2b2042538b30620c834bfd5aea773de8d0bd0fd9d783ee5f6fc1d045dc64453b00722a7ba571a938f18f1797ef1e653848398272ae6cc91ca0711e7295b48
7
+ data.tar.gz: d752d82c76f92915b90221345c138fbb6404ad48ec28bca32789de863a3a68dbb69bb99c0ba91901c7c467a088534495e235177238d01c983e574e8b8f150c91
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.3
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ before_install:
2
+ - gem install bundler
3
+ rvm:
4
+ - 2.3.0
5
+ - 2.2
6
+ - jruby-9.1.2.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in open_graphy.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016 On The Beach Ltd.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # OpenGraphy [![Build Status](https://travis-ci.org/onthebeach/open_graphy.svg)](https://travis-ci.org/onthebeach/open_graphy) [![Gem Version](https://badge.fury.io/rb/open_graphy.svg)](http://badge.fury.io/rb/open_graphy)
2
+
3
+ This ruby gem allow you to fetch data that follows the opengraph protocol, and lets you fetch data from custom metatags also.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'open_graphy'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install open_graphy
20
+
21
+ ## Usage
22
+
23
+ Firstly require the gem using:
24
+ ```ruby
25
+ require 'open_graphy'
26
+ ```
27
+
28
+ To fetch opengraph data from a URL use:
29
+ ```ruby
30
+ movie = OpenGraphy.fetch("https://www.rottentomatoes.com/m/coffee_and_cigarettes/")
31
+ ```
32
+ The fetch method returns an object with methods defined that can be used to access the data retrieved. A is also defined so you can check the existence of data before using it.
33
+ ```ruby
34
+ movie.title #=> "Coffee and Cigarettes"
35
+ movie.image? #=> true
36
+ movie.image #=> "https://resizing.flixster.com/9l1s-frU7dhkYqr0V-C0AlDpJuU=/740x290/v1.bjs3MDg4NTg7ajsxNzA2MzsxMjAwOzEyODA7NzIw"
37
+ movie.type #=> "video.movie"
38
+ ```
39
+
40
+ ## Configuration
41
+ By default the gem is set to look for og metatags.
42
+ To fetch data from custom metatags you can configure the gem, the example below shows a typical configuration.
43
+
44
+ ```ruby
45
+ OpenGraphy.configure do |config|
46
+ config.metatags = ["og:", "custom:tag:",]
47
+ end
48
+ ```
49
+
50
+ When fetching data the default useragent is `OpenGraphyBot`, the example below shows a custom user agent being set.
51
+
52
+ ```ruby
53
+ OpenGraphy.configure do |config|
54
+ config.user_agent = 'DataBot/0.6'
55
+ end
56
+ ```
57
+
58
+ ## Copyright
59
+
60
+ Copyright (c) 2016 OnTheBeach Ltd. See LICENSE.txt for further details.
61
+
62
+ ## Contributing
63
+
64
+ 1. Fork it ( https://github.com/[my-github-username]/open_graphy/fork )
65
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
66
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
67
+ 4. Push to the branch (`git push origin my-new-feature`)
68
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+ require 'bundler/gem_tasks'
3
+
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec) do |spec|
8
+ spec.pattern = FileList['spec/**/*_spec.rb']
9
+ end
10
+
11
+ desc 'Run the test suite'
12
+ task :default => :spec
@@ -0,0 +1,11 @@
1
+ module OpenGraphy
2
+ class Configuration
3
+ include Singleton
4
+ attr_accessor :metatags, :user_agent
5
+
6
+ def initialize
7
+ @metatags = ['og:']
8
+ @user_agent = 'OpenGraphyBot'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,67 @@
1
+ module OpenGraphy
2
+ module Uri
3
+ class Fetcher
4
+ def initialize(uri_str, limit = 10)
5
+ @uri_str, @limit = uri_str, limit
6
+ end
7
+
8
+ def fetch
9
+ check_redirect_limit
10
+
11
+ http_response = response
12
+ case http_response
13
+ when Net::HTTPSuccess then
14
+ http_response
15
+ when Net::HTTPRedirection then
16
+ follow_redirection(http_response)
17
+ else
18
+ http_response.value
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def follow_redirection(http_response)
25
+ @uri_str = http_response['location']
26
+ @limit -= 1
27
+ self.fetch
28
+ end
29
+
30
+ def check_redirect_limit
31
+ raise Uri::RedirectLoopError, 'too many HTTP redirects' if @limit == 0
32
+ end
33
+
34
+ def uri
35
+ uri = URI(@uri_str)
36
+ raise BadUriError, 'the url is incomplete' if uri.host == nil
37
+
38
+ uri
39
+ end
40
+
41
+ def request
42
+ Net::HTTP::Get.new(uri.request_uri, headers)
43
+ end
44
+
45
+ def response
46
+ http.request(request)
47
+ end
48
+
49
+ def http
50
+ Net::HTTP.new(uri.host, uri.port).tap do |http|
51
+ http.use_ssl = ssl?
52
+ end
53
+ end
54
+
55
+ def ssl?
56
+ uri.scheme == 'https'
57
+ end
58
+
59
+ def headers
60
+ {
61
+ 'User-Agent' => OpenGraphy.configuration.user_agent,
62
+ }
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,31 @@
1
+ module OpenGraphy
2
+ class MetaTag
3
+ def initialize(doc, meta_tag)
4
+ @doc, @meta_tag = doc, meta_tag
5
+ end
6
+
7
+ def namespace
8
+ @namespace ||= TagNamespace.new(tag_name.split(':'))
9
+ end
10
+
11
+ def valid?
12
+ tag_name
13
+ end
14
+
15
+ def name
16
+ @meta_tag.attr('property').sub(tag_name, '')
17
+ end
18
+
19
+ def value
20
+ @meta_tag.attr('content').to_s
21
+ end
22
+
23
+ private
24
+
25
+ def tag_name
26
+ OpenGraphy.configuration.metatags.find do |valid_meta_tag_name|
27
+ @meta_tag.attr('property') =~ Regexp.new(valid_meta_tag_name)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,88 @@
1
+ module OpenGraphy
2
+ class MetaTags
3
+ def title
4
+ data.fetch('title', __html_title_tag)
5
+ end
6
+
7
+ def title?
8
+ !!title
9
+ end
10
+
11
+ def image
12
+ if valid_image_url?
13
+ image_url
14
+ else
15
+ raise NoMethodError
16
+ end
17
+ end
18
+
19
+ def image?
20
+ valid_image_url?
21
+ end
22
+
23
+ def add(key, value, namespace: TagNamespace.new)
24
+ data[key] = value
25
+ namespace.add_to(key, value, self)
26
+ self
27
+ end
28
+
29
+ def define_namespace(name)
30
+ if respond_to?(name)
31
+ public_send(name)
32
+ else
33
+ MetaTags.new.tap { |tag|
34
+ define_singleton_method(name, -> { tag })
35
+ }
36
+ end
37
+ end
38
+
39
+ def define_value(key, value)
40
+ if define_accessors?(key)
41
+ define_singleton_method key, -> { value }
42
+ define_singleton_method "#{key}?", -> { !!value }
43
+ end
44
+ end
45
+
46
+ def method_missing(method_sym, *arguments, &block)
47
+ if method_sym.to_s.end_with?('?')
48
+ false
49
+ else
50
+ super
51
+ end
52
+ end
53
+
54
+ def respond_to?(method_name, include_private = false)
55
+ method_name.to_s.end_with?('?') || super
56
+ end
57
+
58
+ def respond_to_missing?(method_name, include_private = false)
59
+ method_name.to_s.end_with?('?') || super
60
+ end
61
+
62
+ private
63
+
64
+ def define_accessors?(key)
65
+ !black_list.include?(key)
66
+ end
67
+
68
+ def image_url
69
+ data.fetch('image', false)
70
+ end
71
+
72
+ def valid_image_url?
73
+ @valid_image_url ||= UrlValidator.new(image_url).valid?
74
+ end
75
+
76
+ def black_list
77
+ %w(image)
78
+ end
79
+
80
+ def data
81
+ @data ||= {}
82
+ end
83
+
84
+ def __html_title_tag
85
+ @data['__html_title_tag']
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,40 @@
1
+ module OpenGraphy
2
+ class TagNamespace
3
+ extend Forwardable
4
+ include Enumerable
5
+
6
+ def_delegators :namespace, :empty?, :length, :each, :last, :first, :any?, :size, :[]
7
+
8
+ def initialize(namespace=[])
9
+ @namespace = namespace
10
+ end
11
+
12
+ def any?
13
+ namespace.any? && first != 'og'
14
+ end
15
+
16
+ def add_to(key, value, tag)
17
+ if any?
18
+ tag.define_namespace(child_name).add(key, value, namespace: self.next)
19
+ else
20
+ tag.define_value(key, value)
21
+ end
22
+ end
23
+
24
+ def child_name
25
+ namespace.first
26
+ end
27
+
28
+ def next
29
+ TagNamespace.new(
30
+ [namespace.size > 1 ? namespace.last : nil].compact
31
+ )
32
+ end
33
+
34
+ private
35
+
36
+ def namespace
37
+ @namespace
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,18 @@
1
+ require 'net/http'
2
+
3
+ module OpenGraphy
4
+ module Uri
5
+ class RedirectLoopError < StandardError; end
6
+ class BadUriError < StandardError; end
7
+
8
+ def self.open(uri_str)
9
+ fetch(uri_str).body
10
+ end
11
+
12
+ private
13
+
14
+ def self.fetch(uri)
15
+ Fetcher.new(uri).fetch
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,40 @@
1
+ module OpenGraphy
2
+ class Url
3
+ def initialize(uri)
4
+ @uri = uri
5
+ end
6
+
7
+ def self.fetch(uri)
8
+ new(uri).fetch
9
+ end
10
+
11
+ def fetch
12
+ data.add('url', @uri)
13
+ begin
14
+ valid_meta_tags.each { |tag| data.add(tag.name, tag.value, namespace: tag.namespace) }
15
+ data.add('__html_title_tag', doc.css('title').text)
16
+ rescue SocketError, Net::HTTPServerException, Uri::RedirectLoopError, Uri::BadUriError
17
+ end
18
+
19
+ data
20
+ end
21
+
22
+ private
23
+
24
+ def valid_meta_tags
25
+ valid_meta_tags ||= meta_tags.select(&:valid?)
26
+ end
27
+
28
+ def meta_tags
29
+ doc.css('meta').map { |tag| MetaTag.new(doc, tag) }
30
+ end
31
+
32
+ def data
33
+ @data ||= MetaTags.new
34
+ end
35
+
36
+ def doc
37
+ @doc ||= Nokogiri::HTML(Uri.open(@uri))
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,11 @@
1
+ module OpenGraphy
2
+ class UrlValidator
3
+ def initialize(url)
4
+ @url = url
5
+ end
6
+
7
+ def valid?
8
+ !!(@url =~ /\A#{URI::regexp(['http', 'https'])}\z/)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module OpenGraphy
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,26 @@
1
+ require 'open_graphy/version'
2
+ require 'nokogiri'
3
+ require 'socket'
4
+ require 'singleton'
5
+ require 'open_graphy/configuration'
6
+ require 'open_graphy/url'
7
+ require 'open_graphy/uri'
8
+ require 'open_graphy/tag_namespace'
9
+ require 'open_graphy/meta_tags'
10
+ require 'open_graphy/meta_tag'
11
+ require 'open_graphy/fetcher'
12
+ require 'open_graphy/url_validator'
13
+
14
+ module OpenGraphy
15
+ def self.configuration
16
+ Configuration.instance
17
+ end
18
+
19
+ def self.configure
20
+ yield(configuration)
21
+ end
22
+
23
+ def self.fetch(uri)
24
+ Url.fetch(uri)
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'open_graphy/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "open_graphy"
8
+ spec.version = OpenGraphy::VERSION
9
+ spec.authors = ["Craig Bradley", "James Cotterill"]
10
+ spec.email = ["craig.bradley@onthebeach.co.uk", "james.cotterill@onthebeach.co.uk" ]
11
+ spec.summary = %q{Open Graph Protocol wrapper}
12
+ spec.description = %q{A simple ruby wrapper for the open graph protocol}
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.7"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency "nokogiri", "~> 1.6"
23
+ spec.add_development_dependency "rspec", "~> 3.1"
24
+ spec.add_development_dependency "vcr", '~> 2.9'
25
+ spec.add_development_dependency "webmock", "~> 1.20"
26
+ end
@@ -0,0 +1,117 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://google.com/404.html
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - "*/*"
14
+ User-Agent:
15
+ - OpenGraphyBot
16
+ response:
17
+ status:
18
+ code: 301
19
+ message: Moved Permanently
20
+ headers:
21
+ Location:
22
+ - http://www.google.com/404.html
23
+ Content-Type:
24
+ - text/html; charset=UTF-8
25
+ X-Content-Type-Options:
26
+ - nosniff
27
+ Date:
28
+ - Mon, 01 Dec 2014 20:45:42 GMT
29
+ Expires:
30
+ - Wed, 31 Dec 2014 20:45:42 GMT
31
+ Cache-Control:
32
+ - public, max-age=2592000
33
+ Server:
34
+ - sffe
35
+ Content-Length:
36
+ - '227'
37
+ X-Xss-Protection:
38
+ - 1; mode=block
39
+ Alternate-Protocol:
40
+ - 80:quic,p=0.02
41
+ body:
42
+ encoding: UTF-8
43
+ string: "<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n<TITLE>301
44
+ Moved</TITLE></HEAD><BODY>\n<H1>301 Moved</H1>\nThe document has moved\n<A
45
+ HREF=\"http://www.google.com/404.html\">here</A>.\r\n</BODY></HTML>\r\n"
46
+ http_version:
47
+ recorded_at: Mon, 01 Dec 2014 20:45:42 GMT
48
+ - request:
49
+ method: get
50
+ uri: http://www.google.com/404.html
51
+ body:
52
+ encoding: US-ASCII
53
+ string: ''
54
+ headers:
55
+ Accept-Encoding:
56
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
57
+ Accept:
58
+ - "*/*"
59
+ User-Agent:
60
+ - OpenGraphyBot
61
+ response:
62
+ status:
63
+ code: 404
64
+ message: Not Found
65
+ headers:
66
+ Content-Type:
67
+ - text/html; charset=UTF-8
68
+ X-Content-Type-Options:
69
+ - nosniff
70
+ Date:
71
+ - Mon, 01 Dec 2014 20:45:43 GMT
72
+ Server:
73
+ - sffe
74
+ Content-Length:
75
+ - '1433'
76
+ X-Xss-Protection:
77
+ - 1; mode=block
78
+ Alternate-Protocol:
79
+ - 80:quic,p=0.02
80
+ body:
81
+ encoding: ASCII-8BIT
82
+ string: !binary |-
83
+ PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CiAgPG1ldGEgY2hhcnNl
84
+ dD11dGYtOD4KICA8bWV0YSBuYW1lPXZpZXdwb3J0IGNvbnRlbnQ9ImluaXRp
85
+ YWwtc2NhbGU9MSwgbWluaW11bS1zY2FsZT0xLCB3aWR0aD1kZXZpY2Utd2lk
86
+ dGgiPgogIDx0aXRsZT5FcnJvciA0MDQgKE5vdCBGb3VuZCkhITE8L3RpdGxl
87
+ PgogIDxzdHlsZT4KICAgICp7bWFyZ2luOjA7cGFkZGluZzowfWh0bWwsY29k
88
+ ZXtmb250OjE1cHgvMjJweCBhcmlhbCxzYW5zLXNlcmlmfWh0bWx7YmFja2dy
89
+ b3VuZDojZmZmO2NvbG9yOiMyMjI7cGFkZGluZzoxNXB4fWJvZHl7bWFyZ2lu
90
+ OjclIGF1dG8gMDttYXgtd2lkdGg6MzkwcHg7bWluLWhlaWdodDoxODBweDtw
91
+ YWRkaW5nOjMwcHggMCAxNXB4fSogPiBib2R5e2JhY2tncm91bmQ6dXJsKC8v
92
+ d3d3Lmdvb2dsZS5jb20vaW1hZ2VzL2Vycm9ycy9yb2JvdC5wbmcpIDEwMCUg
93
+ NXB4IG5vLXJlcGVhdDtwYWRkaW5nLXJpZ2h0OjIwNXB4fXB7bWFyZ2luOjEx
94
+ cHggMCAyMnB4O292ZXJmbG93OmhpZGRlbn1pbnN7Y29sb3I6Izc3Nzt0ZXh0
95
+ LWRlY29yYXRpb246bm9uZX1hIGltZ3tib3JkZXI6MH1AbWVkaWEgc2NyZWVu
96
+ IGFuZCAobWF4LXdpZHRoOjc3MnB4KXtib2R5e2JhY2tncm91bmQ6bm9uZTtt
97
+ YXJnaW4tdG9wOjA7bWF4LXdpZHRoOm5vbmU7cGFkZGluZy1yaWdodDowfX0j
98
+ bG9nb3tiYWNrZ3JvdW5kOnVybCgvL3d3dy5nb29nbGUuY29tL2ltYWdlcy9l
99
+ cnJvcnMvbG9nb19zbV8yLnBuZykgbm8tcmVwZWF0fUBtZWRpYSBvbmx5IHNj
100
+ cmVlbiBhbmQgKG1pbi1yZXNvbHV0aW9uOjE5MmRwaSl7I2xvZ297YmFja2dy
101
+ b3VuZDp1cmwoLy93d3cuZ29vZ2xlLmNvbS9pbWFnZXMvZXJyb3JzL2xvZ29f
102
+ c21fMl9oci5wbmcpIG5vLXJlcGVhdCAwJSAwJS8xMDAlIDEwMCU7LW1vei1i
103
+ b3JkZXItaW1hZ2U6dXJsKC8vd3d3Lmdvb2dsZS5jb20vaW1hZ2VzL2Vycm9y
104
+ cy9sb2dvX3NtXzJfaHIucG5nKSAwfX1AbWVkaWEgb25seSBzY3JlZW4gYW5k
105
+ ICgtd2Via2l0LW1pbi1kZXZpY2UtcGl4ZWwtcmF0aW86Mil7I2xvZ297YmFj
106
+ a2dyb3VuZDp1cmwoLy93d3cuZ29vZ2xlLmNvbS9pbWFnZXMvZXJyb3JzL2xv
107
+ Z29fc21fMl9oci5wbmcpIG5vLXJlcGVhdDstd2Via2l0LWJhY2tncm91bmQt
108
+ c2l6ZToxMDAlIDEwMCV9fSNsb2dve2Rpc3BsYXk6aW5saW5lLWJsb2NrO2hl
109
+ aWdodDo1NXB4O3dpZHRoOjE1MHB4fQogIDwvc3R5bGU+CiAgPGEgaHJlZj0v
110
+ L3d3dy5nb29nbGUuY29tLz48c3BhbiBpZD1sb2dvIGFyaWEtbGFiZWw9R29v
111
+ Z2xlPjwvc3Bhbj48L2E+CiAgPHA+PGI+NDA0LjwvYj4gPGlucz5UaGF04oCZ
112
+ cyBhbiBlcnJvci48L2lucz4KICA8cD5UaGUgcmVxdWVzdGVkIFVSTCA8Y29k
113
+ ZT4vNDA0Lmh0bWw8L2NvZGU+IHdhcyBub3QgZm91bmQgb24gdGhpcyBzZXJ2
114
+ ZXIuICA8aW5zPlRoYXTigJlzIGFsbCB3ZSBrbm93LjwvaW5zPgo=
115
+ http_version:
116
+ recorded_at: Mon, 01 Dec 2014 20:45:43 GMT
117
+ recorded_with: VCR 2.9.3