├── lib ├── webmention │ ├── version.rb │ └── client.rb └── webmention.rb ├── Gemfile ├── .travis.yml ├── test ├── lib │ └── webmention │ │ ├── version_test.rb │ │ ├── crawl_test.rb │ │ ├── mention_test.rb │ │ ├── url_test.rb │ │ └── discovery_test.rb ├── test_helper.rb └── data │ └── sample_html.rb ├── .gitignore ├── Rakefile ├── example.rb ├── webmention.gemspec ├── bin └── webmention └── README.md /lib/webmention/version.rb: -------------------------------------------------------------------------------- 1 | module Webmention 2 | VERSION = "0.1.6" 3 | end 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify gem's dependencies in webmention.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.4.1 4 | - 2.3.4 5 | - 2.2.7 6 | notifications: 7 | email: false 8 | -------------------------------------------------------------------------------- /test/lib/webmention/version_test.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../test_helper' 2 | 3 | describe Webmention do 4 | 5 | it "must be defined" do 6 | Webmention::VERSION.wont_be_nil 7 | end 8 | 9 | end 10 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | require 'webmock/minitest' 3 | 4 | require File.expand_path('../../lib/webmention.rb', __FILE__) 5 | require File.expand_path('../data/sample_html.rb', __FILE__) 6 | -------------------------------------------------------------------------------- /lib/webmention.rb: -------------------------------------------------------------------------------- 1 | require 'json' 2 | require 'httparty' 3 | require 'nokogiri' 4 | require 'open-uri' 5 | require 'set' 6 | require 'uri' 7 | 8 | require 'webmention/version' 9 | require 'webmention/client' 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | require 'rake/testtask' 3 | 4 | Rake::TestTask.new do |t| 5 | t.libs << 'lib/webmention' 6 | t.test_files = FileList['test/lib/webmention/*_test.rb'] 7 | t.verbose = true 8 | end 9 | 10 | task :default => :test 11 | -------------------------------------------------------------------------------- /test/lib/webmention/crawl_test.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../test_helper' 2 | 3 | describe Webmention::Client do 4 | before do 5 | WebMock.stub_request(:any, 'http://source.example.com/post/100').to_return( 6 | :status => 200, 7 | :body => SampleData.sample_source_post_html, 8 | :headers => {} 9 | ) 10 | 11 | @client = Webmention::Client.new "http://source.example.com/post/100" 12 | end 13 | 14 | describe "#crawl" do 15 | describe "when a valid url" do 16 | it "should return a count and list of links" do 17 | @client.crawl.must_be :>, 0 18 | @client.links.must_include 'http://target.example.com/post/4' 19 | @client.links.must_include 'http://target.example.com/post/5' 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /example.rb: -------------------------------------------------------------------------------- 1 | require './lib/webmention.rb' 2 | 3 | # Send webmentions to any links on the page that have a webmention endpoint 4 | url = 'http://aaronparecki.com/notes/2013/06/23/1/indiewebcamp' 5 | client = Webmention::Client.new url 6 | sent = client.send_mentions 7 | puts "Sent #{sent} mentions" 8 | 9 | 10 | # Discover the webmention endpoint of a target and send the mention 11 | target = "http://indiewebcamp.com/" 12 | endpoint = Webmention::Client.supports_webmention? target 13 | if endpoint 14 | Webmention::Client.send_mention endpoint, "http://source.example.com/post/100", target 15 | end 16 | 17 | 18 | # You can also use the client to send to a specific webmention endpoint 19 | Webmention::Client.send_mention "http://webmention.io/example/webmention", "http://source.example.com/post/100", "http://target.example.com/post/100" 20 | 21 | -------------------------------------------------------------------------------- /webmention.gemspec: -------------------------------------------------------------------------------- 1 | lib = File.expand_path('../lib', __FILE__) 2 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 3 | require 'webmention/version' 4 | 5 | Gem::Specification.new do |s| 6 | s.name = 'webmention' 7 | s.version = Webmention::VERSION 8 | s.date = '2014-05-25' 9 | s.homepage = 'https://github.com/indieweb/mention-client-ruby' 10 | s.summary = 'A gem for sending webmention (and pingback) notifications' 11 | s.authors = [ 12 | 'Aaron Parecki', 13 | 'Nat Welch' 14 | ] 15 | 16 | s.email = 'aaron@parecki.com' 17 | 18 | s.files = `git ls-files`.split($/) 19 | s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) } 20 | s.test_files = s.files.grep(%r{^(test|spec|features)/}) 21 | s.require_paths = ['lib'] 22 | 23 | s.required_ruby_version = '>= 1.9.3' 24 | 25 | s.add_dependency 'json' 26 | s.add_dependency 'nokogiri' 27 | s.add_dependency 'httparty', '~> 0.13.1' 28 | s.add_dependency 'link_header', '~> 0.0.8' 29 | 30 | s.add_development_dependency 'bundler' 31 | s.add_development_dependency 'rake' 32 | s.add_development_dependency 'minitest' 33 | s.add_development_dependency 'webmock' 34 | end 35 | -------------------------------------------------------------------------------- /test/lib/webmention/mention_test.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../test_helper' 2 | 3 | describe Webmention::Client do 4 | before do 5 | WebMock.stub_request(:any, 'http://source.example.com/post/100').to_return( 6 | :status => 202, 7 | :body => SampleData.sample_source_post_html, 8 | :headers => {} 9 | ) 10 | 11 | WebMock.stub_request(:any, 'http://target.example.com/post/4').to_return( 12 | :status => 202, 13 | :body => SampleData.rel_webmention_href, 14 | :headers => {} 15 | ) 16 | 17 | WebMock.stub_request(:any, 'http://target.example.com/post/5').to_return( 18 | :status => 202, 19 | :body => '', 20 | :headers => { 21 | 'Link' => 'rel="webmention"; ' 22 | } 23 | ) 24 | 25 | WebMock.stub_request(:any, 'http://webmention.io/example/webmention').to_return( 26 | :status => 202 27 | ) 28 | 29 | @client = Webmention::Client.new "http://source.example.com/post/100" 30 | end 31 | 32 | describe "#send_mentions" do 33 | it "should return number of mentions sent" do 34 | @client = Webmention::Client.new "http://source.example.com/post/100" 35 | @client.send_mentions.must_equal 2 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /bin/webmention: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | $:.unshift(File.join(File.dirname(__FILE__), "/../lib")) 4 | require "webmention" 5 | require "link_header" 6 | 7 | url = ARGV[0] 8 | 9 | if url == nil 10 | puts "Usage: webmention http://example.com/post/100" 11 | exit 1 12 | end 13 | 14 | if !Webmention::Client.valid_http_url?(url) 15 | puts "Not a valid URL" 16 | exit 1 17 | end 18 | 19 | client = Webmention::Client.new url 20 | 21 | def debug(msg) 22 | puts msg 23 | end 24 | 25 | debug "Finding links on #{url}" 26 | client.crawl 27 | 28 | links = client.links 29 | debug "Found #{links.length} links:" 30 | debug links.to_a.map{|m| "\t#{m}"}.join("\n") 31 | 32 | debug "" 33 | 34 | links.each do |link| 35 | debug link 36 | 37 | endpoint = Webmention::Client.supports_webmention?(link) 38 | if endpoint 39 | debug "\tDiscovered Webmention endpoint:" 40 | debug "\t#{endpoint}" 41 | debug "\tSending webmention..." 42 | result = Webmention::Client.send_mention endpoint, url, link, true 43 | if result 44 | debug "\tReturned HTTP #{result.code}" 45 | if result.headers['link'] 46 | link_headers = LinkHeader.parse result.headers['link'] 47 | if status_link = link_headers.find_link(['rel', 'status']) 48 | debug "\tWebmention status: #{status_link.href}" 49 | end 50 | end 51 | else 52 | debug "\tEncountered an unknown error sending this webmention!" 53 | end 54 | else 55 | debug "\tNo webmention endpoint found" 56 | end 57 | 58 | debug "" 59 | end 60 | -------------------------------------------------------------------------------- /test/lib/webmention/url_test.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../test_helper' 2 | 3 | describe Webmention::Client do 4 | describe "#new" do 5 | describe "when a valid url" do 6 | it "should not throw an error for http" do 7 | client = Webmention::Client.new "http://google.com" 8 | client.url.must_equal URI.parse("http://google.com") 9 | end 10 | 11 | it "should not throw an error for https" do 12 | client = Webmention::Client.new "https://google.com" 13 | client.url.must_equal URI.parse("https://google.com") 14 | end 15 | end 16 | 17 | describe "when an invalid url" do 18 | it "should raise an error for ftp" do 19 | lambda do 20 | Webmention::Client.new "ftp://google.com" 21 | end.must_raise(ArgumentError) 22 | end 23 | 24 | it "should raise an error for no protocol" do 25 | lambda do 26 | Webmention::Client.new "google.com" 27 | end.must_raise(ArgumentError) 28 | end 29 | end 30 | end 31 | 32 | describe "#absolute_endpoint" do 33 | it "should expand an endpoint url with a path to an absolute url based on the webmention url" do 34 | Webmention::Client.absolute_endpoint('/webmention', 'http://webmention.io/example/1').must_equal "http://webmention.io/webmention" 35 | end 36 | 37 | it "should expand an endpoint url without a path to an absolute url based on the webmention url" do 38 | Webmention::Client.absolute_endpoint('webmention.php', 'http://webmention.io/example/1').must_equal "http://webmention.io/example/webmention.php" 39 | end 40 | 41 | it "should take an empty endpoint url and return the webmention url" do 42 | Webmention::Client.absolute_endpoint('', 'http://webmention.io/example/1').must_equal "http://webmention.io/example/1" 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Webmention Client 2 | ================= 3 | 4 | A Ruby gem for sending [webmention](http://indiewebcamp.com/webmention) (and [pingback](http://indiewebcamp.com/pingback)) notifications. 5 | 6 | [![Build Status](https://travis-ci.org/indieweb/mention-client-ruby.png?branch=master)](https://travis-ci.org/indieweb/mention-client-ruby) 7 | 8 | Installation 9 | ------------ 10 | 11 | gem install webmention 12 | 13 | 14 | Usage 15 | ----- 16 | 17 | ### Send webmentions to all links on a page 18 | 19 | ```ruby 20 | client = Webmention::Client.new url 21 | sent = client.send_mentions 22 | 23 | puts "Sent #{sent} mentions" 24 | ``` 25 | 26 | This will find all absolute links on the page at `url` and will attempt to send 27 | mentions to each. This is accomplished by doing a HEAD request and looking at the headers 28 | for supported servers, if none are found, then it searches the body of the page. 29 | 30 | After finding either webmention or pingback endpoints, the request is sent to each. 31 | 32 | ### Send webmention to a specific URL 33 | 34 | ```ruby 35 | # Discover the webmention endpoint of a target and send the mention 36 | 37 | source = "http://source.example.com/post/100" # For example, your page 38 | target = "http://indiewebcamp.com/" # The page you linked to 39 | 40 | if endpoint = Webmention::Client.supports_webmention?(target) 41 | Webmention::Client.send_mention endpoint, source, target 42 | end 43 | ``` 44 | 45 | Command Line Utility 46 | -------------------- 47 | 48 | For testing or for sending webmentions manually, you can use the command-line utility provided. 49 | 50 | ```bash 51 | $ webmention http://source.example.com/post/100 52 | ``` 53 | 54 | This will look for an [h-entry](http://indiewebcamp.com/h-entry) on the given URL and attempt to send webmentions to each URL in the entry. 55 | 56 | 57 | Webmention 58 | ---------- 59 | 60 | To learn more about Webmention, see [webmention.org](http://webmention.org) and [indiewebcamp.com/webmention](http://indiewebcamp.com/webmention). 61 | 62 | 63 | License 64 | ------- 65 | 66 | Copyright 2013 by Aaron Parecki 67 | 68 | Licensed under the Apache License, Version 2.0 (the "License"); 69 | you may not use this file except in compliance with the License. 70 | You may obtain a copy of the License at 71 | 72 | http://www.apache.org/licenses/LICENSE-2.0 73 | 74 | Unless required by applicable law or agreed to in writing, software 75 | distributed under the License is distributed on an "AS IS" BASIS, 76 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 77 | See the License for the specific language governing permissions and 78 | limitations under the License. 79 | -------------------------------------------------------------------------------- /test/data/sample_html.rb: -------------------------------------------------------------------------------- 1 | class SampleData 2 | 3 | def self.rel_webmention_href 4 | <<-eos 5 | 6 | 7 | 8 | 9 | 10 | eos 11 | end 12 | 13 | def self.rel_webmention_a_href 14 | <<-eos 15 | 16 | 17 | webmention 18 | 19 | 20 | eos 21 | end 22 | def self.rel_href_webmention 23 | <<-eos 24 | 25 | 26 | 27 | 28 | 29 | eos 30 | end 31 | 32 | def self.rel_webmention_org_href 33 | <<-eos 34 | 35 | 36 | 37 | 38 | 39 | eos 40 | end 41 | 42 | def self.rel_href_webmention_org 43 | <<-eos 44 | 45 | 46 | 47 | 48 | 49 | eos 50 | end 51 | 52 | def self.rel_webmention_org_slash_href 53 | <<-eos 54 | 55 | 56 | 57 | 58 | 59 | eos 60 | end 61 | 62 | def self.rel_href_webmention_org_slash 63 | <<-eos 64 | 65 | 66 | 67 | 68 | 69 | eos 70 | end 71 | 72 | def self.sample_source_post_html 73 | <<-eos 74 | 75 | 76 | Sample Post 77 | 78 | 79 |

