indieweb-endpoints 0.6.0 → 1.1.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 +4 -4
- data/.reek.yml +2 -0
- data/.rubocop.yml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +8 -8
- data/CHANGELOG.md +35 -14
- data/CONTRIBUTING.md +2 -2
- data/README.md +14 -7
- data/indieweb-endpoints.gemspec +14 -14
- data/lib/indieweb/endpoints.rb +9 -11
- data/lib/indieweb/endpoints/client.rb +5 -1
- data/lib/indieweb/endpoints/concerns/registerable.rb +15 -0
- data/lib/indieweb/endpoints/parsers.rb +12 -78
- data/lib/indieweb/endpoints/parsers/redirect_uri_parser.rb +2 -32
- data/lib/indieweb/endpoints/parsers/webmention_parser.rb +5 -14
- data/lib/indieweb/endpoints/services/http_request_service.rb +39 -0
- data/lib/indieweb/endpoints/services/response_body_parser_service.rb +14 -0
- data/lib/indieweb/endpoints/services/response_headers_parser_service.rb +16 -0
- data/lib/indieweb/endpoints/version.rb +1 -1
- metadata +33 -31
- data/lib/indieweb/endpoints/http_request.rb +0 -29
- data/lib/indieweb/endpoints/registerable.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '08489907fd615d0e6eec6e6c80aee184713c5a65014c150255517413688693dd'
|
4
|
+
data.tar.gz: 0d426b9e30cc91dacec91f26fea509d0b761ac30b96c02336d28b99d0aad68d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 468db55b447dddc64b56c60a013111d74f7d25c9f71ae3ca728484bc60a283652f87cefe92ec187125f57bce1a7512bcb02047c0e85bac671297bcfce95d5e0a
|
7
|
+
data.tar.gz: bd0d10b05873cefe89c64ae2144896c59c06556e58d8980da19dd1a85f5959a9c1601f2c15c2689faba6b86a115edfb4419d8ec2d9ce5ff4b1fac83e40f6a209
|
data/.reek.yml
CHANGED
data/.rubocop.yml
CHANGED
@@ -2,17 +2,17 @@ require:
|
|
2
2
|
- rubocop-performance
|
3
3
|
- rubocop-rspec
|
4
4
|
|
5
|
-
Layout/
|
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
|
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.4.
|
1
|
+
2.4.9
|
data/.travis.yml
CHANGED
@@ -1,16 +1,16 @@
|
|
1
|
+
dist: bionic
|
1
2
|
language: ruby
|
2
3
|
rvm:
|
3
|
-
- 2.4
|
4
|
-
- 2.5
|
5
|
-
- 2.6
|
6
|
-
|
7
|
-
|
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
|
data/CHANGELOG.md
CHANGED
@@ -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
|
-
-
|
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 (
|
10
|
-
- Refactor parsers to ignore URLs with fragments (
|
11
|
-
- Rescue `NoMethodError` (for `nil`) and `TypeError` (for non-`String`) (
|
12
|
-
- Raise `ArgumentError` if url scheme is not `http` or `https` (
|
13
|
-
- Shorten up User Agent string (
|
14
|
-
- Refactor `HTTPRequest` class using specification defaults (
|
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 (
|
19
|
-
- Rename base `Error` class to `IndieWebEndpointsError` (
|
20
|
-
- Add `HttpRequest` class (
|
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` (
|
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` (
|
29
|
-
- Refactor parsers and `Registerable` module (
|
30
|
-
- Refactor Client#response method (
|
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
|
|
data/CONTRIBUTING.md
CHANGED
@@ -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.
|
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.
|
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.
|
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.
|
75
|
+
client = IndieWeb::Endpoints::Client.new('https://aaronparecki.com')
|
76
76
|
|
77
|
-
puts client.response
|
78
|
-
|
79
|
-
|
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
|
data/indieweb-endpoints.gemspec
CHANGED
@@ -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
|
+
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', '~>
|
29
|
-
spec.add_development_dependency 'reek', '~> 5.
|
30
|
-
spec.add_development_dependency 'rspec', '~> 3.
|
31
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
32
|
-
spec.add_development_dependency 'rubocop-performance', '~> 1.
|
33
|
-
spec.add_development_dependency 'rubocop-rspec', '~> 1.
|
34
|
-
spec.add_development_dependency 'simplecov', '~> 0.
|
35
|
-
spec.add_development_dependency 'simplecov-console', '~> 0.
|
36
|
-
spec.add_development_dependency 'webmock', '~> 3.
|
37
|
-
|
38
|
-
spec.add_runtime_dependency 'absolutely', '~> 3.
|
39
|
-
spec.add_runtime_dependency 'addressable', '~> 2.
|
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.
|
41
|
+
spec.add_runtime_dependency 'link-header-parser', '~> 0.3.0'
|
42
42
|
spec.add_runtime_dependency 'nokogiri', '~> 1.10'
|
43
43
|
end
|
data/lib/indieweb/endpoints.rb
CHANGED
@@ -9,11 +9,15 @@ require 'nokogiri'
|
|
9
9
|
require 'indieweb/endpoints/version'
|
10
10
|
require 'indieweb/endpoints/exceptions'
|
11
11
|
|
12
|
-
require 'indieweb/endpoints/
|
13
|
-
|
14
|
-
require 'indieweb/endpoints/
|
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
|
-
|
27
|
-
|
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
|
@@ -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
|
-
|
14
|
+
mapped_results.shift
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :response
|
17
20
|
|
18
|
-
|
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
|
-
|
28
|
+
@results_from_body ||= Services::ResponseBodyParserService.new.parse(response, self.class.identifier)
|
27
29
|
end
|
28
30
|
|
29
31
|
def results_from_headers
|
30
|
-
|
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
|
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
|
12
|
+
return unless mapped_results.any?
|
13
13
|
|
14
|
-
|
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
|
14
|
-
|
13
|
+
def results_for_node(node)
|
14
|
+
Services::ResponseBodyParserService.new.parse(response, self.class.identifier, node)
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
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
|
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:
|
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:
|
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: '
|
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: '
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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/
|
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/
|
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.
|
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.
|
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
|