mirror of
https://gitea.invidious.io/iv-org/shard-athena-negotiation.git
synced 2024-08-15 00:53:23 +00:00
Add more specialized negotiators
Fix issue with accept language setting
This commit is contained in:
parent
bf08531bca
commit
3850074f02
12 changed files with 211 additions and 14 deletions
67
spec/charset_negotiator_spec.cr
Normal file
67
spec/charset_negotiator_spec.cr
Normal file
|
@ -0,0 +1,67 @@
|
|||
require "./spec_helper"
|
||||
|
||||
struct CharsetNegotiatorTest < NegotiatorTestCase
|
||||
@negotiator : ANG::CharsetNegotiator
|
||||
|
||||
def initialize
|
||||
@negotiator = ANG::CharsetNegotiator.new
|
||||
end
|
||||
|
||||
def test_best_unmatched_header : Nil
|
||||
@negotiator.best("foo, bar, yo", {"baz"}).should be_nil
|
||||
end
|
||||
|
||||
def test_best_ignores_missing_content : Nil
|
||||
accept = @negotiator.best "en; q=0.1, fr; q=0.4, bu; q=1.0", {"en", "fr"}
|
||||
|
||||
accept = accept.should_not be_nil
|
||||
accept.should be_a ANG::AcceptCharset
|
||||
accept.value.should eq "fr"
|
||||
end
|
||||
|
||||
def test_best_respects_priorities : Nil
|
||||
accept = @negotiator.best "foo, bar, yo", {"yo"}
|
||||
accept = accept.should_not be_nil
|
||||
accept.should be_a ANG::AcceptCharset
|
||||
accept.type.should eq "yo"
|
||||
end
|
||||
|
||||
def test_best_respects_quality : Nil
|
||||
accept = @negotiator.best "utf-8;q=0.5,iso-8859-1", {"iso-8859-1;q=0.3", "utf-8;q=0.9", "utf-16;q=1.0"}
|
||||
accept = accept.should_not be_nil
|
||||
accept.should be_a ANG::AcceptCharset
|
||||
accept.type.should eq "utf-8"
|
||||
end
|
||||
|
||||
@[DataProvider("best_data_provider")]
|
||||
def test_best(header : String, priorities : Indexable(String), expected : String?) : Nil
|
||||
accept = @negotiator.best header, priorities
|
||||
|
||||
if accept.nil?
|
||||
expected.should be_nil
|
||||
else
|
||||
accept.should be_a ANG::AcceptCharset
|
||||
accept.value.should eq expected
|
||||
end
|
||||
end
|
||||
|
||||
def best_data_provider : Tuple
|
||||
php_pear_charset = "ISO-8859-1, Big5;q=0.6,utf-8;q=0.7, *;q=0.5"
|
||||
php_pear_charset2 = "ISO-8859-1, Big5;q=0.6,utf-8;q=0.7"
|
||||
|
||||
{
|
||||
{php_pear_charset, {"utf-8", "big5", "iso-8859-1", "shift-jis"}, "iso-8859-1"},
|
||||
{php_pear_charset, {"utf-8", "big5", "shift-jis"}, "utf-8"},
|
||||
{php_pear_charset, {"Big5", "shift-jis"}, "Big5"},
|
||||
{php_pear_charset, {"shift-jis"}, "shift-jis"},
|
||||
{php_pear_charset2, {"utf-8", "big5", "iso-8859-1", "shift-jis"}, "iso-8859-1"},
|
||||
{php_pear_charset2, {"utf-8", "big5", "shift-jis"}, "utf-8"},
|
||||
{php_pear_charset2, {"Big5", "shift-jis"}, "Big5"},
|
||||
{"utf-8;q=0.6,iso-8859-5;q=0.9", {"iso-8859-5", "utf-8"}, "iso-8859-5"},
|
||||
{"en, *;q=0.9", {"fr"}, "fr"},
|
||||
# Quality of source factors
|
||||
{php_pear_charset, {"iso-8859-1;q=0.5", "utf-8", "utf-16;q=1.0"}, "utf-8"},
|
||||
{php_pear_charset, {"iso-8859-1;q=0.8", "utf-8", "utf-16;q=1.0"}, "iso-8859-1;q=0.8"},
|
||||
}
|
||||
end
|
||||
end
|
42
spec/encoding_negotiator_spec.cr
Normal file
42
spec/encoding_negotiator_spec.cr
Normal file
|
@ -0,0 +1,42 @@
|
|||
require "./spec_helper"
|
||||
|
||||
struct EncodingNegotiatorTest < NegotiatorTestCase
|
||||
@negotiator : ANG::EncodingNegotiator
|
||||
|
||||
def initialize
|
||||
@negotiator = ANG::EncodingNegotiator.new
|
||||
end
|
||||
|
||||
def test_best_unmatched_header : Nil
|
||||
@negotiator.best("foo, bar, yo", {"baz"}).should be_nil
|
||||
end
|
||||
|
||||
def test_best_respects_quality : Nil
|
||||
accept = @negotiator.best "gzip;q=0.7,identity", {"identity;q=0.5", "gzip;q=0.9"}
|
||||
accept = accept.should_not be_nil
|
||||
accept.should be_a ANG::AcceptEncoding
|
||||
accept.type.should eq "gzip"
|
||||
end
|
||||
|
||||
@[DataProvider("best_data_provider")]
|
||||
def test_best(header : String, priorities : Indexable(String), expected : String?) : Nil
|
||||
accept = @negotiator.best header, priorities
|
||||
|
||||
if accept.nil?
|
||||
expected.should be_nil
|
||||
else
|
||||
accept.should be_a ANG::AcceptEncoding
|
||||
accept.value.should eq expected
|
||||
end
|
||||
end
|
||||
|
||||
def best_data_provider : Tuple
|
||||
{
|
||||
{"gzip;q=1.0, identity; q=0.5, *;q=0", {"identity"}, "identity"},
|
||||
{"gzip;q=0.5, identity; q=0.5, *;q=0.7", {"bzip", "foo"}, "bzip"},
|
||||
{"gzip;q=0.7, identity; q=0.5, *;q=0.7", {"gzip", "foo"}, "gzip"},
|
||||
# Quality of source factors
|
||||
{"gzip;q=0.7,identity", {"identity;q=0.5", "gzip;q=0.9"}, "gzip;q=0.9"},
|
||||
}
|
||||
end
|
||||
end
|
43
spec/language_negotiator_spec.cr
Normal file
43
spec/language_negotiator_spec.cr
Normal file
|
@ -0,0 +1,43 @@
|
|||
require "./spec_helper"
|
||||
|
||||
struct LanguageNegotiatorTest < NegotiatorTestCase
|
||||
@negotiator : ANG::LanguageNegotiator
|
||||
|
||||
def initialize
|
||||
@negotiator = ANG::LanguageNegotiator.new
|
||||
end
|
||||
|
||||
def test_best_respects_quality : Nil
|
||||
accept = @negotiator.best "en;q=0.5,de", {"de;q=0.3", "en;q=0.9"}
|
||||
accept = accept.should_not be_nil
|
||||
accept.should be_a ANG::AcceptLanguage
|
||||
accept.type.should eq "en"
|
||||
end
|
||||
|
||||
@[DataProvider("best_data_provider")]
|
||||
def test_best(header : String, priorities : Indexable(String), expected : String?) : Nil
|
||||
accept = @negotiator.best header, priorities
|
||||
|
||||
if accept.nil?
|
||||
expected.should be_nil
|
||||
else
|
||||
accept.should be_a ANG::AcceptLanguage
|
||||
accept.value.should eq expected
|
||||
end
|
||||
end
|
||||
|
||||
def best_data_provider : Tuple
|
||||
{
|
||||
{"en, de", {"fr"}, nil},
|
||||
{"foo, bar, yo", {"baz", "biz"}, nil},
|
||||
{"fr-FR, en;q=0.8", {"en-US", "de-DE"}, "en-US"},
|
||||
{"en, *;q=0.9", {"fr"}, "fr"},
|
||||
{"foo, bar, yo", {"yo"}, "yo"},
|
||||
{"en; q=0.1, fr; q=0.4, bu; q=1.0", {"en", "fr"}, "fr"},
|
||||
{"en; q=0.1, fr; q=0.4, fu; q=0.9, de; q=0.2", {"en", "fu"}, "fu"},
|
||||
{"fr, zh-Hans-CN;q=0.3", {"fr"}, "fr"},
|
||||
# Quality of source factors
|
||||
{"en;q=0.5,de", {"de;q=0.3", "en;q=0.9"}, "en;q=0.9"},
|
||||
}
|
||||
end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
require "./spec_helper"
|
||||
|
||||
struct NegotiatorTest < ASPEC::TestCase
|
||||
struct NegotiatorTest < NegotiatorTestCase
|
||||
@negotiator : ANG::Negotiator
|
||||
|
||||
def initialize
|
||||
|
@ -18,20 +18,12 @@ struct NegotiatorTest < ASPEC::TestCase
|
|||
@negotiator.best("/qwer", {"foo/bar"}, false).should be_nil
|
||||
end
|
||||
|
||||
def test_best_exception_handling : Nil
|
||||
def test_invalid_media_type : Nil
|
||||
ex = expect_raises ANG::Exceptions::InvalidMediaType, "Invalid media type: '/qwer'." do
|
||||
@negotiator.best "foo/bar", {"/qwer"}
|
||||
end
|
||||
|
||||
ex.type.should eq "/qwer"
|
||||
|
||||
expect_raises ArgumentError, "priorities should not be empty." do
|
||||
@negotiator.best "foo/bar", [] of String
|
||||
end
|
||||
|
||||
expect_raises ArgumentError, "The header string should not be empty." do
|
||||
@negotiator.best "", {"text/html"}
|
||||
end
|
||||
end
|
||||
|
||||
@[DataProvider("best_data_provider")]
|
||||
|
|
11
spec/negotiator_test_case.cr
Normal file
11
spec/negotiator_test_case.cr
Normal file
|
@ -0,0 +1,11 @@
|
|||
abstract struct NegotiatorTestCase < ASPEC::TestCase
|
||||
def test_best_exception_handling : Nil
|
||||
expect_raises ArgumentError, "priorities should not be empty." do
|
||||
@negotiator.best "foo/bar", [] of String
|
||||
end
|
||||
|
||||
expect_raises ArgumentError, "The header string should not be empty." do
|
||||
@negotiator.best "", {"text/html"}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
require "spec"
|
||||
require "athena-spec"
|
||||
require "../src/athena-negotiation"
|
||||
require "./negotiator_test_case"
|
||||
|
||||
include ASPEC::Methods
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ struct Athena::Negotiation::AcceptLanguage < Athena::Negotiation::BaseAccept
|
|||
def initialize(value : String)
|
||||
super value
|
||||
|
||||
parts = @value.split '-'
|
||||
parts = @type.split '-'
|
||||
|
||||
case parts.size
|
||||
when 2
|
||||
|
|
|
@ -3,6 +3,9 @@ require "./accept_match"
|
|||
require "./accept_charset"
|
||||
require "./accept_encoding"
|
||||
require "./accept_language"
|
||||
require "./charset_negotiator"
|
||||
require "./encoding_negotiator"
|
||||
require "./language_negotiator"
|
||||
require "./negotiator"
|
||||
|
||||
require "./exceptions/*"
|
||||
|
|
7
src/charset_negotiator.cr
Normal file
7
src/charset_negotiator.cr
Normal file
|
@ -0,0 +1,7 @@
|
|||
require "./abstract_negotiator"
|
||||
|
||||
class Athena::Negotiation::CharsetNegotiator < Athena::Negotiation::AbstractNegotiator
|
||||
private def create_header(header : String) : ANG::BaseAccept
|
||||
ANG::AcceptCharset.new header
|
||||
end
|
||||
end
|
7
src/encoding_negotiator.cr
Normal file
7
src/encoding_negotiator.cr
Normal file
|
@ -0,0 +1,7 @@
|
|||
require "./abstract_negotiator"
|
||||
|
||||
class Athena::Negotiation::EncodingNegotiator < Athena::Negotiation::AbstractNegotiator
|
||||
private def create_header(header : String) : ANG::BaseAccept
|
||||
ANG::AcceptEncoding.new header
|
||||
end
|
||||
end
|
26
src/language_negotiator.cr
Normal file
26
src/language_negotiator.cr
Normal file
|
@ -0,0 +1,26 @@
|
|||
require "./abstract_negotiator"
|
||||
|
||||
class Athena::Negotiation::LanguageNegotiator < Athena::Negotiation::AbstractNegotiator
|
||||
protected def match(accept : ANG::AcceptLanguage, priority : ANG::AcceptLanguage, index : Int32) : ANG::AcceptMatch?
|
||||
accept_base = accept.language
|
||||
priority_base = priority.language
|
||||
|
||||
accept_sub = accept.region
|
||||
priority_sub = priority.region
|
||||
|
||||
base_equal = accept_base.downcase == priority_base.downcase
|
||||
sub_equal = accept_sub.try &.downcase == priority_sub.try &.downcase
|
||||
|
||||
if ((accept_base == "*" || base_equal) && (accept_sub.nil? || sub_equal))
|
||||
score = 10 * (base_equal ? 1 : 0) + (sub_equal ? 1 : 0)
|
||||
|
||||
return ANG::AcceptMatch.new accept.quality * priority.quality, score, index
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
private def create_header(header : String) : ANG::BaseAccept
|
||||
ANG::AcceptLanguage.new header
|
||||
end
|
||||
end
|
|
@ -1,9 +1,7 @@
|
|||
require "./abstract_negotiator"
|
||||
|
||||
class Athena::Negotiation::Negotiator < Athena::Negotiation::AbstractNegotiator
|
||||
protected def match(accept : ANG::BaseAccept, priority : ANG::BaseAccept, index : Int32) : ANG::AcceptMatch?
|
||||
return nil if !accept.is_a?(ANG::Accept) || !priority.is_a?(ANG::Accept)
|
||||
|
||||
protected def match(accept : ANG::Accept, priority : ANG::Accept, index : Int32) : ANG::AcceptMatch?
|
||||
accept_base = accept.base_part
|
||||
priority_base = priority.base_part
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue