indieweb-endpoints 3.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +0 -1
- data/CHANGELOG.md +9 -0
- data/CONTRIBUTING.md +2 -2
- data/Gemfile +4 -3
- data/README.md +11 -29
- data/indieweb-endpoints.gemspec +2 -2
- data/lib/indieweb/endpoints.rb +7 -5
- data/lib/indieweb/endpoints/client.rb +36 -9
- data/lib/indieweb/endpoints/parsers/base_parser.rb +4 -2
- data/lib/indieweb/endpoints/parsers/redirect_uri_parser.rb +1 -0
- data/lib/indieweb/endpoints/parsers/webmention_parser.rb +1 -1
- data/lib/indieweb/endpoints/services/response_parser_service.rb +29 -0
- data/lib/indieweb/endpoints/version.rb +1 -1
- metadata +8 -10
- data/lib/indieweb/endpoints/services/http_request_service.rb +0 -22
- data/lib/indieweb/endpoints/services/response_body_parser_service.rb +0 -14
- data/lib/indieweb/endpoints/services/response_headers_parser_service.rb +0 -16
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 0c45996ba696d87124c8c764fce951197377fccfa3bf84d30ed702b3a27df610
         | 
| 4 | 
            +
              data.tar.gz: 562c474fa0079dfc5d6cbd8286e1a8c5cb169d1f54ede4404bfab2cec854a0bf
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 4417010c2a25d2bb07f8e59f63cd3aa31149aaa5dda33391fba11b7ef1d90d1acb2cd8e642dcf38086a6016027159914941d8dd69fb7f9beae7fe30b6b1cc2db
         | 
| 7 | 
            +
              data.tar.gz: 43da9e43bb391e7e2ecf999d1bb21dd3776c005037a746230d65066c67dad68883f1397fa2e46c812daec21bd80df006e24620a4608e06774787d08705b81981
         | 
    
        data/.ruby-version
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            2. | 
| 1 | 
            +
            2.5.8
         | 
    
        data/.travis.yml
    CHANGED
    
    
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,5 +1,14 @@ | |
| 1 1 | 
             
            # Changelog
         | 
| 2 2 |  | 
| 3 | 
            +
            ## 4.0.0 / 2020-07-21
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            - **Breaking change:** Return a Hash of endpoints instead of an OpenStruct (15dc387)
         | 
