indieweb-endpoints 0.6.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ab63e805300751b251c129c817104bbc47b4fb8d90d758b1310734a7f9591dcf
4
- data.tar.gz: 45431916ee155fc23df530dae6ebf51298675a6f065ab1163391a482612b9a40
3
+ metadata.gz: '08489907fd615d0e6eec6e6c80aee184713c5a65014c150255517413688693dd'
4
+ data.tar.gz: 0d426b9e30cc91dacec91f26fea509d0b761ac30b96c02336d28b99d0aad68d9
5
5
  SHA512:
6
- metadata.gz: 2fc61c949330b86b0b8eaf784de934be79ec1cd85b700fb6b1e44bb4e27f877fe2bea99be0c444ae4fd9fe5793cae7218d035f8e5a0ee3ffe5abacdee86f0393
7
- data.tar.gz: a0e56ed6e7be2bc619a2fb68d62e8898ebf62a45710b96bf78c1c32079d7ffe57c16c5066071b427c91418def99af5667f3ecd6327b5ff6712da60f945ab4531
6
+ metadata.gz: 468db55b447dddc64b56c60a013111d74f7d25c9f71ae3ca728484bc60a283652f87cefe92ec187125f57bce1a7512bcb02047c0e85bac671297bcfce95d5e0a
7
+ data.tar.gz: bd0d10b05873cefe89c64ae2144896c59c06556e58d8980da19dd1a85f5959a9c1601f2c15c2689faba6b86a115edfb4419d8ec2d9ce5ff4b1fac83e40f6a209
data/.reek.yml CHANGED
@@ -4,6 +4,8 @@ detectors:
4
4
  UtilityFunction:
5
5
  exclude:
6
6
  - FixtureHelpers#read_fixture
7
+ - IndieWeb::Endpoints::Services::ResponseBodyParserService#parse
8
+ - IndieWeb::Endpoints::Services::ResponseHeadersParserService#parse
7
9
 
8
10
  exclude_paths:
9
11
  - vendor/
@@ -2,17 +2,17 @@ require:
2
2
  - rubocop-performance
3
3
  - rubocop-rspec
4
4
 
5
- Layout/AlignHash:
5
+ Layout/HashAlignment:
6
6
  EnforcedHashRocketStyle: table
7
7
 
8
+ Layout/LineLength:
9
+ Enabled: false
10
+
8
11
  Metrics/BlockLength:
9
12
  Exclude:
10
13
  - indieweb-endpoints.gemspec
11
14
  - spec/**/*.rb
12
15
 
13
- Metrics/LineLength:
14
- Enabled: false
15
-
16
16
  Naming/RescuedExceptionsVariableName:
17
17
  PreferredName: exception
18
18
 
@@ -1 +1 @@
1
- 2.4.6
1
+ 2.4.9
@@ -1,16 +1,16 @@
1
+ dist: bionic
1
2
  language: ruby
2
3
  rvm:
3
- - 2.4.6
4
- - 2.5.5
5
- - 2.6.3
6
- cache:
7
- - bundler
8
- before_install:
9
- - gem update --system
10
- - gem install bundler
4
+ - 2.4
5
+ - 2.5
6
+ - 2.6
7
+ - 2.7
8
+ cache: bundler
11
9
  before_script:
12
10
  - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
13
11
  - chmod +x ./cc-test-reporter
14
12
  - ./cc-test-reporter before-build
15
13
  after_script:
16
14
  - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
15
+ notifications:
16
+ email: false
@@ -1,33 +1,54 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.1.0 / 2020-01-20
4
+
5
+ - Expand supported Ruby versions to include 2.7 (ae63ed0)
6
+
7
+ ## 1.0.2 / 2019-08-31
8
+
9
+ - Update WebMock and Addressable gems (298da63)
10
+ - Update development dependencies (5663e3a)
11
+
12
+ ## 1.0.1 / 2019-07-17
13
+
14
+ - Safely combine, flatten, and compact result set (5f2d9c5)
15
+
16
+ ## 1.0.0 / 2019-07-08
17
+
18
+ - Refactor gem code using service objects approach (78511d7 and 9d2fee0)
19
+
20
+ ## 0.7.0 / 2019-07-03
21
+
22
+ - Update runtime and development dependencies (d99214b and 7692ab3)
23
+
3
24
  ## 0.6.0 / 2019-06-15