Link to Target 4

80 |

Link to Target 5

81 | 82 | 83 | eos 84 | end 85 | 86 | def self.rel_webmention_relative_with_path 87 | <<-eos 88 | 89 | 90 | 91 | 92 | 93 | eos 94 | end 95 | 96 | def self.rel_webmention_relative_without_path 97 | <<-eos 98 | 99 | 100 | 101 | 102 | 103 | eos 104 | end 105 | 106 | def self.link_tag_multiple_rel_values 107 | <<-eos 108 | 109 | 110 | 111 | 112 | 113 | eos 114 | end 115 | 116 | def self.empty_link_tag_no_href 117 | <<-eos 118 | 119 | 120 | 121 | 122 | 123 | eos 124 | end 125 | end 126 | -------------------------------------------------------------------------------- /lib/webmention/client.rb: -------------------------------------------------------------------------------- 1 | module Webmention 2 | class Client 3 | # Public: Returns a URI of the url initialized with. 4 | attr_reader :url 5 | 6 | # Public: Returns an array of links contained within the url. 7 | attr_reader :links 8 | 9 | # Public: Create a new client 10 | # 11 | # url - The url you want us to crawl. 12 | def initialize(url) 13 | @url = URI.parse(url) 14 | @links ||= Set.new 15 | 16 | unless Webmention::Client.valid_http_url? @url 17 | raise ArgumentError.new "#{@url} is not a valid HTTP or HTTPS URI." 18 | end 19 | end 20 | 21 | # Public: Crawl the url this client was initialized with. 22 | # 23 | # Returns the number of links found. 24 | def crawl 25 | @links ||= Set.new 26 | if @url.nil? 27 | raise ArgumentError.new "url is nil." 28 | end 29 | 30 | Nokogiri::HTML(open(self.url)).css('.h-entry a').each do |link| 31 | link = link.attribute('href').to_s 32 | if Webmention::Client.valid_http_url? link 33 | @links.add link 34 | end 35 | end 36 | 37 | return @links.count 38 | end 39 | 40 | # Public: Sends mentions to each of the links found in the page. 41 | # 42 | # Returns the number of links mentioned. 43 | def send_mentions 44 | if self.links.nil? or self.links.empty? 45 | self.crawl 46 | end 47 | 48 | cnt = 0 49 | self.links.each do |link| 50 | endpoint = Webmention::Client.supports_webmention? link 51 | if endpoint 52 | cnt += 1 if Webmention::Client.send_mention endpoint, self.url, link 53 | end 54 | end 55 | 56 | return cnt 57 | end 58 | 59 | # Public: Send a mention to an endoint about a link from a link. 60 | # 61 | # endpoint - URL to send mention to. 62 | # source - Source of mention (your page). 63 | # target - The link that was mentioned in the source page. 64 | # 65 | # Returns a boolean. 66 | def self.send_mention endpoint, source, target, full_response=false 67 | data = { 68 | :source => source, 69 | :target => target, 70 | } 71 | 72 | # Ensure the endpoint is an absolute URL 73 | endpoint = absolute_endpoint endpoint, target 74 | 75 | begin 76 | response = HTTParty.post(endpoint, { 77 | :body => data 78 | }) 79 | 80 | if full_response 81 | return response 82 | else 83 | return response.code == 200 || response.code == 202 84 | end 85 | rescue 86 | return false 87 | end 88 | end 89 | 90 | # Public: Fetch a url and check if it supports webmention 91 | # 92 | # url - URL to check 93 | # 94 | # Returns false if does not support webmention, returns string 95 | # of url to ping if it does. 96 | def self.supports_webmention? url 97 | return false if !Webmention::Client.valid_http_url? url 98 | 99 | doc = nil 100 | 101 | begin 102 | response = HTTParty.get(url, { 103 | :timeout => 3, 104 | :headers => { 105 | 'User-Agent' => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36 (https://rubygems.org/gems/webmention)", 106 | 'Accept' => '*/*' 107 | } 108 | }) 109 | 110 | # First check the HTTP Headers 111 | if !response.headers['Link'].nil? 112 | endpoint = self.discover_webmention_endpoint_from_header response.headers['Link'] 113 | return endpoint if endpoint 114 | end 115 | 116 | # Do we support webmention? 117 | endpoint = self.discover_webmention_endpoint_from_html response.body.to_s 118 | return endpoint if endpoint 119 | 120 | # TODO: Move to supports_pingback? method 121 | # Last chance, do we support Pingback? 122 | # if !doc.css('link[rel="pingback"]').empty? 123 | # return doc.css('link[rel="pingback"]').attribute("href").value 124 | # end 125 | 126 | rescue EOFError 127 | rescue Errno::ECONNRESET 128 | end 129 | 130 | return false 131 | end 132 | 133 | def self.discover_webmention_endpoint_from_html html 134 | doc = Nokogiri::HTML(html) 135 | if !doc.css('[rel~="webmention"]').css('[href]').empty? 136 | doc.css('[rel~="webmention"]').css('[href]').attribute("href").value 137 | elsif !doc.css('[rel="http://webmention.org/"]').css('[href]').empty? 138 | doc.css('[rel="http://webmention.org/"]').css('[href]').attribute("href").value 139 | elsif !doc.css('[rel="http://webmention.org"]').css('[href]').empty? 140 | doc.css('[rel="http://webmention.org"]').css('[href]').attribute("href").value 141 | else 142 | false 143 | end 144 | end 145 | 146 | def self.discover_webmention_endpoint_from_header header 147 | if matches = header.match(%r{<([^>]+)>; rel="[^"]*\s?webmention\s?[^"]*"}) 148 | return matches[1] 149 | elsif matches = header.match(%r{<([^>]+)>; rel=webmention}) 150 | return matches[1] 151 | elsif matches = header.match(%r{rel="[^"]*\s?webmention\s?[^"]*"; <([^>]+)>}) 152 | return matches[1] 153 | elsif matches = header.match(%r{rel=webmention; <([^>]+)>}) 154 | return matches[1] 155 | elsif matches = header.match(%r{<([^>]+)>; rel="http://webmention\.org/?"}) 156 | return matches[1] 157 | elsif matches = header.match(%r{rel="http://webmention\.org/?"; <([^>]+)>}) 158 | return matches[1] 159 | end 160 | return false 161 | end 162 | 163 | # Public: Use URI to parse a url and check if it is HTTP or HTTPS. 164 | # 165 | # url - URL to check 166 | # 167 | # Returns a boolean. 168 | def self.valid_http_url? url 169 | if url.is_a? String 170 | url = URI.parse(url) 171 | end 172 | 173 | return (url.is_a? URI::HTTP or url.is_a? URI::HTTPS) 174 | end 175 | 176 | # Public: Takes an endpoint and ensures an absolute URL is returned 177 | # 178 | # endpoint - Endpoint which may be an absolute or relative URL 179 | # url - URL of the webmention 180 | # 181 | # Returns original endpoint if it is already an absolute URL; constructs 182 | # new absolute URL using relative endpoint if not 183 | def self.absolute_endpoint endpoint, url 184 | unless Webmention::Client.valid_http_url? endpoint 185 | endpoint = URI.join(url, endpoint).to_s 186 | end 187 | endpoint 188 | end 189 | end 190 | end 191 | -------------------------------------------------------------------------------- /test/lib/webmention/discovery_test.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../test_helper' 2 | 3 | describe Webmention::Client do 4 | before do 5 | WebMock.stub_request(:any, 'http://example.com/header').to_return( 6 | :status => 200, 7 | :body => 'example', 8 | :headers => { 9 | 'Link' => 'rel="webmention"; ' 10 | } 11 | ) 12 | 13 | WebMock.stub_request(:any, 'http://example.com/html').to_return( 14 | :status => 200, 15 | :body => 'example' 16 | ) 17 | 18 | WebMock.stub_request(:any, 'http://example.com/none').to_return( 19 | :status => 200, 20 | :body => 'example' 21 | ) 22 | end 23 | 24 | describe "#discover_webmention_endpoint_from_url" do 25 | it "should find endpoint from html head" do 26 | Webmention::Client.supports_webmention?("http://example.com/html").must_equal "http://webmention.io/example/webmention" 27 | end 28 | 29 | it "should find endpoint from http header" do 30 | Webmention::Client.supports_webmention?("http://example.com/header").must_equal "http://webmention.io/example/webmention" 31 | end 32 | 33 | it "should return false when no endpoint found" do 34 | Webmention::Client.supports_webmention?("http://example.com/none").must_equal false 35 | end 36 | end 37 | 38 | describe "#discover_webmention_endpoint_from_string" do 39 | it "should find rel=\"webmention\" followed by href in header" do 40 | Webmention::Client.discover_webmention_endpoint_from_header('rel="webmention"; ').must_equal "http://webmention.io/example/webmention" 41 | end 42 | 43 | it "should find rel=webmention followed by href in header" do 44 | Webmention::Client.discover_webmention_endpoint_from_header('rel=webmention; ').must_equal "http://webmention.io/example/webmention" 45 | end 46 | 47 | it "should find href followed by rel=\"webmention\" in header" do 48 | Webmention::Client.discover_webmention_endpoint_from_header('; rel="webmention"').must_equal "http://webmention.io/example/webmention" 49 | end 50 | 51 | it "should find href followed by rel=webmention in header" do 52 | Webmention::Client.discover_webmention_endpoint_from_header('; rel=webmention').must_equal "http://webmention.io/example/webmention" 53 | end 54 | 55 | it "should find rel=http://webmention.org followed by href in header" do 56 | Webmention::Client.discover_webmention_endpoint_from_header('rel="http://webmention.org"; ').must_equal "http://webmention.io/example/webmention" 57 | end 58 | 59 | it "should find href followed by rel=http://webmention.org in header" do 60 | Webmention::Client.discover_webmention_endpoint_from_header('; rel="http://webmention.org"').must_equal "http://webmention.io/example/webmention" 61 | end 62 | 63 | it "should find rel=http://webmention.org/ followed by href in header" do 64 | Webmention::Client.discover_webmention_endpoint_from_header('rel="http://webmention.org/"; ').must_equal "http://webmention.io/example/webmention" 65 | end 66 | 67 | it "should find href followed by rel=http://webmention.org/ in header" do 68 | Webmention::Client.discover_webmention_endpoint_from_header('; rel="http://webmention.org"').must_equal "http://webmention.io/example/webmention" 69 | end 70 | 71 | it "should find rel=webmention followed by href in html" do 72 | Webmention::Client.discover_webmention_endpoint_from_html(SampleData.rel_webmention_href).must_equal "http://webmention.io/example/webmention" 73 | end 74 | 75 | it "should find href followed by rel=webmention in html" do 76 | Webmention::Client.discover_webmention_endpoint_from_html(SampleData.rel_href_webmention).must_equal "http://webmention.io/example/webmention" 77 | end 78 | 79 | it "should find rel=http://webmention.org followed by href in html" do 80 | Webmention::Client.discover_webmention_endpoint_from_html(SampleData.rel_webmention_org_href).must_equal "http://webmention.io/example/webmention" 81 | end 82 | 83 | it "should find href followed by rel=http://webmention.org in html" do 84 | Webmention::Client.discover_webmention_endpoint_from_html(SampleData.rel_href_webmention_org).must_equal "http://webmention.io/example/webmention" 85 | end 86 | 87 | it "should find rel=http://webmention.org/ followed by href in html" do 88 | Webmention::Client.discover_webmention_endpoint_from_html(SampleData.rel_webmention_org_slash_href).must_equal "http://webmention.io/example/webmention" 89 | end 90 | 91 | it "should find href followed by rel=http://webmention.org/ in html" do 92 | Webmention::Client.discover_webmention_endpoint_from_html(SampleData.rel_href_webmention_org_slash).must_equal "http://webmention.io/example/webmention" 93 | end 94 | 95 | it "should find rel=webmention followed by relative href with path in header" do 96 | Webmention::Client.discover_webmention_endpoint_from_header('; rel="http://webmention.org"').must_equal "/example/webmention" 97 | end 98 | 99 | it "should find rel=webmention followed by relative href with path in html" do 100 | Webmention::Client.discover_webmention_endpoint_from_html(SampleData.rel_webmention_relative_with_path).must_equal "/example/webmention" 101 | end 102 | 103 | it "should find rel=webmention followed by relative href without path in header" do 104 | Webmention::Client.discover_webmention_endpoint_from_header('; rel="http://webmention.org"').must_equal "webmention.php" 105 | end 106 | 107 | it "should find rel=webmention followed by relative href without path in html" do 108 | Webmention::Client.discover_webmention_endpoint_from_html(SampleData.rel_webmention_relative_without_path).must_equal "webmention.php" 109 | end 110 | 111 | it "should find webmention in a link tag among multiple rel values" do 112 | Webmention::Client.discover_webmention_endpoint_from_html(SampleData.link_tag_multiple_rel_values).must_equal "http://webmention.io/example/webmention" 113 | end 114 | 115 | it "should find webmention in a link header among multiple rel values" do 116 | Webmention::Client.discover_webmention_endpoint_from_header('; rel="webmention foo bar"').must_equal "http://webmention.io/example/webmention" 117 | end 118 | 119 | it "should find rel=webmention in a link tag with an empty href" do 120 | Webmention::Client.discover_webmention_endpoint_from_html(SampleData.empty_link_tag_no_href).must_equal "" 121 | end 122 | end 123 | 124 | end 125 | --------------------------------------------------------------------------------