| 6 | 
            +
            - Update [link-header-parser](https://rubygems.org/gems/link-header-parser) dependency to v2.0.0 (2255e6b)
         | 
| 7 | 
            +
            - **Breaking change:** Update development Ruby version to 2.5.8 and minimum Ruby version to 2.5 (dd5a142)
         | 
| 8 | 
            +
            - Refactor response headers/body parsers into a single class (ee02da3)
         | 
| 9 | 
            +
            - Refactor `IndieWeb::Endpoints::Client` and remove `HttpRequestService` (2732616)
         | 
| 10 | 
            +
            - Add offending url to exception message (#5) (4bf7a54)
         | 
| 11 | 
            +
             | 
| 3 12 | 
             
            ## 3.0.0 / 2020-05-14
         | 
| 4 13 |  | 
| 5 14 | 
             
            - Update Absolutely and LinkHeaderParser dependencies (9e0a64a)
         | 
    
        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. | 
| 11 | 
            +
            indieweb-endpoints-ruby is developed using Ruby 2.5.8 and is additionally tested against Ruby 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. | 
| 13 | 
            +
            Before making changes to indieweb-endpoints-ruby, you'll want to install Ruby 2.5.8. 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.8 using your method of choice, install the project's gems by running:
         | 
| 14 14 |  | 
| 15 15 | 
             
            ```sh
         | 
| 16 16 | 
             
            bundle install
         | 
    
        data/Gemfile
    CHANGED
    
    | @@ -3,12 +3,13 @@ source 'https://rubygems.org' | |
| 3 3 | 
             
            # Specify your gem's dependencies in indieweb-endpoints.gemspec
         | 
| 4 4 | 
             
            gemspec
         | 
| 5 5 |  | 
| 6 | 
            +
            gem 'pry-byebug', '~> 3.9'
         | 
| 6 7 | 
             
            gem 'rake', '~> 13.0'
         | 
| 7 8 | 
             
            gem 'reek', '~> 6.0'
         | 
| 8 9 | 
             
            gem 'rspec', '~> 3.9'
         | 
| 9 | 
            -
            gem 'rubocop', '~> 0. | 
| 10 | 
            -
            gem 'rubocop-performance', '~> 1. | 
| 11 | 
            -
            gem 'rubocop-rspec', '~> 1. | 
| 10 | 
            +
            gem 'rubocop', '~> 0.88.0'
         | 
| 11 | 
            +
            gem 'rubocop-performance', '~> 1.7'
         | 
| 12 | 
            +
            gem 'rubocop-rspec', '~> 1.42'
         | 
| 12 13 | 
             
            gem 'simplecov', '~> 0.18.5'
         | 
| 13 14 | 
             
            gem 'simplecov-console', '~> 0.7.2'
         | 
| 14 15 | 
             
            gem 'webmock', '~> 3.8'
         | 
    
        data/README.md
    CHANGED
    
    | @@ -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. | 
| 15 | 
            +
            - Supports Ruby 2.5 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. | 
| 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).
         | 
| 20 20 |  | 
| 21 | 
            -
            indieweb-endpoints-ruby is developed using Ruby 2. | 
| 21 | 
            +
            indieweb-endpoints-ruby is developed using Ruby 2.5.8 and is additionally tested against Ruby 2.6 and 2.7 using [Travis CI](https://travis-ci.com/indieweb/indieweb-endpoints-ruby).
         | 
| 22 22 |  | 
| 23 23 | 
             
            ## Installation
         | 
| 24 24 |  | 
| @@ -45,25 +45,11 @@ With indieweb-endpoints-ruby added to your project's `Gemfile` and installed, yo | |
| 45 45 | 
             
            ```ruby
         | 
| 46 46 | 
             
            require 'indieweb/endpoints'
         | 
| 47 47 |  | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 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 | 
            -
            ```
         | 
| 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 (represented below as a `Hash`):
         | 
| 54 | 
            -
             | 
| 55 | 
            -
            ```ruby
         | 
| 56 | 
            -
            {
         | 
| 57 | 
            -
              authorization_endpoint: 'https://aaronparecki.com/auth',
         | 
| 58 | 
            -
              micropub: 'https://aaronparecki.com/micropub',
         | 
| 59 | 
            -
              microsub: 'https://aperture.p3k.io/microsub/1',
         | 
| 60 | 
            -
              redirect_uri: nil,
         | 
| 61 | 
            -
              token_endpoint: 'https://aaronparecki.com/auth/token',
         | 
| 62 | 
            -
              webmention: 'https://webmention.io/aaronpk/webmention'
         | 
| 63 | 
            -
            }
         | 
| 48 | 
            +
            IndieWeb::Endpoints.get('https://aaronparecki.com')
         | 
| 49 | 
            +
            #=> { 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" }
         | 
| 64 50 | 
             
            ```
         | 
| 65 51 |  | 
| 66 | 
            -
             | 
| 52 | 
            +
            This example will search `https://aaronparecki.com` for valid IndieAuth, Micropub, and Webmention endpoints and return a `Hash` of results. Each key in the returned `Hash` will have a value of either a `String` representing a URL or `nil`. The `redirect_uri` key's value will be either an `Array` or `nil` since a given URL may register multiple callback URLs.
         | 
| 67 53 |  | 
| 68 54 | 
             
            ### Advanced Usage
         | 
| 69 55 |  | 
| @@ -73,17 +59,13 @@ Should the need arise, you may work with the `IndieWeb::Endpoints::Client` class | |
| 73 59 | 
             
            require 'indieweb/endpoints'
         | 
| 74 60 |  | 
| 75 61 | 
             
            client = IndieWeb::Endpoints::Client.new('https://aaronparecki.com')
         | 
| 62 | 
            +
            #=> #<IndieWeb::Endpoints::Client url: "https://aaronparecki.com">
         | 
| 76 63 |  | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
            endpoints = client.endpoints
         | 
| 64 | 
            +
            client.response
         | 
| 65 | 
            +
            #=> #<HTTP::Response/1.1 200 OK {…}>
         | 
| 80 66 |  | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 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'
         | 
| 67 | 
            +
            client.endpoints
         | 
| 68 | 
            +
            #=> { 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" }
         | 
| 87 69 | 
             
            ```
         | 
| 88 70 |  | 
| 89 71 | 
             
            ### Exception Handling
         | 
    
        data/indieweb-endpoints.gemspec
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            require_relative 'lib/indieweb/endpoints/version'
         | 
| 2 2 |  | 
| 3 3 | 
             
            Gem::Specification.new do |spec|
         | 
| 4 | 
            -
              spec.required_ruby_version = Gem::Requirement.new('>= 2. | 
| 4 | 
            +
              spec.required_ruby_version = Gem::Requirement.new('>= 2.5', '< 2.8')
         | 
| 5 5 |  | 
| 6 6 | 
             
              spec.name          = 'indieweb-endpoints'
         | 
| 7 7 | 
             
              spec.version       = IndieWeb::Endpoints::VERSION
         | 
| @@ -25,6 +25,6 @@ Gem::Specification.new do |spec| | |
| 25 25 | 
             
              spec.add_runtime_dependency 'absolutely', '~> 4.0'
         | 
| 26 26 | 
             
              spec.add_runtime_dependency 'addressable', '~> 2.7'
         | 
| 27 27 | 
             
              spec.add_runtime_dependency 'http', '~> 4.4'
         | 
| 28 | 
            -
              spec.add_runtime_dependency 'link-header-parser', '~>  | 
| 28 | 
            +
              spec.add_runtime_dependency 'link-header-parser', '~> 2.0'
         | 
| 29 29 | 
             
              spec.add_runtime_dependency 'nokogiri', '~> 1.10'
         | 
| 30 30 | 
             
            end
         | 
    
        data/lib/indieweb/endpoints.rb
    CHANGED
    
    | @@ -1,5 +1,3 @@ | |
| 1 | 
            -
            require 'ostruct'
         | 
| 2 | 
            -
             | 
| 3 1 | 
             
            require 'absolutely'
         | 
| 4 2 | 
             
            require 'addressable/uri'
         | 
| 5 3 | 
             
            require 'http'
         | 
| @@ -9,9 +7,7 @@ require 'nokogiri' | |
| 9 7 | 
             
            require 'indieweb/endpoints/version'
         | 
| 10 8 | 
             
            require 'indieweb/endpoints/exceptions'
         | 
| 11 9 |  | 
| 12 | 
            -
            require 'indieweb/endpoints/services/ | 
| 13 | 
            -
            require 'indieweb/endpoints/services/response_body_parser_service'
         | 
| 14 | 
            -
            require 'indieweb/endpoints/services/response_headers_parser_service'
         | 
| 10 | 
            +
            require 'indieweb/endpoints/services/response_parser_service'
         | 
| 15 11 |  | 
| 16 12 | 
             
            require 'indieweb/endpoints/client'
         | 
| 17 13 | 
             
            require 'indieweb/endpoints/parsers'
         | 
| @@ -26,6 +22,12 @@ require 'indieweb/endpoints/parsers/webmention_parser' | |
| 26 22 |  | 
| 27 23 | 
             
            module IndieWeb
         | 
| 28 24 | 
             
              module Endpoints
         | 
| 25 | 
            +
                # Discover a URL's IndieAuth, Micropub, Microsub, and Webmention endpoints
         | 
| 26 | 
            +
                #
         | 
| 27 | 
            +
                #   IndieWeb::Endpoints.get('https://aaronparecki.com')
         | 
| 28 | 
            +
                #
         | 
| 29 | 
            +
                # @param url [String] an absolute URL
         | 
| 30 | 
            +
                # @return [Hash{Symbol => String, Array, nil}]
         | 
| 29 31 | 
             
                def self.get(url)
         | 
| 30 32 | 
             
                  Client.new(url).endpoints
         | 
| 31 33 | 
             
                end
         | 
| @@ -1,27 +1,54 @@ | |
| 1 1 | 
             
            module IndieWeb
         | 
| 2 2 | 
             
              module Endpoints
         | 
| 3 3 | 
             
                class Client
         | 
| 4 | 
            +
                  HTTP_HEADERS_OPTS = {
         | 
| 5 | 
            +
                    accept: '*/*',
         | 
| 6 | 
            +
                    user_agent: 'IndieWeb Endpoint Discovery (https://rubygems.org/gems/indieweb-endpoints)'
         | 
| 7 | 
            +
                  }.freeze
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  # Create a new client with a URL to parse for IndieWeb endpoints
         | 
| 10 | 
            +
                  #
         | 
| 11 | 
            +
                  #   client = IndieWeb::Endpoints::Client.new('https://aaronparecki.com')
         | 
| 12 | 
            +
                  #
         | 
| 13 | 
            +
                  # @param url [String] an absolute URL
         | 
| 4 14 | 
             
                  def initialize(url)
         | 
| 5 | 
            -
                     | 
| 15 | 
            +
                    raise ArgumentError, "url must be a String (given #{url.class})" unless url.is_a?(String)
         | 
| 6 16 |  | 
| 7 | 
            -
                     | 
| 8 | 
            -
             | 
| 9 | 
            -
                    raise  | 
| 10 | 
            -
                   | 
| 11 | 
            -
             | 
| 17 | 
            +
                    @url = url
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    raise ArgumentError, "url (#{url}) must be an absolute URL (e.g. https://example.com)" unless uri.absolute? && uri.scheme.match?(/^https?$/)
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  # @return [String]
         | 
| 23 | 
            +
                  def inspect
         | 
| 24 | 
            +
                    format(%(#<#{self.class.name}:%#0x url: #{url.inspect}>), object_id)
         | 
| 12 25 | 
             
                  end
         | 
| 13 26 |  | 
| 27 | 
            +
                  # @return [Hash{Symbol => String, Array, nil}]
         | 
| 14 28 | 
             
                  def endpoints
         | 
| 15 | 
            -
                    @endpoints ||=  | 
| 29 | 
            +
                    @endpoints ||= Parsers.registered.transform_values { |parser| parser.new(response).results }
         | 
| 16 30 | 
             
                  end
         | 
| 17 31 |  | 
| 32 | 
            +
                  # @see https://www.w3.org/TR/webmention/#limits-on-get-requests
         | 
| 33 | 
            +
                  #
         | 
| 34 | 
            +
                  # @return [HTTP::Response]
         | 
| 18 35 | 
             
                  def response
         | 
| 19 | 
            -
                    @response ||=  | 
| 36 | 
            +
                    @response ||= HTTP.follow(max_hops: 20).headers(HTTP_HEADERS_OPTS).timeout(connect: 5, read: 5).get(uri)
         | 
| 37 | 
            +
                  rescue HTTP::ConnectionError,
         | 
| 38 | 
            +
                         HTTP::TimeoutError,
         | 
| 39 | 
            +
                         HTTP::Redirector::TooManyRedirectsError => exception
         | 
| 40 | 
            +
                    raise IndieWeb::Endpoints.const_get(exception.class.name.split('::').last), exception
         | 
| 20 41 | 
             
                  end
         | 
| 21 42 |  | 
| 22 43 | 
             
                  private
         | 
| 23 44 |  | 
| 24 | 
            -
                  attr_accessor : | 
| 45 | 
            +
                  attr_accessor :url
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  def uri
         | 
| 48 | 
            +
                    @uri ||= Addressable::URI.parse(url)
         | 
| 49 | 
            +
                  rescue Addressable::URI::InvalidURIError => exception
         | 
| 50 | 
            +
                    raise InvalidURIError, exception
         | 
| 51 | 
            +
                  end
         | 
| 25 52 | 
             
                end
         | 
| 26 53 | 
             
              end
         | 
| 27 54 | 
             
            end
         | 
| @@ -6,12 +6,14 @@ module IndieWeb | |
| 6 6 | 
             
                      attr_reader :identifier
         | 
| 7 7 | 
             
                    end
         | 
| 8 8 |  | 
| 9 | 
            +
                    # @param response [HTTP::Response]
         | 
| 9 10 | 
             
                    def initialize(response)
         | 
| 10 11 | 
             
                      raise ArgumentError, "response must be an HTTP::Response (given #{response.class.name})" unless response.is_a?(HTTP::Response)
         | 
| 11 12 |  | 
| 12 13 | 
             
                      @response = response
         | 
| 13 14 | 
             
                    end
         | 
| 14 15 |  | 
| 16 | 
            +
                    # @return [String]
         | 
| 15 17 | 
             
                    def results
         | 
| 16 18 | 
             
                      mapped_results.shift
         | 
| 17 19 | 
             
                    end
         | 
| @@ -27,11 +29,11 @@ module IndieWeb | |
| 27 29 | 
             
                    end
         | 
| 28 30 |  | 
| 29 31 | 
             
                    def results_from_body
         | 
| 30 | 
            -
                      @results_from_body ||= Services:: | 
| 32 | 
            +
                      @results_from_body ||= Services::ResponseParserService.parse_body(response, self.class.identifier)
         | 
| 31 33 | 
             
                    end
         | 
| 32 34 |  | 
| 33 35 | 
             
                    def results_from_headers
         | 
| 34 | 
            -
                      @results_from_headers ||= Services:: | 
| 36 | 
            +
                      @results_from_headers ||= Services::ResponseParserService.parse_headers(response, self.class.identifier)
         | 
| 35 37 | 
             
                    end
         | 
| 36 38 |  | 
| 37 39 | 
             
                    def results_from_http_request
         | 
| @@ -9,7 +9,7 @@ module IndieWeb | |
| 9 9 | 
             
                    private
         | 
| 10 10 |  | 
| 11 11 | 
             
                    def results_for_node(node)
         | 
| 12 | 
            -
                      Services:: | 
| 12 | 
            +
                      Services::ResponseParserService.parse_body(response, self.class.identifier, node)
         | 
| 13 13 | 
             
                    end
         | 
| 14 14 |  | 
| 15 15 | 
             
                    # https://www.w3.org/TR/webmention/#sender-discovers-receiver-webmention-endpoint
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            module IndieWeb
         | 
| 2 | 
            +
              module Endpoints
         | 
| 3 | 
            +
                module Services
         | 
| 4 | 
            +
                  class ResponseParserService
         | 
| 5 | 
            +
                    # @param response [HTTP::Response]
         | 
| 6 | 
            +
                    # @param identifier [Symbol]
         | 
| 7 | 
            +
                    # @return [Array<String>]
         | 
| 8 | 
            +
                    def self.parse_body(response, identifier, node = 'link')
         | 
| 9 | 
            +
                      return unless response.mime_type == 'text/html'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                      # Reject endpoints that contain a fragment identifier
         | 
| 12 | 
            +
                      Nokogiri::HTML(response.body.to_s).css(%(#{node}[rel~="#{identifier}"][href]:not([href*="#"]))).map { |element| element['href'] }
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                    # @param response [HTTP::Response]
         | 
| 16 | 
            +
                    # @param identifier [Symbol]
         | 
| 17 | 
            +
                    # @return [Array<String>, nil]
         | 
| 18 | 
            +
                    def self.parse_headers(response, identifier)
         | 
| 19 | 
            +
                      headers = LinkHeaderParser.parse(response.headers.get('link'), base: response.uri.to_s).group_by_relation_type[identifier]
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                      return unless headers
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                      # Reject endpoints that contain a fragment identifier
         | 
| 24 | 
            +
                      headers.reject { |header| Addressable::URI.parse(header.target_uri).fragment }.map(&:target_uri)
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            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: 4.0.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: 2020- | 
| 11 | 
            +
            date: 2020-07-21 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: absolutely
         | 
| @@ -58,14 +58,14 @@ dependencies: | |
| 58 58 | 
             
                requirements:
         | 
| 59 59 | 
             
                - - "~>"
         | 
| 60 60 | 
             
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            -
                    version:  | 
| 61 | 
            +
                    version: '2.0'
         | 
| 62 62 | 
             
              type: :runtime
         | 
| 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:  | 
| 68 | 
            +
                    version: '2.0'
         | 
| 69 69 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 70 70 | 
             
              name: nokogiri
         | 
| 71 71 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -116,16 +116,14 @@ files: | |
| 116 116 | 
             
            - lib/indieweb/endpoints/parsers/redirect_uri_parser.rb
         | 
| 117 117 | 
             
            - lib/indieweb/endpoints/parsers/token_endpoint_parser.rb
         | 
| 118 118 | 
             
            - lib/indieweb/endpoints/parsers/webmention_parser.rb
         | 
| 119 | 
            -
            - lib/indieweb/endpoints/services/ | 
| 120 | 
            -
            - lib/indieweb/endpoints/services/response_body_parser_service.rb
         | 
| 121 | 
            -
            - lib/indieweb/endpoints/services/response_headers_parser_service.rb
         | 
| 119 | 
            +
            - lib/indieweb/endpoints/services/response_parser_service.rb
         | 
| 122 120 | 
             
            - lib/indieweb/endpoints/version.rb
         | 
| 123 121 | 
             
            homepage: https://github.com/indieweb/indieweb-endpoints-ruby
         | 
| 124 122 | 
             
            licenses:
         | 
| 125 123 | 
             
            - MIT
         | 
| 126 124 | 
             
            metadata:
         | 
| 127 125 | 
             
              bug_tracker_uri: https://github.com/indieweb/indieweb-endpoints-ruby/issues
         | 
| 128 | 
            -
              changelog_uri: https://github.com/indieweb/indieweb-endpoints-ruby/blob/ | 
| 126 | 
            +
              changelog_uri: https://github.com/indieweb/indieweb-endpoints-ruby/blob/v4.0.0/CHANGELOG.md
         | 
| 129 127 | 
             
            post_install_message: 
         | 
| 130 128 | 
             
            rdoc_options: []
         | 
| 131 129 | 
             
            require_paths:
         | 
| @@ -134,7 +132,7 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 134 132 | 
             
              requirements:
         | 
| 135 133 | 
             
              - - ">="
         | 
| 136 134 | 
             
                - !ruby/object:Gem::Version
         | 
| 137 | 
            -
                  version: '2. | 
| 135 | 
            +
                  version: '2.5'
         | 
| 138 136 | 
             
              - - "<"
         | 
| 139 137 | 
             
                - !ruby/object:Gem::Version
         | 
| 140 138 | 
             
                  version: '2.8'
         | 
| @@ -144,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 144 142 | 
             
                - !ruby/object:Gem::Version
         | 
| 145 143 | 
             
                  version: '0'
         | 
| 146 144 | 
             
            requirements: []
         | 
| 147 | 
            -
            rubygems_version: 3.1. | 
| 145 | 
            +
            rubygems_version: 3.1.2
         | 
| 148 146 | 
             
            signing_key: 
         | 
| 149 147 | 
             
            specification_version: 4
         | 
| 150 148 | 
             
            summary: Discover a URL’s IndieAuth, Micropub, Microsub, and Webmention endpoints.
         | 
| @@ -1,22 +0,0 @@ | |
| 1 | 
            -
            module IndieWeb
         | 
| 2 | 
            -
              module Endpoints
         | 
| 3 | 
            -
                module Services
         | 
| 4 | 
            -
                  class HttpRequestService
         | 
| 5 | 
            -
                    HTTP_HEADERS_OPTS = {
         | 
| 6 | 
            -
                      accept: '*/*',
         | 
| 7 | 
            -
                      user_agent: 'IndieWeb Endpoint Discovery (https://rubygems.org/gems/indieweb-endpoints)'
         | 
| 8 | 
            -
                    }.freeze
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                    # HTTP options derived from Webmention specification examples
         | 
| 11 | 
            -
                    # https://www.w3.org/TR/webmention/#limits-on-get-requests
         | 
| 12 | 
            -
                    def self.get(uri)
         | 
| 13 | 
            -
                      HTTP.follow(max_hops: 20).headers(HTTP_HEADERS_OPTS).timeout(connect: 5, read: 5).get(uri)
         | 
| 14 | 
            -
                    rescue HTTP::ConnectionError,
         | 
| 15 | 
            -
                           HTTP::TimeoutError,
         | 
| 16 | 
            -
                           HTTP::Redirector::TooManyRedirectsError => exception
         | 
| 17 | 
            -
                      raise IndieWeb::Endpoints.const_get(exception.class.name.split('::').last), exception
         | 
| 18 | 
            -
                    end
         | 
| 19 | 
            -
                  end
         | 
| 20 | 
            -
                end
         | 
| 21 | 
            -
              end
         | 
| 22 | 
            -
            end
         | 
| @@ -1,14 +0,0 @@ | |
| 1 | 
            -
            module IndieWeb
         | 
| 2 | 
            -
              module Endpoints
         | 
| 3 | 
            -
                module Services
         | 
| 4 | 
            -
                  class ResponseBodyParserService
         | 
| 5 | 
            -
                    def self.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
         | 
| @@ -1,16 +0,0 @@ | |
| 1 | 
            -
            module IndieWeb
         | 
| 2 | 
            -
              module Endpoints
         | 
| 3 | 
            -
                module Services
         | 
| 4 | 
            -
                  class ResponseHeadersParserService
         | 
| 5 | 
            -
                    def self.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
         |