4
25
 
5
- - Updates Parser-related classes to resolve [#2](https://github.com/indieweb/indieweb-endpoints-ruby/issues/2).
26
+ - Update Parser-related classes to resolve #2
6
27
 
7
28
  ## 0.5.0 / 2019-05-09
8
29
 
9
- - Add support for Microsub endpoint discovery ([5e81d9f](https://github.com/indieweb/indieweb-endpoints-ruby/commit/5e81d9f)).
10
- - Refactor parsers to ignore URLs with fragments ([797b376](https://github.com/indieweb/indieweb-endpoints-ruby/commit/797b376)).
11
- - Rescue `NoMethodError` (for `nil`) and `TypeError` (for non-`String`) ([e33522e](https://github.com/indieweb/indieweb-endpoints-ruby/commit/e33522e)).
12
- - Raise `ArgumentError` if url scheme is not `http` or `https` ([8eb1b1a](https://github.com/indieweb/indieweb-endpoints-ruby/commit/8eb1b1a)).
13
- - Shorten up User Agent string ([f9717b4](https://github.com/indieweb/indieweb-endpoints-ruby/commit/f9717b4)).
14
- - Refactor `HTTPRequest` class using specification defaults ([feef2ba](https://github.com/indieweb/indieweb-endpoints-ruby/commit/feef2ba)).
30
+ - Add support for Microsub endpoint discovery (5e81d9f)
31
+ - Refactor parsers to ignore URLs with fragments (797b376)
32
+ - Rescue `NoMethodError` (for `nil`) and `TypeError` (for non-`String`) (e33522e)
33
+ - Raise `ArgumentError` if url scheme is not `http` or `https` (8eb1b1a)
34
+ - Shorten up User Agent string (f9717b4)
35
+ - Refactor `HTTPRequest` class using specification defaults (feef2ba)
15
36
 
16
37
  ## 0.4.0 / 2019-05-01
17
38
 
18
- - Add `IndieWeb::Endpoints.client` method ([c4d42d0](https://github.com/indieweb/indieweb-endpoints-ruby/commit/c4d42d0)).
19
- - Rename base `Error` class to `IndieWebEndpointsError` ([d6d6f98](https://github.com/indieweb/indieweb-endpoints-ruby/commit/d6d6f98)).
20
- - Add `HttpRequest` class ([7864cbd](https://github.com/indieweb/indieweb-endpoints-ruby/commit/7864cbd)).
39
+ - Add `IndieWeb::Endpoints.client` method (c4d42d0)
40
+ - Rename base `Error` class to `IndieWebEndpointsError` (d6d6f98)
41
+ - Add `HttpRequest` class (7864cbd)
21
42
 
22
43
  ## 0.3.0 / 2019-04-30
23
44
 
24
- - `IndieWeb::Endpoints::Client#endpoints` returns an `OpenStruct` instead of a `Hash` ([c209b0b](https://github.com/indieweb/indieweb-endpoints-ruby/commit/c209b0b)).
45
+ - `IndieWeb::Endpoints::Client#endpoints` returns an `OpenStruct` instead of a `Hash` (c209b0b).
25
46
 
26
47
  ## 0.2.0 / 2019-04-25
27
48
 
28
- - Subclass exceptions under `IndieWeb::Endpoints::Error` ([667eec7](https://github.com/indieweb/indieweb-endpoints-ruby/commit/667eec7)).
29
- - Refactor parsers and `Registerable` module ([3b96858](https://github.com/indieweb/indieweb-endpoints-ruby/commit/3b96858)).
30
- - Refactor Client#response method ([c36fda3](https://github.com/indieweb/indieweb-endpoints-ruby/commit/c36fda3)).
49
+ - Subclass exceptions under `IndieWeb::Endpoints::Error` (667eec7)
50
+ - Refactor parsers and `Registerable` module (3b96858)
51
+ - Refactor `Client#response` method (c36fda3)
31
52
 
32
53
  ## 0.1.0 / 2019-04-24
33
54
 
@@ -8,9 +8,9 @@ There are a couple ways you can help improve indieweb-endpoints-ruby:
8
8
 
9
9
  ## Getting Started
10
10
 
11
- indieweb-endpoints-ruby is developed using Ruby 2.4.6 and is additionally tested against Ruby 2.5.5 and 2.6.3 using [Travis CI](https://travis-ci.com/indieweb/indieweb-endpoints-ruby).
11
+ indieweb-endpoints-ruby is developed using Ruby 2.4.9 and is additionally tested against Ruby 2.5, 2.6, and 2.7 using [Travis CI](https://travis-ci.com/indieweb/indieweb-endpoints-ruby).
12
12
 
13
- Before making changes to indieweb-endpoints-ruby, you'll want to install Ruby 2.4.6. It's recommended that you use a Ruby version managment tool like [rbenv](https://github.com/rbenv/rbenv), [chruby](https://github.com/postmodern/chruby), or [rvm](https://github.com/rvm/rvm). Once you've installed Ruby 2.4.6 using your method of choice, install the project's gems by running:
13
+ Before making changes to indieweb-endpoints-ruby, you'll want to install Ruby 2.4.9. It's recommended that you use a Ruby version managment tool like [rbenv](https://github.com/rbenv/rbenv), [chruby](https://github.com/postmodern/chruby), or [rvm](https://github.com/rvm/rvm). Once you've installed Ruby 2.4.9 using your method of choice, install the project's gems by running:
14
14
 
15
15
  ```sh
16
16
  bundle install
data/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
  Before installing and using indieweb-endpoints-ruby, you'll want to have [Ruby](https://www.ruby-lang.org) 2.4 (or newer) installed. It's recommended that you use a Ruby version managment tool like [rbenv](https://github.com/rbenv/rbenv), [chruby](https://github.com/postmodern/chruby), or [rvm](https://github.com/rvm/rvm).
20
20
 
21
- indieweb-endpoints-ruby is developed using Ruby 2.4.6 and is additionally tested against Ruby 2.5.5 and 2.6.3 using [Travis CI](https://travis-ci.com/indieweb/indieweb-endpoints-ruby).
21
+ indieweb-endpoints-ruby is developed using Ruby 2.4.9 and is additionally tested against Ruby 2.5, 2.6, and 2.7 using [Travis CI](https://travis-ci.com/indieweb/indieweb-endpoints-ruby).
22
22
 
23
23
  ## Installation
24
24
 
@@ -47,10 +47,10 @@ require 'indieweb/endpoints'
47
47
 
48
48
  endpoints = IndieWeb::Endpoints.get('https://aaronparecki.com')
49
49
 
50
- puts endpoints # => #<OpenStruct …>
50
+ puts endpoints # => #<OpenStruct authorization_endpoint="https://aaronparecki.com/auth", micropub="https://aaronparecki.com/micropub", microsub="https://aperture.p3k.io/microsub/1", redirect_uri=nil, token_endpoint="https://aaronparecki.com/auth/token", webmention="https://webmention.io/aaronpk/webmention">
51
51
  ```
52
52
 
53
- This example will search `https://aaronparecki.com` for valid IndieAuth, Micropub, and Webmention endpoints. In this case, the program returns an `OpenStruct` with the following attributes:
53
+ This example will search `https://aaronparecki.com` for valid IndieAuth, Micropub, and Webmention endpoints. In this case, the program returns an `OpenStruct` with the following attributes (represented below as a `Hash`):
54
54
 
55
55
  ```ruby
56
56
  {
@@ -72,11 +72,18 @@ Should the need arise, you may work with the `IndieWeb::Endpoints::Client` class
72
72
  ```ruby
73
73
  require 'indieweb/endpoints'
74
74
 
75
- client = IndieWeb::Endpoints.client('https://aaronparecki.com')
75
+ client = IndieWeb::Endpoints::Client.new('https://aaronparecki.com')
76
76
 
77
- puts client.response # => #<HTTP::Response …>
78
- puts client.endpoints # => #<OpenStruct …>
79
- puts client.endpoints.webmention # => 'https://webmention.io/aaronpk/webmention'
77
+ puts client.response # => #<HTTP::Response/1.1 200 OK {…}>
78
+
79
+ endpoints = client.endpoints
80
+
81
+ puts endpoints.authorization_endpoint # => 'https://aaronparecki.com/auth'
82
+ puts endpoints.micropub # => 'https://aaronparecki.com/micropub'
83
+ puts endpoints.microsub # => 'https://aperture.p3k.io/microsub/1'
84
+ puts endpoints.redirect_uri # => nil
85
+ puts endpoints.token_endpoint # => 'https://aaronparecki.com/auth/token'
86
+ puts endpoints.webmention # => 'https://webmention.io/aaronpk/webmention'
80
87
  ```
81
88
 
82
89
  ### Exception Handling
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'indieweb/endpoints/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.required_ruby_version = ['>= 2.4', '< 2.7']
7
+ spec.required_ruby_version = ['>= 2.4', '< 2.8']
8
8
 
9
9
  spec.name = 'indieweb-endpoints'
10
10
  spec.version = IndieWeb::Endpoints::VERSION
@@ -25,19 +25,19 @@ Gem::Specification.new do |spec|
25
25
  'changelog_uri' => "#{spec.homepage}/blob/v#{spec.version}/CHANGELOG.md"
26
26
  }
27
27
 
28
- spec.add_development_dependency 'rake', '~> 12.3'
29
- spec.add_development_dependency 'reek', '~> 5.4'
30
- spec.add_development_dependency 'rspec', '~> 3.8'
31
- spec.add_development_dependency 'rubocop', '~> 0.71.0'
32
- spec.add_development_dependency 'rubocop-performance', '~> 1.3'
33
- spec.add_development_dependency 'rubocop-rspec', '~> 1.33'
34
- spec.add_development_dependency 'simplecov', '~> 0.16.1'
35
- spec.add_development_dependency 'simplecov-console', '~> 0.5.0'
36
- spec.add_development_dependency 'webmock', '~> 3.6'
37
-
38
- spec.add_runtime_dependency 'absolutely', '~> 3.0'
39
- spec.add_runtime_dependency 'addressable', '~> 2.6'
28
+ spec.add_development_dependency 'rake', '~> 13.0'
29
+ spec.add_development_dependency 'reek', '~> 5.6'
30
+ spec.add_development_dependency 'rspec', '~> 3.9'
31
+ spec.add_development_dependency 'rubocop', '~> 0.79.0'
32
+ spec.add_development_dependency 'rubocop-performance', '~> 1.5'
33
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.37'
34
+ spec.add_development_dependency 'simplecov', '~> 0.17.1'
35
+ spec.add_development_dependency 'simplecov-console', '~> 0.6.0'
36
+ spec.add_development_dependency 'webmock', '~> 3.8'
37
+
38
+ spec.add_runtime_dependency 'absolutely', '~> 3.1'
39
+ spec.add_runtime_dependency 'addressable', '~> 2.7'
40
40
  spec.add_runtime_dependency 'http', '~> 5.0.0.pre'
41
- spec.add_runtime_dependency 'link-header-parser', '~> 0.1.0'
41
+ spec.add_runtime_dependency 'link-header-parser', '~> 0.3.0'
42
42
  spec.add_runtime_dependency 'nokogiri', '~> 1.10'
43
43
  end
@@ -9,11 +9,15 @@ require 'nokogiri'
9
9
  require 'indieweb/endpoints/version'
10
10
  require 'indieweb/endpoints/exceptions'
11
11
 
12
- require 'indieweb/endpoints/client'
13
- require 'indieweb/endpoints/http_request'
14
- require 'indieweb/endpoints/registerable'
12
+ require 'indieweb/endpoints/concerns/registerable'
13
+
14
+ require 'indieweb/endpoints/services/http_request_service'
15
+ require 'indieweb/endpoints/services/response_body_parser_service'
16
+ require 'indieweb/endpoints/services/response_headers_parser_service'
15
17
 
18
+ require 'indieweb/endpoints/client'
16
19
  require 'indieweb/endpoints/parsers'
20
+
17
21
  require 'indieweb/endpoints/parsers/authorization_endpoint_parser'
18
22
  require 'indieweb/endpoints/parsers/micropub_parser'
19
23
  require 'indieweb/endpoints/parsers/microsub_parser'
@@ -23,14 +27,8 @@ require 'indieweb/endpoints/parsers/webmention_parser'
23
27
 
24
28
  module IndieWeb
25
29
  module Endpoints
26
- class << self
27
- def client(url)
28
- Client.new(url)
29
- end
30
-
31
- def get(url)
32
- client(url).endpoints
33
- end
30
+ def self.get(url)
31
+ Client.new(url).endpoints
34
32
  end
35
33
  end
36
34
  end
@@ -16,8 +16,12 @@ module IndieWeb
16
16
  end
17
17
 
18
18
  def response
19
- @response ||= HttpRequest.get(@uri)
19
+ @response ||= Services::HttpRequestService.new.get(uri)
20
20
  end
21
+
22
+ private
23
+
24
+ attr_accessor :uri
21
25
  end
22
26
  end
23
27
  end
@@ -0,0 +1,15 @@
1
+ module IndieWeb
2
+ module Endpoints
3
+ module Concerns
4
+ module Registerable
5
+ def register(klass)
6
+ registered[klass.identifier] = klass
7
+ end
8
+
9
+ def registered
10
+ @registered ||= {}
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,11 +1,9 @@
1
1
  module IndieWeb
2
2
  module Endpoints
3
3
  module Parsers
4
- extend Registerable
4
+ extend Concerns::Registerable
5
5
 
6
6
  class BaseParser
7
- attr_reader :response
8
-
9
7
  def initialize(response)
10
8
  raise ArgumentError, "response must be an HTTP::Response (given #{response.class.name})" unless response.is_a?(HTTP::Response)
11
9
 
@@ -13,93 +11,29 @@ module IndieWeb
13
11
  end
14
12
 
15
13
  def results
16
- return unless results_from_http_request
14
+ mapped_results.shift
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :response
17
20
 
18
- @results ||= Absolutely.to_abs(base: response.uri.to_s, relative: results_from_http_request)
21
+ def mapped_results
22
+ @mapped_results ||= results_from_http_request.map { |endpoint| Absolutely.to_abs(base: response.uri.to_s, relative: endpoint) }.uniq.sort
19
23
  rescue Absolutely::InvalidURIError => exception
20
24
  raise InvalidURIError, exception
21
25
  end
22
26
 
23
- private
24
-
25
27
  def results_from_body
26
- BaseLinkElementParser.new(response, self.class.identifier).results
28
+ @results_from_body ||= Services::ResponseBodyParserService.new.parse(response, self.class.identifier)
27
29
  end
28
30
 
29
31
  def results_from_headers
30
- BaseLinkHeaderParser.new(response, self.class.identifier).results
32
+ @results_from_headers ||= Services::ResponseHeadersParserService.new.parse(response, self.class.identifier)
31
33
  end
32
34
 
33
35
  def results_from_http_request
34
- @results_from_http_request ||= results_from_headers || results_from_body || nil
35
- end
36
-
37
- class BaseLinkElementParser
38
- attr_reader :identifier, :response
39
-
40
- def initialize(response, identifier)
41
- @response = response
42
- @identifier = identifier
43
- end
44
-
45
- def results
46
- link_element['href'] if response_is_html && link_element
47
- end
48
-
49
- private
50
-
51
- def doc
52
- @doc ||= Nokogiri::HTML(response.body.to_s)
53
- end
54
-
55
- def link_element
56
- # Return first `link` element with valid `rel` attribute
57
- # https://www.w3.org/TR/indieauth/#discovery-1
58
- # https://www.w3.org/TR/micropub/#endpoint-discovery
59
- @link_element ||= link_elements.shift
60
- end
61
-
62
- def link_elements
63
- @link_elements ||= doc.css(link_elements_css_selector)
64
- end
65
-
66
- def link_elements_css_selector
67
- @link_elements_css_selector ||= %(link[rel~="#{identifier}"][href]:not([href*="#"]))
68
- end
69
-
70
- def response_is_html
71
- @response_is_html ||= response.mime_type == 'text/html'
72
- end
73
- end
74
-
75
- class BaseLinkHeaderParser
76
- attr_reader :identifier, :response
77
-
78
- def initialize(response, identifier)
79
- @response = response
80
- @identifier = identifier
81
- end
82
-
83
- def results
84
- return unless link_headers
85
-
86
- link_headers.shift.target_uri
87
- end
88
-
89
- private
90
-
91
- def link_headers
92
- @link_headers ||= begin
93
- return unless parsed_link_headers
94
-
95
- # Reject endpoints that contain a fragment identifier
96
- parsed_link_headers.reject { |parsed_link_header| Addressable::URI.parse(parsed_link_header.target_uri).fragment }
97
- end
98
- end
99
-
100
- def parsed_link_headers
101
- @parsed_link_headers ||= LinkHeaderParser.parse(response.headers.get('link'), base: response.uri.to_s).by_relation_type[identifier]
102
- end
36
+ @results_from_http_request ||= [results_from_headers, results_from_body].flatten.compact
103
37
  end
104
38
  end
105
39
  end
@@ -9,39 +9,9 @@ module IndieWeb
9
9
  Parsers.register(self)
10
10
 
11
11
  def results
12
- return unless results_from_http_request.any?
12
+ return unless mapped_results.any?
13
13
 
14
- @results ||= results_from_http_request.map { |endpoint| Absolutely.to_abs(base: response.uri.to_s, relative: endpoint) }.uniq.sort
15
- rescue Absolutely::InvalidURIError => exception
16
- raise InvalidURIError, exception
17
- end
18
-
19
- private
20
-
21
- def results_from_body
22
- RedirectUriLinkElementParser.new(response, self.class.identifier).results
23
- end
24
-
25
- def results_from_headers
26
- RedirectUriLinkHeaderParser.new(response, self.class.identifier).results
27
- end
28
-
29
- def results_from_http_request
30
- @results_from_http_request ||= [results_from_headers, results_from_body].flatten.compact
31
- end
32
-
33
- class RedirectUriLinkElementParser < BaseLinkElementParser
34
- def results
35
- link_elements.map { |element| element['href'] } if response_is_html && link_elements.any?
36
- end
37
- end
38
-
39
- class RedirectUriLinkHeaderParser < BaseLinkHeaderParser
40
- def results
41
- return unless link_headers
42
-
43
- link_headers.map(&:target_uri)
44
- end
14
+ mapped_results
45
15
  end
46
16
  end
47
17
  end
@@ -10,22 +10,13 @@ module IndieWeb
10
10
 
11
11
  private
12
12
 
13
- def results_from_body
14
- WebmentionLinkElementParser.new(response, self.class.identifier).results
13
+ def results_for_node(node)
14
+ Services::ResponseBodyParserService.new.parse(response, self.class.identifier, node)
15
15
  end
16
16
 
17
- class WebmentionLinkElementParser < BaseLinkElementParser
18
- private
19
-
20
- def link_element
21
- # Return first `a` or `link` element with valid `rel` attribute
22
- # https://www.w3.org/TR/webmention/#sender-discovers-receiver-webmention-endpoint
23
- @link_element ||= link_elements.find { |element| %w[a link].include?(element.name) }
24
- end
25
-
26
- def link_elements_css_selector
27
- @link_elements_css_selector ||= %([rel~="#{identifier}"][href]:not([href*="#"]))
28
- end
17
+ # https://www.w3.org/TR/webmention/#sender-discovers-receiver-webmention-endpoint
18
+ def results_from_body
19
+ @results_from_body ||= [results_for_node('link'), results_for_node('a')].flatten.compact
29
20
  end
30
21
  end
31
22
  end
@@ -0,0 +1,39 @@
1
+ module IndieWeb
2
+ module Endpoints
3
+ module Services
4
+ class HttpRequestService
5
+ # Defaults derived from Webmention specification examples
6
+ # https://www.w3.org/TR/webmention/#limits-on-get-requests
7
+ HTTP_CLIENT_OPTS = {
8
+ follow: {
9
+ max_hops: 20
10
+ },
11
+ headers: {
12
+ accept: '*/*',
13
+ user_agent: 'IndieWeb Endpoint Discovery (https://rubygems.org/gems/indieweb-endpoints)'
14
+ },
15
+ timeout_options: {
16
+ connect_timeout: 5,
17
+ read_timeout: 5
18
+ }
19
+ }.freeze
20
+
21
+ def initialize
22
+ @client = HTTP::Client.new(HTTP_CLIENT_OPTS)
23
+ end
24
+
25
+ def get(uri)
26
+ client.request(:get, uri)
27
+ rescue HTTP::ConnectionError,
28
+ HTTP::TimeoutError,
29
+ HTTP::Redirector::TooManyRedirectsError => exception
30
+ raise IndieWeb::Endpoints.const_get(exception.class.name.split('::').last), exception
31
+ end
32
+
33
+ private
34
+
35
+ attr_accessor :client
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,14 @@
1
+ module IndieWeb
2
+ module Endpoints
3
+ module Services
4
+ class ResponseBodyParserService
5
+ def parse(response, identifier, node = 'link')
6
+ return unless response.mime_type == 'text/html'
7
+
8
+ # Reject endpoints that contain a fragment identifier
9
+ Nokogiri::HTML(response.body.to_s).css(%(#{node}[rel~="#{identifier}"][href]:not([href*="#"]))).map { |element| element['href'] }
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ module IndieWeb
2
+ module Endpoints
3
+ module Services
4
+ class ResponseHeadersParserService
5
+ def parse(response, identifier)
6
+ headers = LinkHeaderParser.parse(response.headers.get('link'), base: response.uri.to_s).by_relation_type[identifier]
7
+
8
+ return unless headers
9
+
10
+ # Reject endpoints that contain a fragment identifier
11
+ headers.reject { |header| Addressable::URI.parse(header.target_uri).fragment }.map(&:target_uri)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,5 @@
1
1
  module IndieWeb
2
2
  module Endpoints
3
- VERSION = '0.6.0'.freeze
3
+ VERSION = '1.1.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: indieweb-endpoints
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Garber
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-15 00:00:00.000000000 Z
11
+ date: 2020-01-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -16,154 +16,154 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '12.3'
19
+ version: '13.0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '12.3'
26
+ version: '13.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: reek
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '5.4'
33
+ version: '5.6'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '5.4'
40
+ version: '5.6'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.8'
47
+ version: '3.9'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3.8'
54
+ version: '3.9'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rubocop
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.71.0
61
+ version: 0.79.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.71.0
68
+ version: 0.79.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rubocop-performance
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.3'
75
+ version: '1.5'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '1.3'
82
+ version: '1.5'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rubocop-rspec
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '1.33'
89
+ version: '1.37'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '1.33'
96
+ version: '1.37'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 0.16.1
103
+ version: 0.17.1
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 0.16.1
110
+ version: 0.17.1
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: simplecov-console
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 0.5.0
117
+ version: 0.6.0
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: 0.5.0
124
+ version: 0.6.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: webmock
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '3.6'
131
+ version: '3.8'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '3.6'
138
+ version: '3.8'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: absolutely
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '3.0'
145
+ version: '3.1'
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '3.0'
152
+ version: '3.1'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: addressable
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
157
  - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: '2.6'
159
+ version: '2.7'
160
160
  type: :runtime
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: '2.6'
166
+ version: '2.7'
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: http
169
169
  requirement: !ruby/object:Gem::Requirement
@@ -184,14 +184,14 @@ dependencies:
184
184
  requirements:
185
185
  - - "~>"
186
186
  - !ruby/object:Gem::Version
187
- version: 0.1.0
187
+ version: 0.3.0
188
188
  type: :runtime
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
192
  - - "~>"
193
193
  - !ruby/object:Gem::Version
194
- version: 0.1.0
194
+ version: 0.3.0
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: nokogiri
197
197
  requirement: !ruby/object:Gem::Requirement
@@ -233,8 +233,8 @@ files:
233
233
  - indieweb-endpoints.gemspec
234
234
  - lib/indieweb/endpoints.rb
235
235
  - lib/indieweb/endpoints/client.rb
236
+ - lib/indieweb/endpoints/concerns/registerable.rb
236
237
  - lib/indieweb/endpoints/exceptions.rb
237
- - lib/indieweb/endpoints/http_request.rb
238
238
  - lib/indieweb/endpoints/parsers.rb
239
239
  - lib/indieweb/endpoints/parsers/authorization_endpoint_parser.rb
240
240
  - lib/indieweb/endpoints/parsers/micropub_parser.rb
@@ -242,14 +242,16 @@ files:
242
242
  - lib/indieweb/endpoints/parsers/redirect_uri_parser.rb
243
243
  - lib/indieweb/endpoints/parsers/token_endpoint_parser.rb
244
244
  - lib/indieweb/endpoints/parsers/webmention_parser.rb
245
- - lib/indieweb/endpoints/registerable.rb
245
+ - lib/indieweb/endpoints/services/http_request_service.rb
246
+ - lib/indieweb/endpoints/services/response_body_parser_service.rb
247
+ - lib/indieweb/endpoints/services/response_headers_parser_service.rb
246
248
  - lib/indieweb/endpoints/version.rb
247
249
  homepage: https://github.com/indieweb/indieweb-endpoints-ruby
248
250
  licenses:
249
251
  - MIT
250
252
  metadata:
251
253
  bug_tracker_uri: https://github.com/indieweb/indieweb-endpoints-ruby/issues
252
- changelog_uri: https://github.com/indieweb/indieweb-endpoints-ruby/blob/v0.6.0/CHANGELOG.md
254
+ changelog_uri: https://github.com/indieweb/indieweb-endpoints-ruby/blob/v1.1.0/CHANGELOG.md
253
255
  post_install_message:
254
256
  rdoc_options: []
255
257
  require_paths:
@@ -261,14 +263,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
261
263
  version: '2.4'
262
264
  - - "<"
263
265
  - !ruby/object:Gem::Version
264
- version: '2.7'
266
+ version: '2.8'
265
267
  required_rubygems_version: !ruby/object:Gem::Requirement
266
268
  requirements:
267
269
  - - ">="
268
270
  - !ruby/object:Gem::Version
269
271
  version: '0'
270
272
  requirements: []
271
- rubygems_version: 3.0.3
273
+ rubygems_version: 3.0.6
272
274
  signing_key:
273
275
  specification_version: 4
274
276
  summary: Discover a URL’s IndieAuth, Micropub, Microsub, and Webmention endpoints.
@@ -1,29 +0,0 @@
1
- module IndieWeb
2
- module Endpoints
3
- class HttpRequest
4
- # Defaults derived from Webmention specification examples
5
- # https://www.w3.org/TR/webmention/#limits-on-get-requests
6
- HTTP_CLIENT_OPTS = {
7
- follow: {
8
- max_hops: 20
9
- },
10
- headers: {
11
- accept: '*/*',
12
- user_agent: 'IndieWeb Endpoint Discovery (https://rubygems.org/gems/indieweb-endpoints)'
13
- },
14
- timeout_options: {
15
- connect_timeout: 5,
16
- read_timeout: 5
17
- }
18
- }.freeze
19
-
20
- def self.get(uri)
21
- HTTP::Client.new(HTTP_CLIENT_OPTS).request(:get, uri)
22
- rescue HTTP::ConnectionError,
23
- HTTP::TimeoutError,
24
- HTTP::Redirector::TooManyRedirectsError => exception
25
- raise IndieWeb::Endpoints.const_get(exception.class.name.split('::').last), exception
26
- end
27
- end
28
- end
29
- end
@@ -1,13 +0,0 @@
1
- module IndieWeb
2
- module Endpoints
3
- module Registerable
4
- def register(klass)
5
- registered[klass.identifier] = klass
6
- end
7
-
8
- def registered
9
- @registered ||= {}
10
- end
11
- end
12
- end
13
- end