indieweb-endpoints 6.0.0 → 7.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: d751a18dc854951b0c3b71429959f2fdd0690ee9ba51a1b5cf6b6cc5dcec5143
4
- data.tar.gz: 5b3dd9ab89de1bf668471c58d4bf8097633125e37b9ccf80d0c94554ae3dbe38
3
+ metadata.gz: d00bf075ce905d49768b047c4963ccc8fb260e3ce7c06a1305a10099bdf6e4a0
4
+ data.tar.gz: 2c50a4fe3f85d401ccf981e5ef4c374e35f2788a2a00422f52df08c7a7c9821f
5
5
  SHA512:
6
- metadata.gz: 8b2dc2195a547c955545ff89d540e40dde34de784490271c6726afd49249f4ebd66bafcdd43bcc3dff30ca9444f306aa4264da7849b19f9401575dbe3dcd49f4
7
- data.tar.gz: 356ab5dbb4ea2b233ab490323bd80da4e61568654a0c1c209fd6e7932fe7af5ba15792ee209f79ab650f54478e18a9d67357b8204c7dc40a4d2cddf2d04dba8f
6
+ metadata.gz: ed757712cf9c99812ebdf2eb514c37b4a78cf0fd9f86c416611ce64a854706eb0e7b08599be0681438a774b76dbc9e03b2bb8434107fd17dec37403686743182
7
+ data.tar.gz: cadd7fad871a5d33f88e9365f7b8b1300c331cd96f2716d17f24ae8eac9eec79c463f4e45c68cb18fa35d602393fd771d3face3723c0acc1e3ab46acba02f7c7
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 7.1.0 / 2022-03-08
4
+
5
+ - Refactor gem code (eba8115)
6
+ - Refactor specs (5b92119)
7
+ - Rescue from `OpenSSL::SSL::SSLError` (4ea38e5)
8
+
9
+ ## 7.0.0 / 2022-01-06
10
+
11
+ - Update runtime dependency versions (5c9430f)
12
+ - **Breaking change:** Update development Ruby version to 2.6.9 and minimum Ruby version to 2.6 (ed17ab1 and 7e4a621)
13
+ - Migrate to GitHub Actions from Travis CI (c019756)
14
+ - Add `rubygems_mfa_required` to gemspec metadata (1f0a40f)
15
+
16
+ ## 6.1.0 / 2021-05-25
17
+
18
+ - Add support for Ruby 3.0 (3394252)
19
+
3
20
  ## 6.0.0 / 2021-05-25
4
21
 
