Compare commits
10 Commits
ae5c02b7ed
...
eed9ee4583
| Author | SHA1 | Date | |
|---|---|---|---|
| eed9ee4583 | |||
| 3d9bdb1cab | |||
| fa9f0b785e | |||
| 4c36da46fe | |||
| c5d5c123a6 | |||
| 8826b1d672 | |||
| 5280a24f4b | |||
| 5de24e9fc4 | |||
| 33134c12f4 | |||
| 7c89900c70 |
@@ -1,5 +1,6 @@
|
||||
sudo: false
|
||||
language: ruby
|
||||
rvm:
|
||||
- 2.3.1
|
||||
before_install: gem install bundler -v 1.16.2
|
||||
- 2.6.6
|
||||
cache: bundler
|
||||
before_install: gem install bundler
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
[](http://travis-ci.org/5apps/manifique)
|
||||
|
||||
# Manifique
|
||||
|
||||
Manifique fetches metadata of Web applications, like e.g. name, description,
|
||||
@@ -84,4 +86,4 @@ _TODO add information about dual/commercial licensing_
|
||||
|
||||
Everyone interacting in this project’s codebase, issue trackers, and chat
|
||||
rooms is expected to follow the [code of
|
||||
conduct](https://github.com/skddc/manifique/blob/master/CODE_OF_CONDUCT.md).
|
||||
conduct](https://github.com/5apps/manifique/blob/master/CODE_OF_CONDUCT.md).
|
||||
|
||||
11
lib/manifique/errors.rb
Normal file
11
lib/manifique/errors.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
module Manifique
|
||||
class Error < ::StandardError
|
||||
attr_reader :type, :url
|
||||
|
||||
def initialize(msg="Encountered an error", type="generic", url)
|
||||
@type = type
|
||||
@url = url
|
||||
super(msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,8 +1,9 @@
|
||||
require 'json'
|
||||
require 'faraday'
|
||||
require 'faraday_middleware'
|
||||
require "nokogiri"
|
||||
require 'nokogiri'
|
||||
require 'manifique/metadata'
|
||||
require 'manifique/errors'
|
||||
|
||||
module Manifique
|
||||
class WebClient
|
||||
@@ -103,7 +104,7 @@ module Manifique
|
||||
icon_links.each do |link|
|
||||
icon = {}
|
||||
icon["src"] = link.attributes["href"].value rescue nil
|
||||
next if icon["src"].to_s.empty?
|
||||
next unless is_adequate_src(icon["src"])
|
||||
icon["sizes"] = link.attributes["sizes"].value rescue nil
|
||||
icon["type"] = link.attributes["type"].value rescue get_icon_type(icon["src"])
|
||||
@metadata.icons.push icon
|
||||
@@ -117,7 +118,7 @@ module Manifique
|
||||
icon_links.each do |link|
|
||||
icon = { "purpose" => "apple-touch-icon" }
|
||||
icon["src"] = link.attributes["href"].value rescue nil
|
||||
next if icon["src"].to_s.empty?
|
||||
next unless is_adequate_src(icon["src"])
|
||||
icon["sizes"] = link.attributes["sizes"].value rescue nil
|
||||
icon["type"] = link.attributes["type"].value rescue get_icon_type(icon["src"])
|
||||
@metadata.icons.push icon
|
||||
@@ -130,7 +131,7 @@ module Manifique
|
||||
if mask_icon_link = @html.at_css("link[rel=mask-icon]")
|
||||
icon = { "purpose" => "mask-icon" }
|
||||
icon["src"] = mask_icon_link.attributes["href"].value rescue nil
|
||||
return if icon["src"].to_s.empty?
|
||||
return unless is_adequate_src(icon["src"])
|
||||
icon["type"] = link.attributes["type"].value rescue get_icon_type(icon["src"])
|
||||
icon["color"] = mask_icon_link.attributes["color"].value rescue nil
|
||||
@metadata.icons.push icon
|
||||
@@ -138,6 +139,14 @@ module Manifique
|
||||
end
|
||||
end
|
||||
|
||||
def is_data_url?(src)
|
||||
!!src.match(/^data:/)
|
||||
end
|
||||
|
||||
def is_adequate_src(src)
|
||||
!src.to_s.empty? && !is_data_url?(src)
|
||||
end
|
||||
|
||||
def get_icon_type(src)
|
||||
extension = src.match(/\.([a-zA-Z]+)$/)[1]
|
||||
return "image/#{extension}"
|
||||
@@ -152,8 +161,10 @@ module Manifique
|
||||
if res.status < 400
|
||||
res
|
||||
else
|
||||
raise "Could not fetch #{url} successfully (#{res.status})"
|
||||
raise Manifique::Error.new "Failed with HTTP status #{res.status}", "http_#{res.status}", url
|
||||
end
|
||||
rescue Faraday::ConnectionFailed, Faraday::TimeoutError, Faraday::SSLError => e
|
||||
raise Manifique::Error.new "Failed to connect", "connection_failed", url
|
||||
end
|
||||
|
||||
def discover_web_manifest_url(html)
|
||||
@@ -161,6 +172,5 @@ module Manifique
|
||||
rescue
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
17
spec/fixtures/kommit.html
vendored
Normal file
17
spec/fixtures/kommit.html
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Kommit</title>
|
||||
<meta name="description" content="Augment your memory" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="icon" href="data:;base64,iVBORw0KGgo=">
|
||||
<link rel="canonical" href="/" />
|
||||
<link rel="alternate" hreflang="en" href="/en/" />
|
||||
<link rel="apple-touch-icon" href="https://abcdefg.s3.amazonaws.com/public/icon.jpg">
|
||||
</head>
|
||||
<head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -13,6 +13,13 @@ RSpec.describe Manifique::WebClient do
|
||||
|
||||
stub_request(:get, "http://example.com/200_empty").
|
||||
to_return(body: "", status: 200, headers: {})
|
||||
|
||||
stub_request(:get, "http://example.com/failed").
|
||||
to_raise(Faraday::ConnectionFailed)
|
||||
stub_request(:get, "http://example.com/timeout").
|
||||
to_raise(Faraday::TimeoutError)
|
||||
stub_request(:get, "http://example.com/ssl_error").
|
||||
to_raise(Faraday::SSLError)
|
||||
end
|
||||
|
||||
context "unsuccessful requests" do
|
||||
@@ -22,7 +29,12 @@ RSpec.describe Manifique::WebClient do
|
||||
it "raises an exception" do
|
||||
expect {
|
||||
client.send(:do_get_request, 'http://example.com/404')
|
||||
}.to raise_error("Could not fetch http://example.com/404 successfully (404)")
|
||||
}.to raise_error { |error|
|
||||
expect(error).to be_a(Manifique::Error)
|
||||
expect(error.message).to eq("Failed with HTTP status 404")
|
||||
expect(error.type).to eq("http_404")
|
||||
expect(error.url).to eq("http://example.com/404")
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,7 +44,39 @@ RSpec.describe Manifique::WebClient do
|
||||
it "raises an exception" do
|
||||
expect {
|
||||
client.send(:do_get_request, 'http://example.com/500')
|
||||
}.to raise_error("Could not fetch http://example.com/500 successfully (500)")
|
||||
}.to raise_error { |error|
|
||||
expect(error).to be_a(Manifique::Error)
|
||||
expect(error.message).to eq("Failed with HTTP status 500")
|
||||
expect(error.type).to eq("http_500")
|
||||
expect(error.url).to eq("http://example.com/500")
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "failed connections" do
|
||||
let(:client) { Manifique::WebClient.new }
|
||||
|
||||
it "raises an exception on connection failures" do
|
||||
expect {
|
||||
client.send(:do_get_request, 'http://example.com/failed')
|
||||
}.to raise_error { |error|
|
||||
expect(error).to be_a(Manifique::Error)
|
||||
expect(error.message).to eq("Failed to connect")
|
||||
expect(error.type).to eq("connection_failed")
|
||||
expect(error.url).to eq("http://example.com/failed")
|
||||
}
|
||||
end
|
||||
|
||||
it "raises an exception on timeouts" do
|
||||
expect {
|
||||
client.send(:do_get_request, 'http://example.com/timeout')
|
||||
}.to raise_error("Failed to connect")
|
||||
end
|
||||
|
||||
it "raises an exception on SSL errors" do
|
||||
expect {
|
||||
client.send(:do_get_request, 'http://example.com/ssl_error')
|
||||
}.to raise_error("Failed to connect")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -211,6 +255,38 @@ RSpec.describe Manifique::WebClient do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with data URL icons" do
|
||||
before do
|
||||
index_html = File.read(File.join(__dir__, "..", "fixtures", "kommit.html"));
|
||||
stub_request(:get, "https://kosmos.social/").
|
||||
to_return(body: index_html, status: 200, headers: {
|
||||
"Content-Type": "text/html; charset=utf-8"
|
||||
})
|
||||
end
|
||||
|
||||
subject { web_client.fetch_metadata }
|
||||
|
||||
it "returns a metadata object" do
|
||||
expect(subject).to be_kind_of(Manifique::Metadata)
|
||||
end
|
||||
|
||||
it "loads properties from parsed HTML" do
|
||||
expect(subject.name).to eq("Kommit")
|
||||
expect(subject.description).to eq("Augment your memory")
|
||||
end
|
||||
|
||||
it "ignores data URL icons" do
|
||||
expect(subject.icons.length).to eq(1)
|
||||
end
|
||||
|
||||
it "loads icons from link[rel=apple-touch-icon] elements" do
|
||||
apple_touch_icons = subject.icons.select{|i| i["purpose"] == "apple-touch-icon"}
|
||||
expect(apple_touch_icons.length).to eq(1)
|
||||
expect(apple_touch_icons.first["type"]).to eq("image/jpg")
|
||||
expect(apple_touch_icons.first["sizes"]).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user