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/media_type.rb
DELETED
@@ -1,162 +0,0 @@
|
|
1
|
-
require 'xenon/errors'
|
2
|
-
require 'xenon/parsers/media_type'
|
3
|
-
|
4
|
-
module Xenon
|
5
|
-
|
6
|
-
# A media type.
|
7
|
-
#
|
8
|
-
# @see ContentType
|
9
|
-
# @see MediaRange
|
10
|
-
class MediaType
|
11
|
-
attr_reader :type, :subtype, :params
|
12
|
-
|
13
|
-
# Initializes a new instance of MediaType.
|
14
|
-
#
|
15
|
-
# @param type [String] The main type, e.g. 'application'.
|
16
|
-
# @param subtype [String] The subtype, e.g. 'json'.
|
17
|
-
# @param params [Hash] Any params for the media type; don't use 'q' or 'charset'.
|
18
|
-
def initialize(type, subtype, params = {})
|
19
|
-
@type = type
|
20
|
-
@subtype = subtype
|
21
|
-
@params = params
|
22
|
-
end
|
23
|
-
|
24
|
-
# Parses a media type.
|
25
|
-
#
|
26
|
-
# @param s [String] The media type string.
|
27
|
-
# @return [MediaType] The media type.
|
28
|
-
def self.parse(s)
|
29
|
-
tree = Parsers::MediaType.new.parse(s)
|
30
|
-
Parsers::MediaTypeTransform.new.apply(tree)
|
31
|
-
rescue Parslet::ParseFailed
|
32
|
-
raise Xenon::ParseError.new("Invalid media type (#{s}).")
|
33
|
-
end
|
34
|
-
|
35
|
-
%w(application audio image message multipart text video).each do |type|
|
36
|
-
define_method "#{type}?" do
|
37
|
-
@type == type
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def experimental?
|
42
|
-
@subtype.start_with?('x.') # not x- see http://tools.ietf.org/html/rfc6838#section-3.4
|
43
|
-
end
|
44
|
-
|
45
|
-
def personal?
|
46
|
-
@subtype.start_with?('prs.')
|
47
|
-
end
|
48
|
-
|
49
|
-
def vendor?
|
50
|
-
@subtype.start_with?('vnd.')
|
51
|
-
end
|
52
|
-
|
53
|
-
%w(ber der fastinfoset json wbxml xml zip).each do |format|
|
54
|
-
define_method "#{format}?" do
|
55
|
-
@subtype == format || @subtype.end_with?("+#{format}")
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
# Creates a {MediaRange} using this media type with a quality factor.
|
60
|
-
#
|
61
|
-
# @param q [Numeric] A value between 1.0 (most desirable) and 0.0 (not acceptable).
|
62
|
-
# @return [MediaRange] The media range.
|
63
|
-
def with_q(q)
|
64
|
-
MediaRange.new(self, q)
|
65
|
-
end
|
66
|
-
|
67
|
-
# Creates a {ContentType} using this media type with a charset.
|
68
|
-
#
|
69
|
-
# @param charset [String] The desired charset, e.g. 'utf-8'.
|
70
|
-
# @return [ContentType] The content type.
|
71
|
-
def with_charset(charset)
|
72
|
-
ContentType.new(self, charset)
|
73
|
-
end
|
74
|
-
|
75
|
-
def to_s
|
76
|
-
"#{@type}/#{@subtype}" << @params.map { |n, v| v ? "; #{n}=#{v}" : "; #{n}" }.join
|
77
|
-
end
|
78
|
-
|
79
|
-
JSON = MediaType.new('application', 'json')
|
80
|
-
XML = MediaType.new('application', 'xml')
|
81
|
-
end
|
82
|
-
|
83
|
-
# A content type.
|
84
|
-
class ContentType
|
85
|
-
attr_reader :media_type, :charset
|
86
|
-
|
87
|
-
DEFAULT_CHARSET = 'utf-8' # historically iso-8859-1 but see http://tools.ietf.org/html/rfc7231#appendix-B
|
88
|
-
|
89
|
-
def initialize(media_type, charset = DEFAULT_CHARSET)
|
90
|
-
@media_type = media_type
|
91
|
-
@charset = charset
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.parse(s)
|
95
|
-
media_type = MediaType.parse(s)
|
96
|
-
charset = media_type.params.delete('charset') || DEFAULT_CHARSET
|
97
|
-
ContentType.new(media_type, charset)
|
98
|
-
end
|
99
|
-
|
100
|
-
def to_s
|
101
|
-
"#{@media_type}; charset=#{@charset}"
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
class MediaRange
|
106
|
-
include Comparable
|
107
|
-
|
108
|
-
DEFAULT_Q = 1.0
|
109
|
-
|
110
|
-
attr_reader :type, :subtype, :q, :params
|
111
|
-
|
112
|
-
def initialize(type, subtype, params = {})
|
113
|
-
@type = type
|
114
|
-
@subtype = subtype
|
115
|
-
@q = Float(params.delete('q')) rescue DEFAULT_Q
|
116
|
-
@params = params
|
117
|
-
end
|
118
|
-
|
119
|
-
def self.parse(s)
|
120
|
-
tree = Parsers::MediaRange.new.parse(s)
|
121
|
-
Parsers::MediaTypeTransform.new.apply(tree)
|
122
|
-
rescue Parslet::ParseFailed
|
123
|
-
raise Xenon::ParseError.new("Invalid media range (#{s})")
|
124
|
-
end
|
125
|
-
|
126
|
-
def <=>(other)
|
127
|
-
dt = compare_types(@type, other.type)
|
128
|
-
return dt if dt != 0
|
129
|
-
ds = compare_types(@subtype, other.subtype)
|
130
|
-
return ds if ds != 0
|
131
|
-
dp = params.size <=> other.params.size
|
132
|
-
return dp if dp != 0
|
133
|
-
@q <=> other.q
|
134
|
-
end
|
135
|
-
|
136
|
-
def =~(media_type)
|
137
|
-
(type == '*' || type == media_type.type) &&
|
138
|
-
(subtype == '*' || subtype == media_type.subtype) &&
|
139
|
-
params.all? { |n, v| media_type.params[n] == v }
|
140
|
-
end
|
141
|
-
|
142
|
-
alias_method :===, :=~
|
143
|
-
|
144
|
-
def to_s
|
145
|
-
s = "#{@type}/#{@subtype}"
|
146
|
-
s << @params.map { |n, v| v ? "; #{n}=#{v}" : "; #{n}" }.join
|
147
|
-
s << "; q=#{@q}" if @q != DEFAULT_Q
|
148
|
-
s
|
149
|
-
end
|
150
|
-
|
151
|
-
private
|
152
|
-
|
153
|
-
def compare_types(a, b)
|
154
|
-
if a == b then 0
|
155
|
-
elsif a == '*' then -1
|
156
|
-
elsif b == '*' then 1
|
157
|
-
else 0
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
require 'parslet'
|
2
|
-
|
3
|
-
module Xenon
|
4
|
-
module Parsers
|
5
|
-
|
6
|
-
# Parslet doesn't match sequence of sequences (i.e. [['foo', 'bar']]) as a sequence(:v) in transform
|
7
|
-
# rules so this is a little wrapper class that allows smuggling an array through the matcher rules,
|
8
|
-
# for example above would be [Tuple.new('foo', 'bar')], when no 'proper' class is required.
|
9
|
-
class Tuple
|
10
|
-
def initialize(*values)
|
11
|
-
@values = values
|
12
|
-
end
|
13
|
-
|
14
|
-
def to_a
|
15
|
-
@values
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
module BasicRules
|
20
|
-
include Parslet
|
21
|
-
|
22
|
-
# http://tools.ietf.org/html/rfc5234#appendix-B.1
|
23
|
-
rule(:alpha) { match(/[a-z]/i) }
|
24
|
-
rule(:bit) { match(/[01]/) }
|
25
|
-
rule(:char) { match(/[\u0001-\u007f]/) }
|
26
|
-
rule(:digit) { match(/[0-9]/) }
|
27
|
-
rule(:hexdig) { match(/[a-f0-9]/i)}
|
28
|
-
rule(:vchar) { match(/[\u0021-\u007e]/) }
|
29
|
-
rule(:alphanum) { alpha | digit }
|
30
|
-
|
31
|
-
rule(:sp) { str(' ') }
|
32
|
-
rule(:sp?) { sp.repeat }
|
33
|
-
rule(:htab) { str("\t") }
|
34
|
-
rule(:wsp) { sp | htab }
|
35
|
-
rule(:lwsp) { (crlf.maybe >> wsp).repeat }
|
36
|
-
|
37
|
-
rule(:cr) { str("\r") }
|
38
|
-
rule(:lf) { str("\n") }
|
39
|
-
rule(:crlf) { cr >> lf }
|
40
|
-
rule(:dquote) { str('"') }
|
41
|
-
|
42
|
-
# http://tools.ietf.org/html/rfc7230#section-3.2.3
|
43
|
-
rule(:ows) { wsp.repeat }
|
44
|
-
rule(:rws) { wsp.repeat(1) }
|
45
|
-
rule(:bws) { wsp.repeat }
|
46
|
-
|
47
|
-
# http://tools.ietf.org/html/rfc7230#section-3.2.6
|
48
|
-
rule(:tchar) { alpha | digit | match(/[!#\$%&'\*\+\-\.\^_`\|~]/) }
|
49
|
-
rule(:token) { tchar.repeat(1) }
|
50
|
-
|
51
|
-
# http://tools.ietf.org/html/rfc7231#section-7.1.1.1
|
52
|
-
rule(:day_name) { str('Mon') | str('Tue') | str('Wed') | str('Thu') | str('Fri') | str('Sat') | str('Sun') }
|
53
|
-
rule(:day) { digit.repeat(2) }
|
54
|
-
rule(:month) { (str('Jan') | str('Feb') | str('Mar') | str('Apr') | str('May') | str('Jun') | str('Jul') | str('Aug') | str('Sep') | str('Oct') | str('Nov') | str('Dec')) }
|
55
|
-
rule(:year) { digit.repeat(4) }
|
56
|
-
rule(:date1) { day >> sp >> month >> sp >> year }
|
57
|
-
rule(:gmt) { str('GMT') }
|
58
|
-
rule(:hour) { digit.repeat(2) }
|
59
|
-
rule(:minute) { digit.repeat(2) }
|
60
|
-
rule(:second) { digit.repeat(2) }
|
61
|
-
rule(:time_of_day) { hour >> str(':') >> minute >> str(':') >> second }
|
62
|
-
rule(:imf_fixdate) { day_name >> str(',') >> sp >> date1 >> sp >> time_of_day >> sp >> gmt }
|
63
|
-
rule(:day_name_l) { str('Monday') | str('Tuesday') | str('Wednesday') | str('Thursday') | str('Friday') | str('Saturday') | str('Sunday') }
|
64
|
-
rule(:year2) { digit.repeat(2) }
|
65
|
-
rule(:date2) { day >> str('-') >> month >> str('-') >> year2 }
|
66
|
-
rule(:rfc850_date) { day_name_l >> str(',') >> sp >> date2 >> sp >> time_of_day >> sp >> gmt }
|
67
|
-
rule(:day1) { sp >> digit }
|
68
|
-
rule(:date3) { month >> sp >> (day | day1) }
|
69
|
-
rule(:asctime_date) { day_name >> sp >> date3 >> sp >> time_of_day >> sp >> year }
|
70
|
-
rule(:obs_date) { rfc850_date | asctime_date }
|
71
|
-
rule(:http_date) { (imf_fixdate | obs_date).as(:http_date) }
|
72
|
-
|
73
|
-
# extras -- TODO: move these into header rules?
|
74
|
-
rule(:comma) { str(',') >> sp? }
|
75
|
-
rule(:semicolon) { str(';') >> sp? }
|
76
|
-
end
|
77
|
-
|
78
|
-
class BasicTransform < Parslet::Transform
|
79
|
-
rule(simple(:v)) { v.respond_to?(:str) ? v.str : v }
|
80
|
-
|
81
|
-
rule(quoted_string: simple(:qs)) { qs[1..-2].gsub(/\\(.)/, '\1') }
|
82
|
-
rule(http_date: simple(:str)) { Time.httpdate(str) }
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|
86
|
-
end
|
@@ -1,60 +0,0 @@
|
|
1
|
-
require 'xenon/quoted_string'
|
2
|
-
require 'xenon/parsers/basic_rules'
|
3
|
-
|
4
|
-
module Xenon
|
5
|
-
module Parsers
|
6
|
-
|
7
|
-
module HeaderRules
|
8
|
-
include Parslet, BasicRules
|
9
|
-
|
10
|
-
# http://tools.ietf.org/html/rfc7230#section-3.2.6
|
11
|
-
rule(:list_sep) { str(',') >> sp? }
|
12
|
-
rule(:param_sep) { str(';') >> sp? }
|
13
|
-
rule(:obs_text) { match(/[\u0080-\u00ff]/)}
|
14
|
-
rule(:qdtext) { htab | sp | match(/[\u0021\u0023-\u005b\u005d-\u007e]/) | obs_text }
|
15
|
-
rule(:quoted_pair) { str('\\') >> (htab | sp | vchar | obs_text) }
|
16
|
-
rule(:quoted_string) { (dquote >> (qdtext | quoted_pair).repeat >> dquote).as(:quoted_string) }
|
17
|
-
rule(:ctext) { htab | sp | match(/[\u0021-\u0027\u002a-\u005b\u005d-\u007e]/) | obs_text }
|
18
|
-
rule(:comment) { (str('(') >> (ctext | quoted_pair | comment).repeat >> str(')')).as(:comment) }
|
19
|
-
|
20
|
-
# http://tools.ietf.org/html/rfc7231#section-5.3.1
|
21
|
-
rule(:weight_value) { (digit >> (str('.') >> digit.repeat(0, 3)).maybe).as(:q) }
|
22
|
-
rule(:weight) { param_sep >> str('q') >> sp? >> str('=') >> sp? >> weight_value >> sp? }
|
23
|
-
end
|
24
|
-
|
25
|
-
module AuthHeaderRules
|
26
|
-
include Parslet, HeaderRules
|
27
|
-
|
28
|
-
rule(:token68) { ((alpha | digit | match(/[\-\._~\+\/]/)) >> str('=').repeat).repeat(1).as(:token) }
|
29
|
-
rule(:auth_scheme) { token.as(:auth_scheme) }
|
30
|
-
rule(:name) { token.as(:name) }
|
31
|
-
rule(:value) { token.as(:value) }
|
32
|
-
rule(:auth_param) { (name >> bws >> str('=') >> bws >> (token | quoted_string).as(:value)).as(:auth_param) }
|
33
|
-
rule(:auth_params) { (auth_param.maybe >> (ows >> comma >> ows >> auth_param).repeat).as(:auth_params) }
|
34
|
-
end
|
35
|
-
|
36
|
-
module ETagHeaderRules
|
37
|
-
include Parslet, HeaderRules
|
38
|
-
|
39
|
-
# http://tools.ietf.org/html/rfc7232#section-2.3
|
40
|
-
rule(:wildcard) { str('*').as(:wildcard) }
|
41
|
-
rule(:weak) { str('W/').as(:weak) }
|
42
|
-
rule(:etagc) { str('!') | match(/[\u0023-\u007e#-~]/) | obs_text }
|
43
|
-
rule(:opaque_tag) { dquote >> etagc.repeat.as(:opaque_tag) >> dquote }
|
44
|
-
rule(:etag) { (weak.maybe >> opaque_tag).as(:etag) }
|
45
|
-
end
|
46
|
-
|
47
|
-
class HeaderTransform < BasicTransform
|
48
|
-
using QuotedString
|
49
|
-
|
50
|
-
rule(quoted_string: simple(:qs)) { qs.unquote }
|
51
|
-
rule(comment: simple(:c)) { c.uncomment }
|
52
|
-
end
|
53
|
-
|
54
|
-
class ETagHeaderTransform < HeaderTransform
|
55
|
-
rule(etag: { opaque_tag: simple(:t), weak: simple(:w) }) { Xenon::ETag.new(t, weak: true) }
|
56
|
-
rule(etag: { opaque_tag: simple(:t) }) { Xenon::ETag.new(t) }
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
60
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'xenon/parsers/basic_rules'
|
2
|
-
|
3
|
-
module Xenon
|
4
|
-
module Parsers
|
5
|
-
|
6
|
-
# note this uses the rules from https://tools.ietf.org/html/rfc6838 not http://tools.ietf.org/html/rfc7231
|
7
|
-
# because the latter is slightly ambiguous, e.g. a token can include * so */json would parse correctly
|
8
|
-
module MediaTypeRules
|
9
|
-
include Parslet, BasicRules
|
10
|
-
|
11
|
-
rule(:restricted_name_first) { match(/[a-zA-Z0-9]/) }
|
12
|
-
rule(:restricted_name_chars) { match(/[a-zA-Z0-9!#\$&\-\^_\.\+]/).repeat(0, 126) }
|
13
|
-
rule(:restricted_name) { restricted_name_first >> restricted_name_chars }
|
14
|
-
|
15
|
-
rule(:type) { restricted_name.as(:type) }
|
16
|
-
rule(:slash) { str('/') }
|
17
|
-
rule(:subtype) { restricted_name.as(:subtype) >> sp? }
|
18
|
-
|
19
|
-
rule(:param_sep) { str(';') >> sp? }
|
20
|
-
rule(:param_name) { restricted_name.as(:param_name) >> sp? }
|
21
|
-
rule(:equals) { str('=') >> sp? }
|
22
|
-
rule(:param_value) { token.as(:param_value) >> sp? } # not quite correct but probably correct enough
|
23
|
-
rule(:param) { param_sep >> param_name >> (equals >> param_value).maybe >> sp? }
|
24
|
-
rule(:params) { param.repeat.as(:params) }
|
25
|
-
|
26
|
-
rule(:media_type) { (type >> slash >> subtype >> params).as(:media_type) >> sp? }
|
27
|
-
|
28
|
-
rule(:wildcard) { str('*') }
|
29
|
-
rule(:wild_media_range) { wildcard.as(:type) >> slash >> wildcard.as(:subtype) >> params }
|
30
|
-
rule(:root_media_range) { type >> slash >> (wildcard.as(:subtype) | subtype) >> params }
|
31
|
-
rule(:media_range) { (wild_media_range | root_media_range).as(:media_range) >> sp? }
|
32
|
-
end
|
33
|
-
|
34
|
-
class MediaType < Parslet::Parser
|
35
|
-
include MediaTypeRules
|
36
|
-
root(:media_type)
|
37
|
-
end
|
38
|
-
|
39
|
-
class MediaRange < Parslet::Parser
|
40
|
-
include MediaTypeRules
|
41
|
-
root(:media_range)
|
42
|
-
end
|
43
|
-
|
44
|
-
class MediaTypeTransform < Parslet::Transform
|
45
|
-
rule(param_name: simple(:n), param_value: simple(:v)) { [n.str, v.str] }
|
46
|
-
rule(param_name: simple(:n)) { [n.str, nil] }
|
47
|
-
rule(type: simple(:t), subtype: simple(:s), params: subtree(:p)) { { type: t.str, subtype: s.str, params: Hash[p] } }
|
48
|
-
rule(media_type: subtree(:mt)) { Xenon::MediaType.new(mt[:type], mt[:subtype], mt[:params])}
|
49
|
-
rule(media_range: subtree(:mr)) { Xenon::MediaRange.new(mr[:type], mr[:subtype], mr[:params])}
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
53
|
-
end
|
data/lib/xenon/quoted_string.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
module Xenon
|
2
|
-
module QuotedString
|
3
|
-
refine String do
|
4
|
-
def quote
|
5
|
-
qs = gsub(/([\\"])/, '\\\\\1')
|
6
|
-
self == qs ? self : %{"#{qs}"}
|
7
|
-
end
|
8
|
-
|
9
|
-
def unquote
|
10
|
-
qs = start_with?('"') && end_with?('"') ? self[1..-2] : self
|
11
|
-
qs.gsub(/\\(.)/, '\1')
|
12
|
-
end
|
13
|
-
|
14
|
-
def uncomment
|
15
|
-
qs = start_with?('(') && end_with?(')') ? self[1..-2] : self
|
16
|
-
qs.gsub(/\\(.)/, '\1')
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
Dir[File.join(__dir__, '*_directives.rb')].each { |f| require f }
|
2
|
-
|
3
|
-
module Xenon
|
4
|
-
module Routing
|
5
|
-
module Directives
|
6
|
-
include RouteDirectives
|
7
|
-
include HeaderDirectives
|
8
|
-
include MethodDirectives
|
9
|
-
include ParamDirectives
|
10
|
-
include PathDirectives
|
11
|
-
include SecurityDirectives
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'xenon/routing/route_directives'
|
2
|
-
|
3
|
-
module Xenon
|
4
|
-
module Routing
|
5
|
-
module HeaderDirectives
|
6
|
-
include RouteDirectives
|
7
|
-
|
8
|
-
def optional_header(name)
|
9
|
-
extract_request do |request|
|
10
|
-
yield request.header(name)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def header(name)
|
15
|
-
optional_header(name) do |value|
|
16
|
-
if value
|
17
|
-
yield value
|
18
|
-
else
|
19
|
-
reject Rejection.new(:header, { required: name })
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def respond_with_header(header)
|
25
|
-
map_response -> r { r.copy(headers: r.headers.add(header)) } do
|
26
|
-
yield
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'xenon/routing/route_directives'
|
2
|
-
|
3
|
-
module Xenon
|
4
|
-
module Routing
|
5
|
-
module MethodDirectives
|
6
|
-
include RouteDirectives
|
7
|
-
|
8
|
-
def request_method(method)
|
9
|
-
extract_request do |request|
|
10
|
-
if request.request_method == method
|
11
|
-
yield
|
12
|
-
else
|
13
|
-
reject Rejection.new(:method, { supported: method })
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
%i(delete get head options patch post put).each do |method|
|
19
|
-
define_method(method) do |&inner|
|
20
|
-
request_method(method, &inner)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|