xenon 0.0.3 → 0.0.4
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
- metadata +13 -145
- data/.codeclimate.yml +0 -18
- data/.gitignore +0 -25
- data/.rspec +0 -3
- data/.travis.yml +0 -6
- data/Gemfile +0 -13
- data/Guardfile +0 -16
- data/LICENSE +0 -22
- data/README.md +0 -86
- data/Rakefile +0 -8
- data/examples/hello_world/config.ru +0 -3
- data/examples/hello_world/hello_world.rb +0 -17
- data/lib/xenon.rb +0 -253
- data/lib/xenon/auth.rb +0 -63
- data/lib/xenon/errors.rb +0 -5
- data/lib/xenon/etag.rb +0 -48
- data/lib/xenon/headers.rb +0 -112
- data/lib/xenon/headers/accept.rb +0 -34
- data/lib/xenon/headers/accept_charset.rb +0 -59
- data/lib/xenon/headers/accept_encoding.rb +0 -63
- data/lib/xenon/headers/accept_language.rb +0 -59
- data/lib/xenon/headers/authorization.rb +0 -50
- data/lib/xenon/headers/cache_control.rb +0 -56
- data/lib/xenon/headers/content_type.rb +0 -23
- data/lib/xenon/headers/if_match.rb +0 -53
- data/lib/xenon/headers/if_modified_since.rb +0 -22
- data/lib/xenon/headers/if_none_match.rb +0 -53
- data/lib/xenon/headers/if_range.rb +0 -45
- data/lib/xenon/headers/if_unmodified_since.rb +0 -22
- data/lib/xenon/headers/user_agent.rb +0 -65
- data/lib/xenon/headers/www_authenticate.rb +0 -70
- data/lib/xenon/media_type.rb +0 -162
- data/lib/xenon/parsers/basic_rules.rb +0 -86
- data/lib/xenon/parsers/header_rules.rb +0 -60
- data/lib/xenon/parsers/media_type.rb +0 -53
- data/lib/xenon/quoted_string.rb +0 -20
- data/lib/xenon/routing/directives.rb +0 -14
- data/lib/xenon/routing/header_directives.rb +0 -32
- data/lib/xenon/routing/method_directives.rb +0 -26
- data/lib/xenon/routing/param_directives.rb +0 -22
- data/lib/xenon/routing/path_directives.rb +0 -37
- data/lib/xenon/routing/route_directives.rb +0 -51
- data/lib/xenon/routing/security_directives.rb +0 -20
- data/lib/xenon/version.rb +0 -3
- data/spec/spec_helper.rb +0 -94
- data/spec/xenon/etag_spec.rb +0 -19
- data/spec/xenon/headers/accept_charset_spec.rb +0 -31
- data/spec/xenon/headers/accept_encoding_spec.rb +0 -40
- data/spec/xenon/headers/accept_language_spec.rb +0 -33
- data/spec/xenon/headers/accept_spec.rb +0 -54
- data/spec/xenon/headers/authorization_spec.rb +0 -47
- data/spec/xenon/headers/cache_control_spec.rb +0 -64
- data/spec/xenon/headers/if_match_spec.rb +0 -73
- data/spec/xenon/headers/if_modified_since_spec.rb +0 -19
- data/spec/xenon/headers/if_none_match_spec.rb +0 -79
- data/spec/xenon/headers/if_range_spec.rb +0 -45
- data/spec/xenon/headers/if_unmodified_since_spec.rb +0 -19
- data/spec/xenon/headers/user_agent_spec.rb +0 -67
- data/spec/xenon/headers/www_authenticate_spec.rb +0 -43
- data/spec/xenon/media_type_spec.rb +0 -267
- data/xenon.gemspec +0 -30
data/lib/xenon/auth.rb
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
require 'xenon/quoted_string'
|
2
|
-
|
3
|
-
module Xenon
|
4
|
-
class BasicCredentials
|
5
|
-
attr_reader :username, :password
|
6
|
-
|
7
|
-
def initialize(username, password)
|
8
|
-
@username = username
|
9
|
-
@password = password
|
10
|
-
end
|
11
|
-
|
12
|
-
def token
|
13
|
-
Base64.strict_encode64("#{@username}:#{@password}")
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.decode(s)
|
17
|
-
str = Base64.strict_decode64(s)
|
18
|
-
username, password = str.split(':', 2)
|
19
|
-
BasicCredentials.new(username, password)
|
20
|
-
end
|
21
|
-
|
22
|
-
def to_s
|
23
|
-
"Basic #{token}"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
class GenericCredentials
|
28
|
-
using QuotedString
|
29
|
-
|
30
|
-
attr_reader :scheme, :token, :params
|
31
|
-
|
32
|
-
def initialize(scheme, token: nil, params: {})
|
33
|
-
@scheme = scheme
|
34
|
-
@token = token
|
35
|
-
@params = params
|
36
|
-
end
|
37
|
-
|
38
|
-
def to_s
|
39
|
-
s = @scheme.dup
|
40
|
-
s << ' ' << @token if @token
|
41
|
-
s << ' ' << @params.map { |n, v| "#{n}=#{v.quote}" }.join(', ')
|
42
|
-
s
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
class BasicAuth
|
47
|
-
attr_reader :auth_params
|
48
|
-
|
49
|
-
def initialize(auth_params = {}, &store)
|
50
|
-
@auth_params = auth_params
|
51
|
-
@store = store
|
52
|
-
end
|
53
|
-
|
54
|
-
def scheme
|
55
|
-
'Basic'
|
56
|
-
end
|
57
|
-
|
58
|
-
def call(request)
|
59
|
-
header = request.header('Authorization') rescue nil
|
60
|
-
@store.call(header.credentials) if header && header.credentials.is_a?(BasicCredentials)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
data/lib/xenon/errors.rb
DELETED
data/lib/xenon/etag.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
require 'xenon/parsers/header_rules'
|
2
|
-
|
3
|
-
module Xenon
|
4
|
-
class ETag
|
5
|
-
attr_reader :opaque_tag
|
6
|
-
|
7
|
-
def initialize(opaque_tag, weak: false)
|
8
|
-
@opaque_tag = opaque_tag
|
9
|
-
@weak = weak
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.parse(s)
|
13
|
-
tree = Parsers::ETag.new.etag.parse(s)
|
14
|
-
Parsers::ETagHeaderTransform.new.apply(tree)
|
15
|
-
end
|
16
|
-
|
17
|
-
def weak?
|
18
|
-
@weak
|
19
|
-
end
|
20
|
-
|
21
|
-
def strong?
|
22
|
-
!weak?
|
23
|
-
end
|
24
|
-
|
25
|
-
def strong_eq?(other)
|
26
|
-
strong? && other.strong? && @opaque_tag == other.opaque_tag
|
27
|
-
end
|
28
|
-
|
29
|
-
def weak_eq?(other)
|
30
|
-
@opaque_tag == other.opaque_tag
|
31
|
-
end
|
32
|
-
|
33
|
-
def ==(other)
|
34
|
-
strong? == other.strong? && @opaque_tag == other.opaque_tag
|
35
|
-
end
|
36
|
-
|
37
|
-
def to_s
|
38
|
-
s = weak? ? "W/" : ""
|
39
|
-
s << '"' << @opaque_tag << '"'
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
module Parsers
|
44
|
-
class ETag < Parslet::Parser
|
45
|
-
include ETagHeaderRules
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
data/lib/xenon/headers.rb
DELETED
@@ -1,112 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/string'
|
2
|
-
|
3
|
-
module Xenon
|
4
|
-
class Headers
|
5
|
-
include Enumerable
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
@hash = {}
|
9
|
-
end
|
10
|
-
|
11
|
-
def initialize_dup(other)
|
12
|
-
super
|
13
|
-
@hash = @hash.dup
|
14
|
-
end
|
15
|
-
|
16
|
-
def freeze
|
17
|
-
@hash.freeze
|
18
|
-
super
|
19
|
-
end
|
20
|
-
|
21
|
-
def each(&block)
|
22
|
-
@hash.values.each(&block)
|
23
|
-
end
|
24
|
-
|
25
|
-
def set!(header)
|
26
|
-
@hash[header.name] = header
|
27
|
-
self
|
28
|
-
end
|
29
|
-
|
30
|
-
def add!(header)
|
31
|
-
existing = @hash[header.name]
|
32
|
-
if existing
|
33
|
-
if existing.respond_to?(:merge)
|
34
|
-
set!(existing.merge(header))
|
35
|
-
else
|
36
|
-
raise "Unmergeable header '#{header.name}' already exists"
|
37
|
-
end
|
38
|
-
else
|
39
|
-
set!(header)
|
40
|
-
end
|
41
|
-
self
|
42
|
-
end
|
43
|
-
|
44
|
-
%i(set add).each do |name|
|
45
|
-
define_method name do |header|
|
46
|
-
dup.send("#{name}!", header)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
alias_method :<<, :add!
|
51
|
-
|
52
|
-
class << self
|
53
|
-
def register(klass)
|
54
|
-
(@registered ||= {})[klass.const_get(:NAME)] = klass
|
55
|
-
end
|
56
|
-
|
57
|
-
def header_class(name)
|
58
|
-
(@registered || {})[name]
|
59
|
-
end
|
60
|
-
|
61
|
-
def Header(name)
|
62
|
-
klass = Class.new do
|
63
|
-
def name
|
64
|
-
self.class.const_get(:NAME)
|
65
|
-
end
|
66
|
-
|
67
|
-
def self.inherited(base)
|
68
|
-
Headers.register(base)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
Headers.const_set("#{name.tr('-', '_').classify}Header", klass)
|
72
|
-
klass.const_set(:NAME, name)
|
73
|
-
klass
|
74
|
-
end
|
75
|
-
|
76
|
-
def ListHeader(name)
|
77
|
-
klass = Header(name)
|
78
|
-
klass.class_eval do
|
79
|
-
attr_reader :values
|
80
|
-
|
81
|
-
def initialize(values)
|
82
|
-
@values = values
|
83
|
-
end
|
84
|
-
|
85
|
-
def merge(other)
|
86
|
-
self.class.new(*(@values + other.values))
|
87
|
-
end
|
88
|
-
|
89
|
-
def to_s
|
90
|
-
@values.map(&:to_s).join(', ')
|
91
|
-
end
|
92
|
-
end
|
93
|
-
klass
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
class Raw
|
98
|
-
attr_reader :name, :value
|
99
|
-
|
100
|
-
def initialize(name, value)
|
101
|
-
@name = name
|
102
|
-
@value = value
|
103
|
-
end
|
104
|
-
|
105
|
-
def to_s
|
106
|
-
@value
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
Dir[File.join(__dir__, 'headers', '*.rb')].each { |f| require f }
|
data/lib/xenon/headers/accept.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'xenon/headers'
|
2
|
-
require 'xenon/parsers/header_rules'
|
3
|
-
require 'xenon/parsers/media_type'
|
4
|
-
|
5
|
-
module Xenon
|
6
|
-
class Headers
|
7
|
-
# http://tools.ietf.org/html/rfc7231#section-5.3.2
|
8
|
-
class Accept < ListHeader 'Accept'
|
9
|
-
def initialize(*media_ranges)
|
10
|
-
super(media_ranges.sort_by.with_index { |mr, i| [mr, -i] }.reverse!)
|
11
|
-
end
|
12
|
-
|
13
|
-
alias_method :media_ranges, :values
|
14
|
-
|
15
|
-
def self.parse(s)
|
16
|
-
tree = Parsers::AcceptHeader.new.parse(s)
|
17
|
-
Parsers::AcceptHeaderTransform.new.apply(tree)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
module Parsers
|
23
|
-
class AcceptHeader < Parslet::Parser
|
24
|
-
include HeaderRules, MediaTypeRules
|
25
|
-
rule(:accept) { (media_range >> (list_sep >> media_range).repeat).as(:accept) }
|
26
|
-
root(:accept)
|
27
|
-
end
|
28
|
-
|
29
|
-
class AcceptHeaderTransform < MediaTypeTransform
|
30
|
-
rule(accept: sequence(:mr)) { Headers::Accept.new(*mr) }
|
31
|
-
rule(accept: simple(:mr)) { Headers::Accept.new(mr) }
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
require 'xenon/headers'
|
2
|
-
require 'xenon/parsers/header_rules'
|
3
|
-
|
4
|
-
module Xenon
|
5
|
-
class CharsetRange
|
6
|
-
attr_reader :charset, :q
|
7
|
-
|
8
|
-
DEFAULT_Q = 1.0
|
9
|
-
|
10
|
-
def initialize(charset, q = DEFAULT_Q)
|
11
|
-
@charset = charset
|
12
|
-
@q = Float(q) || DEFAULT_Q
|
13
|
-
end
|
14
|
-
|
15
|
-
def <=>(other)
|
16
|
-
@q <=> other.q
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_s
|
20
|
-
s = @charset.dup
|
21
|
-
s << "; q=#{@q}" if @q != DEFAULT_Q
|
22
|
-
s
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class Headers
|
27
|
-
# http://tools.ietf.org/html/rfc7231#section-5.3.3
|
28
|
-
class AcceptCharset < ListHeader 'Accept-Charset'
|
29
|
-
def initialize(*charset_ranges)
|
30
|
-
super(charset_ranges.sort_by.with_index { |mr, i| [mr, -i] }.reverse!)
|
31
|
-
end
|
32
|
-
|
33
|
-
alias_method :charset_ranges, :values
|
34
|
-
|
35
|
-
def self.parse(s)
|
36
|
-
tree = Parsers::AcceptCharsetHeader.new.parse(s)
|
37
|
-
Parsers::AcceptCharsetHeaderTransform.new.apply(tree)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
module Parsers
|
43
|
-
class AcceptCharsetHeader < Parslet::Parser
|
44
|
-
include HeaderRules
|
45
|
-
rule(:charset) { token.as(:charset) >> sp? }
|
46
|
-
rule(:wildcard) { str('*').as(:charset) >> sp? }
|
47
|
-
rule(:charset_range) { (charset | wildcard) >> weight.maybe }
|
48
|
-
rule(:accept_charset) { (charset_range >> (list_sep >> charset_range).repeat).as(:accept_charset) }
|
49
|
-
root(:accept_charset)
|
50
|
-
end
|
51
|
-
|
52
|
-
class AcceptCharsetHeaderTransform < HeaderTransform
|
53
|
-
rule(charset: simple(:c), q: simple(:q)) { CharsetRange.new(c, q) }
|
54
|
-
rule(charset: simple(:c)) { CharsetRange.new(c) }
|
55
|
-
rule(accept_charset: sequence(:cr)) { Headers::AcceptCharset.new(*cr) }
|
56
|
-
rule(accept_charset: simple(:cr)) { Headers::AcceptCharset.new(cr) }
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
require 'xenon/headers'
|
2
|
-
require 'xenon/parsers/header_rules'
|
3
|
-
|
4
|
-
module Xenon
|
5
|
-
class ContentCodingRange
|
6
|
-
attr_reader :coding, :q
|
7
|
-
|
8
|
-
DEFAULT_Q = 1.0
|
9
|
-
|
10
|
-
def initialize(coding, q = DEFAULT_Q)
|
11
|
-
@coding = coding
|
12
|
-
@q = Float(q) || DEFAULT_Q
|
13
|
-
end
|
14
|
-
|
15
|
-
def <=>(other)
|
16
|
-
@q <=> other.q
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_s
|
20
|
-
s = @coding.dup
|
21
|
-
s << "; q=#{@q}" if @q != DEFAULT_Q
|
22
|
-
s
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class Headers
|
27
|
-
# http://tools.ietf.org/html/rfc7231#section-5.3.4
|
28
|
-
class AcceptEncoding < ListHeader 'Accept-Encoding'
|
29
|
-
def initialize(*coding_ranges)
|
30
|
-
super(coding_ranges.sort_by.with_index { |mr, i| [mr, -i] }.reverse!)
|
31
|
-
end
|
32
|
-
|
33
|
-
alias_method :coding_ranges, :values
|
34
|
-
|
35
|
-
def self.parse(s)
|
36
|
-
tree = Parsers::AcceptEncodingHeader.new.parse(s)
|
37
|
-
Parsers::AcceptEncodingHeaderTransform.new.apply(tree)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
module Parsers
|
43
|
-
class AcceptEncodingHeader < Parslet::Parser
|
44
|
-
include HeaderRules
|
45
|
-
%w(identity compress x-compress deflate gzip x-gzip).each do |c|
|
46
|
-
rule(c.tr('-', '_').to_sym) { str(c).as(:coding) >> sp? }
|
47
|
-
end
|
48
|
-
rule(:coding) { compress | x_compress | deflate | gzip | x_gzip }
|
49
|
-
rule(:wildcard) { str('*').as(:coding) >> sp? }
|
50
|
-
rule(:coding_range) { (coding | identity | wildcard) >> weight.maybe }
|
51
|
-
rule(:accept_encoding) { (coding_range >> (list_sep >> coding_range).repeat).maybe.as(:accept_encoding) }
|
52
|
-
root(:accept_encoding)
|
53
|
-
end
|
54
|
-
|
55
|
-
class AcceptEncodingHeaderTransform < HeaderTransform
|
56
|
-
rule(coding: simple(:c), q: simple(:q)) { ContentCodingRange.new(c, q) }
|
57
|
-
rule(coding: simple(:c)) { ContentCodingRange.new(c) }
|
58
|
-
rule(accept_encoding: sequence(:er)) { Headers::AcceptEncoding.new(*er) }
|
59
|
-
rule(accept_encoding: simple(:cc)) { Headers::AcceptEncoding.new(cc) }
|
60
|
-
rule(accept_encoding: nil) { Headers::AcceptEncoding.new }
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
require 'xenon/headers'
|
2
|
-
require 'xenon/parsers/header_rules'
|
3
|
-
|
4
|
-
module Xenon
|
5
|
-
class LanguageRange
|
6
|
-
attr_reader :language, :q
|
7
|
-
|
8
|
-
DEFAULT_Q = 1.0
|
9
|
-
|
10
|
-
def initialize(language, q = DEFAULT_Q)
|
11
|
-
@language = language
|
12
|
-
@q = Float(q) || DEFAULT_Q
|
13
|
-
end
|
14
|
-
|
15
|
-
def <=>(other)
|
16
|
-
@q <=> other.q
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_s
|
20
|
-
s = @language.dup
|
21
|
-
s << "; q=#{@q}" if @q != DEFAULT_Q
|
22
|
-
s
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class Headers
|
27
|
-
# http://tools.ietf.org/html/rfc7231#section-5.3.5
|
28
|
-
class AcceptLanguage < ListHeader 'Accept-Language'
|
29
|
-
def initialize(*language_ranges)
|
30
|
-
super(language_ranges.sort_by.with_index { |mr, i| [mr, -i] }.reverse!)
|
31
|
-
end
|
32
|
-
|
33
|
-
alias_method :language_ranges, :values
|
34
|
-
|
35
|
-
def self.parse(s)
|
36
|
-
tree = Parsers::AcceptLanguageHeader.new.parse(s)
|
37
|
-
Parsers::AcceptLanguageHeaderTransform.new.apply(tree)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
module Parsers
|
43
|
-
class AcceptLanguageHeader < Parslet::Parser
|
44
|
-
include HeaderRules
|
45
|
-
rule(:language) { (alpha.repeat(1, 8) >> (str('-') >> alphanum.repeat(1, 8)).maybe).as(:language) >> sp? }
|
46
|
-
rule(:wildcard) { str('*').as(:language) >> sp? }
|
47
|
-
rule(:language_range) { (language | wildcard) >> weight.maybe }
|
48
|
-
rule(:accept_language) { (language_range >> (list_sep >> language_range).repeat).as(:accept_language) }
|
49
|
-
root(:accept_language)
|
50
|
-
end
|
51
|
-
|
52
|
-
class AcceptLanguageHeaderTransform < HeaderTransform
|
53
|
-
rule(language: simple(:e), q: simple(:q)) { LanguageRange.new(e, q) }
|
54
|
-
rule(language: simple(:e)) { LanguageRange.new(e) }
|
55
|
-
rule(accept_language: sequence(:lr)) { Headers::AcceptLanguage.new(*lr) }
|
56
|
-
rule(accept_language: simple(:lr)) { Headers::AcceptLanguage.new(lr) }
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|