oembed 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Alex Soulim
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,86 @@
1
+ # Introductions
2
+
3
+ [**oEmbed**](http://oembed.com/) is a format for allowing an embedded representation of a URL on third
4
+ party sites. The simple API allows a website to display embedded content
5
+ (such as photos or videos) when a user posts a link to that resource, without
6
+ having to parse the resource directly.
7
+
8
+ **oembed gem** is a simple to use and slim (~150 LOC) library to work with oEmbed format. It has no external dependencies at runtime. All you need to have is Ruby itself.
9
+
10
+ The library shares a behaviour of oEmbed client with any Ruby object. Just `include Oembed::Client` into that object and you are good to go.
11
+
12
+ **oembed gem** is provider agnostic. It has no pre-configured providers.
13
+ You can build a client for any oEmbed provider of the world :)
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ gem 'oembed'
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install oembed
28
+
29
+ ## Usage
30
+
31
+ You have to do a few things to build an oEmbed client with `oembed` gem.
32
+
33
+ - `include Oembed::Client` into your object,
34
+ - add instance method `#endpoint_uri` to that object. This method has to return
35
+ a string with URI of oEmbed endpoint.
36
+
37
+ Lets start with a simple example. It will be a client for the awesome
38
+ [Speaker Deck](http://speakerdeck.com).
39
+
40
+ ```ruby
41
+ require 'oembed'
42
+
43
+ # Speaker Deck client
44
+ class SpeakerDeck
45
+ include Oembed::Client
46
+
47
+ # Read more about endpoint on https://speakerdeck.com/faq#oembed
48
+ def endpoint_uri
49
+ 'http://speakerdeck.com/oembed.json'
50
+ end
51
+ end
52
+ ```
53
+
54
+ That's it. Now you can use a method `#fetch` to get data from oEmbed enpoint of Speaker Deck.
55
+
56
+ ```ruby
57
+ client = SpeakerDeck.new
58
+ p client.fetch('https://speakerdeck.com/u/soulim/p/rails')
59
+ ```
60
+
61
+ The method `#fetch` will return a hash with oEmded data.
62
+
63
+ ```json
64
+ {
65
+ "type" => "rich",
66
+ "version" => 1.0,
67
+ "provider_name" => "Speaker Deck",
68
+ "provider_url" => "https://speakerdeck.com/",
69
+ "title" => "Локализация приложения на базе Rails. Личный опыт и советы",
70
+ "author_name" => "Alex Soulim",
71
+ "author_url" => "https://speakerdeck.com/u/soulim",
72
+ "html" => "<iframe style=\"border:0; padding:0; margin:0; background:transparent;\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\" frameBorder=\"0\" allowTransparency=\"true\" id=\"presentation_frame_4fd3874cebb4b2001f0277e5\" src=\"//speakerdeck.com/embed/4fd3874cebb4b2001f0277e5\" width=\"710\" height=\"596\"></iframe>\n",
73
+ "width" => 710,
74
+ "height" => 596
75
+ }
76
+ ```
77
+
78
+ At the moment `oembed` gem supports the JSON format only. I will fix it soon. Stay tuned! :)
79
+
80
+ ## Contributing
81
+
82
+ 1. Fork it
83
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
84
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
85
+ 4. Push to the branch (`git push origin my-new-feature`)
86
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/lib/oembed.rb ADDED
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+ require 'net/http'
3
+ require 'json'
4
+ require 'uri'
5
+
6
+ module Oembed
7
+ class Error < StandardError; end
8
+
9
+ class ResponseError < Error
10
+ attr_reader :response
11
+
12
+ def initialize(response)
13
+ @response = response
14
+ end
15
+ end
16
+
17
+ class RedirectionTooDeepError < Error; end
18
+
19
+ class ParserError < Error
20
+ attr_reader :original
21
+
22
+ def initialize(original)
23
+ @original = original
24
+ end
25
+ end
26
+
27
+ class NotSupportedFormatError < Error; end
28
+
29
+ autoload :Client, 'oembed/client'
30
+ autoload :Parser, 'oembed/parser'
31
+ autoload :Http, 'oembed/http'
32
+ autoload :Uri, 'oembed/uri'
33
+ end
34
+
35
+ require 'oembed/version'
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ module Oembed
4
+ module Client
5
+ attr_writer :http
6
+
7
+ def endpoint_uri
8
+ raise NotImplementedError
9
+ end
10
+
11
+ def http
12
+ @http ||= Oembed::Http.new
13
+ end
14
+
15
+ def fetch(resource_uri)
16
+ begin
17
+ fetch!(resource_uri)
18
+ rescue Oembed::Error
19
+ nil
20
+ end
21
+ end
22
+
23
+ def fetch!(resource_uri)
24
+ uri = Oembed::Uri.new(endpoint_uri, resource_uri)
25
+ http.get(uri.to_s)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+
3
+ module Oembed
4
+ class Http
5
+ attr_writer :parser
6
+
7
+ def parser
8
+ @parser ||= Oembed::Parser.new
9
+ end
10
+
11
+ def get(path, options = {})
12
+ uri = URI.parse(path)
13
+ connection = establish_connection(uri.host, uri.port)
14
+ response = connection.get(uri.request_uri)
15
+
16
+ case response
17
+ when Net::HTTPRedirection
18
+ follow_redirection(response['location'], options.fetch(:limit, 10))
19
+ when Net::HTTPSuccess
20
+ parser.parse(response.body, response.content_type)
21
+ else
22
+ raise Oembed::ResponseError.new(response), 'HTTP error during request'
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def establish_connection(host, port)
29
+ Net::HTTP.new(host, port).tap do |instance|
30
+ instance.use_ssl = port == URI::HTTPS::DEFAULT_PORT
31
+ end
32
+ end
33
+
34
+ def follow_redirection(location, limit)
35
+ if limit > 0
36
+ get(location, limit - 1)
37
+ else
38
+ raise Oembed::RedirectionTooDeepError, 'HTTP redirects too deep'
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ module Oembed
4
+ class Parser
5
+ SUPPORTED_FORMATS = {
6
+ 'text/xml' => :xml,
7
+ 'application/json' => :json,
8
+ }
9
+
10
+ def parse(body, content_type)
11
+ format = SUPPORTED_FORMATS[content_type]
12
+
13
+ if format
14
+ send(format, body)
15
+ else
16
+ raise Oembed::NotSupportedFormatError,
17
+ "parser does not support #{format.inspect} format"
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def json(body)
24
+ begin
25
+ JSON.parse(body)
26
+ rescue JSON::JSONError => e
27
+ raise Oembed::ParserError.new(e), 'JSON parser error'
28
+ end
29
+ end
30
+
31
+ def xml(body)
32
+ raise NotImplementedError, 'XML parser is not implemented'
33
+ end
34
+ end
35
+ end
data/lib/oembed/uri.rb ADDED
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ module Oembed
4
+ class Uri
5
+ def initialize(endpoint_uri, resource_uri)
6
+ @uri = URI.parse(endpoint_uri)
7
+ @uri.query = URI.encode_www_form(url: resource_uri)
8
+ end
9
+
10
+ def to_s
11
+ @uri.to_s
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module Oembed
2
+ VERSION = "0.0.1"
3
+ end
data/oembed.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+ require File.expand_path('../lib/oembed/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Alex Soulim"]
6
+ gem.email = ["soulim@gmail.com"]
7
+ gem.description = %q{A slim library to work with oEmbed format.}
8
+ gem.summary = %q{A slim library to work with oEmbed format.}
9
+ gem.homepage = "http://github.com/soulim/oembed"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "oembed"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Oembed::VERSION
17
+
18
+ gem.add_development_dependency 'rspec', '~> 2.11.0'
19
+ gem.add_development_dependency 'simplecov', '~> 0.6.4'
20
+ gem.add_development_dependency 'fakeweb', '~> 1.3.0'
21
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Oembed::Client do
4
+ let(:http) { double('Http', get: 'foo') }
5
+ let(:endpoint_uri) { 'http://example.com/oembed' }
6
+ let(:resource_uri) { 'http://example.com/foo' }
7
+
8
+ subject do
9
+ double('OembedClient',
10
+ http: http,
11
+ endpoint_uri: endpoint_uri
12
+ ).extend(Oembed::Client)
13
+ end
14
+
15
+ describe '#fetch' do
16
+ it 'should fetch the date using self.fetch!' do
17
+ subject.should_receive(:fetch!)
18
+ subject.fetch(resource_uri)
19
+ end
20
+
21
+ context 'when there is an error during request' do
22
+ before { http.stub(:get).and_raise(Oembed::Error) }
23
+
24
+ it 'should return nil' do
25
+ expect(subject.fetch(resource_uri)).to be_nil
26
+ end
27
+ end
28
+ end
29
+
30
+ describe '#fetch!' do
31
+ it 'should prepare request URI' do
32
+ Oembed::Uri.should_receive(:new).with(endpoint_uri, resource_uri)
33
+ subject.fetch!(resource_uri)
34
+ end
35
+
36
+ it 'should get oEmbed data via HTTP client' do
37
+ http.should_receive(:get)
38
+ subject.fetch!(resource_uri)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+ require 'fakeweb'
3
+
4
+ describe Oembed::Http do
5
+ let(:parser) { double('Parser', parse: 'foo') }
6
+ let(:uri) { 'http://example.com/foo' }
7
+
8
+ subject { Oembed::Http.new.tap { |http| http.parser = parser } }
9
+
10
+ before { FakeWeb.allow_net_connect = false }
11
+
12
+ describe '#get' do
13
+ context 'when response is successful' do
14
+ before do
15
+ FakeWeb.register_uri(:get, uri, body: 'OK', status: [200, 'OK'])
16
+ end
17
+
18
+ it 'should parse response body' do
19
+ parser.should_receive(:parse)
20
+ subject.get(uri)
21
+ end
22
+
23
+ it 'should return parsing result' do
24
+ expect(subject.get(uri)).to eq(parser.parse)
25
+ end
26
+ end
27
+
28
+ context 'when amount of redirects is above the limit' do
29
+ before do
30
+ FakeWeb.register_uri(:get, uri, body: 'Redirect', status: [301, 'Moved Permanently'])
31
+ end
32
+
33
+ it 'should raise TooManyRedirects exception' do
34
+ expect {
35
+ subject.get(uri, limit: 0)
36
+ }.to raise_error(Oembed::RedirectionTooDeepError)
37
+ end
38
+ end
39
+
40
+ context 'when response is HTTP error' do
41
+ before do
42
+ FakeWeb.register_uri(:get, uri, body: 'Internal Server Error', status: [500, 'Internal Server Error'])
43
+ end
44
+
45
+ it 'should raise HttpError exception' do
46
+ expect { subject.get(uri) }.to raise_error(Oembed::ResponseError)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Oembed::Parser do
4
+ let(:body) { { 'foo' => 'bar', 'baz' => 1 } }
5
+ let(:json_body) { '{"foo":"bar","baz":1}' }
6
+ let(:xml_body) { 'xml-body' }
7
+
8
+ describe '#parse' do
9
+ context 'when content type is JSON' do
10
+ it 'should return parsed body' do
11
+ expect(subject.parse(json_body, 'application/json')).to eq(body)
12
+ end
13
+ end
14
+
15
+ context 'when content type is XML' do
16
+ it 'should raise NotImplementedError' do
17
+ expect {
18
+ subject.parse(xml_body, 'text/xml')
19
+ }.to raise_error(NotImplementedError)
20
+ end
21
+ end
22
+
23
+ context 'when content type is not supported' do
24
+ it 'should raise Oembed::NotSupportedFormatError' do
25
+ expect {
26
+ subject.parse(json_body, 'wrong/type')
27
+ }.to raise_error(Oembed::NotSupportedFormatError)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Oembed::Uri do
4
+ let(:endpoint_uri) { 'http://example.com/oembed' }
5
+ let(:resource_uri) { 'http://example.com/foo' }
6
+
7
+ subject { Oembed::Uri.new(endpoint_uri, resource_uri) }
8
+
9
+ describe '#to_s' do
10
+ it 'should return oEmbed URI string' do
11
+ expect(subject.to_s).to eq('http://example.com/oembed?url=http%3A%2F%2Fexample.com%2Ffoo')
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+ require 'oembed'
3
+
4
+ describe Oembed do
5
+ end
@@ -0,0 +1,19 @@
1
+ require 'simplecov'
2
+
3
+ SimpleCov.start
4
+ RSpec.configure do |config|
5
+ config.treat_symbols_as_metadata_keys_with_true_values = true
6
+ # config.run_all_when_everything_filtered = true
7
+ # config.filter_run :focus
8
+
9
+ # Run specs in random order to surface order dependencies. If you find an
10
+ # order dependency and want to debug it, you can fix the order by providing
11
+ # the seed, which is printed after each run.
12
+ # --seed 1234
13
+ config.order = 'random'
14
+
15
+ # Disable should syntax
16
+ config.expect_with(:rspec) { |c| c.syntax = :expect }
17
+ end
18
+
19
+ require 'oembed'
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oembed
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Alex Soulim
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.11.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 2.11.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: simplecov
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.6.4
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.6.4
46
+ - !ruby/object:Gem::Dependency
47
+ name: fakeweb
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 1.3.0
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 1.3.0
62
+ description: A slim library to work with oEmbed format.
63
+ email:
64
+ - soulim@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - .rspec
71
+ - Gemfile
72
+ - LICENSE
73
+ - README.md
74
+ - Rakefile
75
+ - lib/oembed.rb
76
+ - lib/oembed/client.rb
77
+ - lib/oembed/http.rb
78
+ - lib/oembed/parser.rb
79
+ - lib/oembed/uri.rb
80
+ - lib/oembed/version.rb
81
+ - oembed.gemspec
82
+ - spec/oembed/client_spec.rb
83
+ - spec/oembed/http_spec.rb
84
+ - spec/oembed/parser_spec.rb
85
+ - spec/oembed/uri_spec.rb
86
+ - spec/oembed_spec.rb
87
+ - spec/spec_helper.rb
88
+ homepage: http://github.com/soulim/oembed
89
+ licenses: []
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 1.8.24
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: A slim library to work with oEmbed format.
112
+ test_files:
113
+ - spec/oembed/client_spec.rb
114
+ - spec/oembed/http_spec.rb
115
+ - spec/oembed/parser_spec.rb
116
+ - spec/oembed/uri_spec.rb
117
+ - spec/oembed_spec.rb
118
+ - spec/spec_helper.rb