5
22
  - Refactor parsers (e22e0af)
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.5.9 and is additionally tested against Ruby 2.6 and 2.7 using [Travis CI](https://travis-ci.com/indieweb/indieweb-endpoints-ruby).
11
+ indieweb-endpoints-ruby is developed using Ruby 2.6.9 and is additionally tested against Ruby 2.7, 3.0, and 3.1 using [GitHub Actions](https://github.com/indieweb/indieweb-endpoints-ruby/actions).
12
12
 
13
- Before making changes to indieweb-endpoints-ruby, you'll want to install Ruby 2.5.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.5.9 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.6.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.6.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
@@ -4,7 +4,7 @@
4
4
 
5
5
  [![Gem](https://img.shields.io/gem/v/indieweb-endpoints.svg?logo=rubygems&style=for-the-badge)](https://rubygems.org/gems/indieweb-endpoints)
6
6
  [![Downloads](https://img.shields.io/gem/dt/indieweb-endpoints.svg?logo=rubygems&style=for-the-badge)](https://rubygems.org/gems/indieweb-endpoints)
7
- [![Build](https://img.shields.io/travis/com/indieweb/indieweb-endpoints-ruby/main.svg?logo=travis&style=for-the-badge)](https://travis-ci.com/indieweb/indieweb-endpoints-ruby)
7
+ [![Build](https://img.shields.io/github/workflow/status/indieweb/indieweb-endpoints-ruby/CI?logo=github&style=for-the-badge)](https://github.com/indieweb/indieweb-endpoints-ruby/actions/workflows/ci.yml)
8
8
  [![Maintainability](https://img.shields.io/codeclimate/maintainability/indieweb/indieweb-endpoints-ruby.svg?logo=code-climate&style=for-the-badge)](https://codeclimate.com/github/indieweb/indieweb-endpoints-ruby)
9
9
  [![Coverage](https://img.shields.io/codeclimate/c/indieweb/indieweb-endpoints-ruby.svg?logo=code-climate&style=for-the-badge)](https://codeclimate.com/github/indieweb/indieweb-endpoints-ruby/code)
10
10
 
@@ -12,13 +12,13 @@
12
12
 
13
13
  - Compliant with [Section 4.1](https://www.w3.org/TR/indieauth/#discovery-by-clients) and [Section 4.2.2](https://www.w3.org/TR/indieauth/#redirect-url) of [the W3C's IndieAuth Working Group Note](https://www.w3.org/TR/indieauth/), [Section 5.3](https://www.w3.org/TR/micropub/#endpoint-discovery) of [the W3C's Micropub Recommendation](https://www.w3.org/TR/micropub/), and [Section 3.1.2](https://www.w3.org/TR/webmention/#sender-discovers-receiver-webmention-endpoint) of [the W3C's Webmention Recommendation](https://www.w3.org/TR/webmention/).
14
14
  - Passes all Endpoint Discovery tests on [webmention.rocks](https://webmention.rocks).
15
- - Supports Ruby 2.5 and newer.
15
+ - Supports Ruby 2.6 and newer.
16
16
 
17
17
  ## Getting Started
18
18
 
19
- Before installing and using indieweb-endpoints-ruby, you'll want to have [Ruby](https://www.ruby-lang.org) 2.5 (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).
19
+ Before installing and using indieweb-endpoints-ruby, you'll want to have [Ruby](https://www.ruby-lang.org) 2.6 (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.5.9 and is additionally tested against Ruby 2.6, 2.7, and 3.0 using [Travis CI](https://travis-ci.com/indieweb/indieweb-endpoints-ruby).
21
+ indieweb-endpoints-ruby is developed using Ruby 2.6.9 and is additionally tested against Ruby 2.7, 3.0, and 3.1 using [GitHub Actions](https://github.com/indieweb/indieweb-endpoints-ruby/actions).
22
22
 
23
23
  ## Installation
24
24
 
@@ -59,7 +59,7 @@ Should the need arise, you may work with the `IndieWeb::Endpoints::Client` class
59
59
  require 'indieweb/endpoints'
60
60
 
61
61
  client = IndieWeb::Endpoints::Client.new('https://aaronparecki.com')
62
- #=> #<IndieWeb::Endpoints::Client url: "https://aaronparecki.com">
62
+ #=> #<IndieWeb::Endpoints::Client uri: "https://aaronparecki.com">
63
63
 
64
64
  client.response
65
65
  #=> #<HTTP::Response/1.1 200 OK {…}>
@@ -80,6 +80,10 @@ From [httprb/http](https://github.com/httprb/http):
80
80
 
81
81
  - `IndieWeb::Endpoints::HttpError`
82
82
 
83
+ From the Ruby Standard Library's [`OpenSSL::SSL::SSLError`](https://ruby-doc.org/stdlib-2.6.9/libdoc/openssl/rdoc/OpenSSL/SSL/SSLError.html):
84
+
85
+ - `IndieWeb::Endpoints::SSLError`
86
+
83
87
  ## Contributing
84
88
 
85
89
  Interested in helping improve indieweb-endpoints-ruby? Awesome! Your help is greatly appreciated. See [CONTRIBUTING.md](https://github.com/indieweb/indieweb-endpoints-ruby/blob/main/CONTRIBUTING.md) for details.
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'lib/indieweb/endpoints/version'
2
4
 
3
5
  Gem::Specification.new do |spec|
4
- spec.required_ruby_version = Gem::Requirement.new('>= 2.5', '< 2.8')
6
+ spec.required_ruby_version = '>= 2.6', '< 4'
5
7
 
6
8
  spec.name = 'indieweb-endpoints'
7
9
  spec.version = IndieWeb::Endpoints::VERSION
@@ -19,11 +21,13 @@ Gem::Specification.new do |spec|
19
21
 
20
22
  spec.require_paths = ['lib']
21
23
 
22
- spec.metadata['bug_tracker_uri'] = "#{spec.homepage}/issues"
23
- spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/v#{spec.version}/CHANGELOG.md"
24
+ spec.metadata = {
25
+ 'bug_tracker_uri' => "#{spec.homepage}/issues",
26
+ 'changelog_uri' => "#{spec.homepage}/blob/v#{spec.version}/CHANGELOG.md",
27
+ 'rubygems_mfa_required' => 'true'
28
+ }
24
29
 
25
- spec.add_runtime_dependency 'addressable', '~> 2.7'
26
30
  spec.add_runtime_dependency 'http', '~> 5.0'
27
- spec.add_runtime_dependency 'link-header-parser', '~> 3.0'
28
- spec.add_runtime_dependency 'nokogiri', '~> 1.11'
31
+ spec.add_runtime_dependency 'link-header-parser', '~> 4.0'
32
+ spec.add_runtime_dependency 'nokogiri', '~> 1.13'
29
33
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module IndieWeb
2
4
  module Endpoints
3
5
  class Client
@@ -10,39 +12,45 @@ module IndieWeb
10
12
  #
11
13
  # client = IndieWeb::Endpoints::Client.new('https://aaronparecki.com')
12
14
  #
13
- # @param url [String] an absolute URL
15
+ # @param url [String, HTTP::URI, #to_s] an absolute URL
16
+ # @raise [IndieWeb::Endpoints::InvalidURIError]
14
17
  def initialize(url)
15
- @url = url.to_str
18
+ @uri = HTTP::URI.parse(url.to_s)
19
+ rescue Addressable::URI::InvalidURIError => e
20
+ raise InvalidURIError, e
16
21
  end
17
22
 
18
23
  # @return [String]
19
24
  def inspect
20
- format(%(#<#{self.class.name}:%#0x url: #{url.inspect}>), object_id)
25
+ %(#<#{self.class.name}:#{format('%#0x', object_id)} uri: "#{uri}">)
21
26
  end
22
27
 
28
+ # A Hash of the discovered IndieWeb endpoints from the provided URL
29
+ #
23
30
  # @return [Hash{Symbol => String, Array, nil}]
24
31
  def endpoints
25
- @endpoints ||= Parsers.registered.transform_values { |parser| parser.new(response).results }
32
+ @endpoints ||= Parser.new(response).results
26
33
  end
27
34
 
28
- # @see https://www.w3.org/TR/webmention/#limits-on-get-requests
35
+ # The HTTP::Response object returned by the provided URL
29
36
  #
30
37
  # @return [HTTP::Response]
38
+ # @raise [IndieWeb::Endpoints::HttpError]
31
39
  def response
32
- @response ||= HTTP.follow(max_hops: 20).headers(HTTP_HEADERS_OPTS).timeout(connect: 5, read: 5).get(uri)
33
- rescue HTTP::Error => exception
34
- raise HttpError, exception
40
+ @response ||= HTTP.follow(max_hops: 20)
41
+ .headers(HTTP_HEADERS_OPTS)
42
+ .timeout(connect: 5, read: 5)
43
+ .get(uri)
44
+ rescue HTTP::Error => e
45
+ raise HttpError, e
46
+ rescue OpenSSL::SSL::SSLError => e
47
+ raise SSLError, e
35
48
  end
36
49
 
37
50
  private
38
51
 
39
- attr_accessor :url
40
-
41
- def uri
42
- @uri ||= Addressable::URI.parse(url)
43
- rescue Addressable::URI::InvalidURIError => exception
44
- raise InvalidURIError, exception
45
- end
52
+ # @return [HTTP::URI]
53
+ attr_reader :uri
46
54
  end
47
55
  end
48
56
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IndieWeb
4
+ module Endpoints
5
+ # @api private
6
+ class Parser
7
+ # @param response [HTTP::Response]
8
+ def initialize(response)
9
+ @response = response
10
+ end
11
+
12
+ # @return [Hash{Symbol => String, Array<String>, nil}]
13
+ def results
14
+ {
15
+ authorization_endpoint: result_for(:authorization_endpoint),
16
+ micropub: result_for(:micropub),
17
+ microsub: result_for(:microsub),
18
+ redirect_uri: results_for(:redirect_uri),
19
+ token_endpoint: result_for(:token_endpoint),
20
+ webmention: result_for(:webmention, %w[link a])
21
+ }
22
+ end
23
+
24
+ private
25
+
26
+ # @return [HTTP::Response]
27
+ attr_reader :response
28
+
29
+ # @return [IndieWeb::Endpoints::ResponseBodyParser]
30
+ def response_body_parser
31
+ @response_body_parser ||= ResponseBodyParser.new(response)
32
+ end
33
+
34
+ # @return [IndieWeb::Endpoints::ResponseHeadersParser]
35
+ def response_headers_parser
36
+ @response_headers_parser ||= ResponseHeadersParser.new(response)
37
+ end
38
+
39
+ # @param identifier [Symbol]
40
+ # @param nodes [Array<String>]
41
+ # @return [String, nil]
42
+ def result_for(identifier, nodes = ['link'])
43
+ results_for(identifier, nodes)&.first
44
+ end
45
+
46
+ # @param identifier [Symbol]
47
+ # @param nodes [Array<String>]
48
+ # @return [Array<String>, nil]
49
+ # @raise [IndieWeb::Endpoints::InvalidURIError]
50
+ def results_for(identifier, nodes = ['link'])
51
+ results_from_request = [
52
+ response_headers_parser.results_for(identifier),
53
+ response_body_parser.results_for(identifier, nodes)
54
+ ].flatten.compact
55
+
56
+ return if results_from_request.none?
57
+
58
+ results_from_request.map { |endpoint| response.uri.join(endpoint).to_s }.uniq.sort
59
+ rescue Addressable::URI::InvalidURIError => e
60
+ raise InvalidURIError, e
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IndieWeb
4
+ module Endpoints
5
+ # @api private
6
+ class ResponseBodyParser
7
+ # @param response [HTTP::Response]
8
+ def initialize(response)
9
+ @body = response.body.to_s
10
+ @mime_type = response.mime_type
11
+ @uri = response.uri
12
+ end
13
+
14
+ # @param identifier [Symbol]
15
+ # @param nodes [Array<String>]
16
+ # @return [Array<string>, nil]
17
+ def results_for(identifier, nodes = ['link'])
18
+ return unless mime_type == 'text/html'
19
+
20
+ # Reject endpoints that contain a fragment identifier
21
+ selectors = nodes.map { |node| %(#{node}[rel~="#{identifier}"][href]:not([href*="#"])) }.join(',')
22
+
23
+ parsed_body.css(selectors).map { |element| element['href'] }
24
+ end
25
+
26
+ private
27
+
28
+ # @return [String]
29
+ attr_reader :body
30
+
31
+ # @return [String]
32
+ attr_reader :mime_type
33
+
34
+ # @return [HTTP::URI]
35
+ attr_reader :uri
36
+
37
+ # @return [Nokogiri::HTML5::Document]
38
+ def parsed_body
39
+ @parsed_body ||= Nokogiri::HTML5(body)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IndieWeb
4
+ module Endpoints
5
+ # @api private
6
+ class ResponseHeadersParser
7
+ # @param response [HTTP::Response]
8
+ def initialize(response)
9
+ @headers = response.headers.get('link')
10
+ @uri = response.uri
11
+ end
12
+
13
+ # @param headers [Symbol]
14
+ # @return [Array<String>, nil]
15
+ def results_for(identifier)
16
+ return unless parsed_headers.key?(identifier)
17
+
18
+ # Reject endpoints that contain a fragment identifier
19
+ parsed_headers[identifier].reject { |header| HTTP::URI.parse(header.target_uri).fragment }.map(&:target_uri)
20
+ end
21
+
22
+ private
23
+
24
+ # @return [Array<String>]
25
+ attr_reader :headers
26
+
27
+ # @return [HTTP::URI]
28
+ attr_reader :uri
29
+
30
+ # @return [Hash{Symbol => Array<LinkHeaderParser::LinkHeader>}]
31
+ def parsed_headers
32
+ @parsed_headers ||= LinkHeaderParser.parse(headers, base: uri).group_by_relation_type
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module IndieWeb
2
4
  module Endpoints
3
- VERSION = '6.0.0'.freeze
5
+ VERSION = '7.1.0'
4
6
  end
5
7
  end
@@ -1,26 +1,23 @@
1
- require 'addressable/uri'
1
+ # frozen_string_literal: true
2
+
2
3
  require 'http'
3
4
  require 'link-header-parser'
4
5
  require 'nokogiri'
5
6
 
6
- require 'indieweb/endpoints/version'
7
- require 'indieweb/endpoints/exceptions'
8
-
9
- require 'indieweb/endpoints/services/response_parser_service'
7
+ require_relative 'endpoints/version'
10
8
 
11
- require 'indieweb/endpoints/client'
12
- require 'indieweb/endpoints/parsers'
13
-
14
- require 'indieweb/endpoints/parsers/base_parser'
15
- require 'indieweb/endpoints/parsers/authorization_endpoint_parser'
16
- require 'indieweb/endpoints/parsers/micropub_parser'
17
- require 'indieweb/endpoints/parsers/microsub_parser'
18
- require 'indieweb/endpoints/parsers/redirect_uri_parser'
19
- require 'indieweb/endpoints/parsers/token_endpoint_parser'
20
- require 'indieweb/endpoints/parsers/webmention_parser'
9
+ require_relative 'endpoints/client'
10
+ require_relative 'endpoints/parser'
11
+ require_relative 'endpoints/response_body_parser'
12
+ require_relative 'endpoints/response_headers_parser'
21
13
 
22
14
  module IndieWeb
23
15
  module Endpoints
16
+ class Error < StandardError; end
17
+ class HttpError < Error; end
18
+ class InvalidURIError < Error; end
19
+ class SSLError < Error; end
20
+
24
21
  # Discover a URL's IndieAuth, Micropub, Microsub, and Webmention endpoints
25
22
  #
26
23
  # IndieWeb::Endpoints.get('https://aaronparecki.com')
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: indieweb-endpoints
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.0
4
+ version: 7.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Garber
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-26 00:00:00.000000000 Z
11
+ date: 2022-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: addressable
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '2.7'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '2.7'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: http
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -44,28 +30,28 @@ dependencies:
44
30
  requirements:
45
31
  - - "~>"
46
32
  - !ruby/object:Gem::Version
47
- version: '3.0'
33
+ version: '4.0'
48
34
  type: :runtime
49
35
  prerelease: false
50
36
  version_requirements: !ruby/object:Gem::Requirement
51
37
  requirements:
52
38
  - - "~>"
53
39
  - !ruby/object:Gem::Version
54
- version: '3.0'
40
+ version: '4.0'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: nokogiri
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
45
  - - "~>"
60
46
  - !ruby/object:Gem::Version
61
- version: '1.11'
47
+ version: '1.13'
62
48
  type: :runtime
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
52
  - - "~>"
67
53
  - !ruby/object:Gem::Version
68
- version: '1.11'
54
+ version: '1.13'
69
55
  description: Discover a URL’s IndieAuth, Micropub, Microsub, and Webmention endpoints.
70
56
  email:
71
57
  - jason@sixtwothree.org
@@ -81,24 +67,18 @@ files:
81
67
  - indieweb-endpoints.gemspec
82
68
  - lib/indieweb/endpoints.rb
83
69
  - lib/indieweb/endpoints/client.rb
84
- - lib/indieweb/endpoints/exceptions.rb
85
- - lib/indieweb/endpoints/parsers.rb
86
- - lib/indieweb/endpoints/parsers/authorization_endpoint_parser.rb
87
- - lib/indieweb/endpoints/parsers/base_parser.rb
88
- - lib/indieweb/endpoints/parsers/micropub_parser.rb
89
- - lib/indieweb/endpoints/parsers/microsub_parser.rb
90
- - lib/indieweb/endpoints/parsers/redirect_uri_parser.rb
91
- - lib/indieweb/endpoints/parsers/token_endpoint_parser.rb
92
- - lib/indieweb/endpoints/parsers/webmention_parser.rb
93
- - lib/indieweb/endpoints/services/response_parser_service.rb
70
+ - lib/indieweb/endpoints/parser.rb
71
+ - lib/indieweb/endpoints/response_body_parser.rb
72
+ - lib/indieweb/endpoints/response_headers_parser.rb
94
73
  - lib/indieweb/endpoints/version.rb
95
74
  homepage: https://github.com/indieweb/indieweb-endpoints-ruby
96
75
  licenses:
97
76
  - MIT
98
77
  metadata:
99
78
  bug_tracker_uri: https://github.com/indieweb/indieweb-endpoints-ruby/issues
100
- changelog_uri: https://github.com/indieweb/indieweb-endpoints-ruby/blob/v6.0.0/CHANGELOG.md
101
- post_install_message:
79
+ changelog_uri: https://github.com/indieweb/indieweb-endpoints-ruby/blob/v7.1.0/CHANGELOG.md
80
+ rubygems_mfa_required: 'true'
81
+ post_install_message:
102
82
  rdoc_options: []
103
83
  require_paths:
104
84
  - lib
@@ -106,18 +86,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
106
86
  requirements:
107
87
  - - ">="
108
88
  - !ruby/object:Gem::Version
109
- version: '2.5'
89
+ version: '2.6'
110
90
  - - "<"
111
91
  - !ruby/object:Gem::Version
112
- version: '2.8'
92
+ version: '4'
113
93
  required_rubygems_version: !ruby/object:Gem::Requirement
114
94
  requirements:
115
95
  - - ">="
116
96
  - !ruby/object:Gem::Version
117
97
  version: '0'
118
98
  requirements: []
119
- rubygems_version: 3.2.16
120
- signing_key:
99
+ rubygems_version: 3.2.33
100
+ signing_key:
121
101
  specification_version: 4
122
102
  summary: Discover a URL’s IndieAuth, Micropub, Microsub, and Webmention endpoints.
123
103
  test_files: []
@@ -1,11 +0,0 @@
1
- module IndieWeb
2
- module Endpoints
3
- class Error < StandardError; end
4
-
5
- class ArgumentError < Error; end
6
-
7
- class HttpError < Error; end
8
-
9
- class InvalidURIError < Error; end
10
- end
11
- end
@@ -1,11 +0,0 @@
1
- module IndieWeb
2
- module Endpoints
3
- module Parsers
4
- class AuthorizationEndpointParser < BaseParser
5
- @identifier = :authorization_endpoint
6
-
7
- Parsers.register(self)
8
- end
9
- end
10
- end
11
- end
@@ -1,57 +0,0 @@
1
- module IndieWeb
2
- module Endpoints
3
- module Parsers
4
- class BaseParser
5
- class << self
6
- attr_reader :identifier
7
- end
8
-
9
- # @param response [HTTP::Response]
10
- def initialize(response)
11
- raise ArgumentError, "response must be an HTTP::Response (given #{response.class.name})" unless response.is_a?(HTTP::Response)
12
-
13
- @response = response
14
- end
15
-
16
- # @return [String]
17
- def results
18
- mapped_results.shift
19
- end
20
-
21
- private
22
-
23
- attr_reader :response
24
-
25
- def mapped_results
26
- @mapped_results ||= results_from_http_request.map { |endpoint| Addressable::URI.join(response.uri, endpoint).to_s }.uniq.sort
27
- rescue Addressable::URI::InvalidURIError => exception
28
- raise InvalidURIError, exception
29
- end
30
-
31
- def parsed_response_body
32
- @parsed_response_body ||= Nokogiri::HTML(response.body.to_s)
33
- end
34
-
35
- def parsed_response_headers
36
- @parsed_response_headers ||= LinkHeaderParser.parse(response.headers.get('link'), base: response.uri)
37
- end
38
-
39
- def results_from_body
40
- return if response.mime_type != 'text/html'
41
-
42
- Services::ResponseParserService.parse_body(parsed_response_body, self.class.identifier)
43
- end
44
-
45
- def results_from_headers
46
- return if parsed_response_headers.none?
47
-
48
- Services::ResponseParserService.parse_headers(parsed_response_headers.group_by_relation_type, self.class.identifier)
49
- end
50
-
51
- def results_from_http_request
52
- @results_from_http_request ||= [results_from_headers, results_from_body].flatten.compact
53
- end
54
- end
55
- end
56
- end
57
- end
@@ -1,11 +0,0 @@
1
- module IndieWeb
2
- module Endpoints
3
- module Parsers
4
- class MicropubParser < BaseParser
5
- @identifier = :micropub
6
-
7
- Parsers.register(self)
8
- end
9
- end
10
- end
11
- end
@@ -1,11 +0,0 @@
1
- module IndieWeb
2
- module Endpoints
3
- module Parsers
4
- class MicrosubParser < BaseParser
5
- @identifier = :microsub
6
-
7
- Parsers.register(self)
8
- end
9
- end
10
- end
11
- end
@@ -1,18 +0,0 @@
1
- module IndieWeb
2
- module Endpoints
3
- module Parsers
4
- class RedirectUriParser < BaseParser
5
- @identifier = :redirect_uri
6
-
7
- Parsers.register(self)
8
-
9
- # @return [Array<String>, nil]
10
- def results
11
- return if mapped_results.none?
12
-
13
- mapped_results
14
- end
15
- end
16
- end
17
- end
18
- end
@@ -1,11 +0,0 @@
1
- module IndieWeb
2
- module Endpoints
3
- module Parsers
4
- class TokenEndpointParser < BaseParser
5
- @identifier = :token_endpoint
6
-
7
- Parsers.register(self)
8
- end
9
- end
10
- end
11
- end
@@ -1,22 +0,0 @@
1
- module IndieWeb
2
- module Endpoints
3
- module Parsers
4
- class WebmentionParser < BaseParser
5
- @identifier = :webmention
6
-
7
- Parsers.register(self)
8
-
9
- private
10
-
11
- def results_for_node(node)
12
- Services::ResponseParserService.parse_body(parsed_response_body, self.class.identifier, node)
13
- end
14
-
15
- # https://www.w3.org/TR/webmention/#sender-discovers-receiver-webmention-endpoint
16
- def results_from_body
17
- @results_from_body ||= [results_for_node('link'), results_for_node('a')].flatten.compact
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,13 +0,0 @@
1
- module IndieWeb
2
- module Endpoints
3
- module Parsers
4
- def self.register(klass)
5
- registered[klass.identifier] = klass
6
- end
7
-
8
- def self.registered
9
- @registered ||= {}
10
- end
11
- end
12
- end
13
- end
@@ -1,25 +0,0 @@
1
- module IndieWeb
2
- module Endpoints
3
- module Services
4
- class ResponseParserService
5
- # @param body [Nokogiri::HTML::Document]
6
- # @param identifier [Symbol]
7
- # @return [Array<String>]
8
- def self.parse_body(body, identifier, node = 'link')
9
- # Reject endpoints that contain a fragment identifier
10
- body.css(%(#{node}[rel~="#{identifier}"][href]:not([href*="#"]))).map { |element| element['href'] }
11
- end
12
-
13
- # @param headers [Hash{Symbol => Array<LinkHeaderParser::LinkHeader}]
14
- # @param identifier [Symbol]
15
- # @return [Array<String>, nil]
16
- def self.parse_headers(headers, identifier)
17
- return unless headers.key?(identifier)
18
-
19
- # Reject endpoints that contain a fragment identifier
20
- headers[identifier].reject { |header| Addressable::URI.parse(header.target_uri).fragment }.map(&:target_uri)
21
- end
22
- end
23
- end
24
- end
25
- end