xenon 0.0.2 → 0.0.3
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
 - data/.codeclimate.yml +18 -0
 - data/.gitignore +2 -0
 - data/.travis.yml +6 -0
 - data/Gemfile +10 -0
 - data/Guardfile +0 -32
 - data/README.md +59 -5
 - data/examples/hello_world/config.ru +3 -0
 - data/examples/hello_world/hello_world.rb +17 -0
 - data/lib/xenon.rb +62 -49
 - data/lib/xenon/auth.rb +63 -0
 - data/lib/xenon/errors.rb +1 -0
 - data/lib/xenon/etag.rb +48 -0
 - data/lib/xenon/headers.rb +2 -4
 - data/lib/xenon/headers/accept.rb +3 -2
 - data/lib/xenon/headers/accept_charset.rb +5 -5
 - data/lib/xenon/headers/accept_encoding.rb +5 -5
 - data/lib/xenon/headers/accept_language.rb +5 -5
 - data/lib/xenon/headers/authorization.rb +7 -53
 - data/lib/xenon/headers/cache_control.rb +3 -3
 - data/lib/xenon/headers/content_type.rb +1 -1
 - data/lib/xenon/headers/if_match.rb +53 -0
 - data/lib/xenon/headers/if_modified_since.rb +22 -0
 - data/lib/xenon/headers/if_none_match.rb +53 -0
 - data/lib/xenon/headers/if_range.rb +45 -0
 - data/lib/xenon/headers/if_unmodified_since.rb +22 -0
 - data/lib/xenon/headers/user_agent.rb +65 -0
 - data/lib/xenon/headers/www_authenticate.rb +70 -0
 - data/lib/xenon/media_type.rb +24 -2
 - data/lib/xenon/parsers/basic_rules.rb +38 -7
 - data/lib/xenon/parsers/header_rules.rb +49 -3
 - data/lib/xenon/parsers/media_type.rb +4 -3
 - data/lib/xenon/quoted_string.rb +11 -1
 - data/lib/xenon/routing/directives.rb +14 -0
 - data/lib/xenon/routing/header_directives.rb +32 -0
 - data/lib/xenon/routing/method_directives.rb +26 -0
 - data/lib/xenon/routing/param_directives.rb +22 -0
 - data/lib/xenon/routing/path_directives.rb +37 -0
 - data/lib/xenon/routing/route_directives.rb +51 -0
 - data/lib/xenon/routing/security_directives.rb +20 -0
 - data/lib/xenon/version.rb +1 -1
 - data/spec/spec_helper.rb +3 -0
 - data/spec/xenon/etag_spec.rb +19 -0
 - data/spec/xenon/headers/if_match_spec.rb +73 -0
 - data/spec/xenon/headers/if_modified_since_spec.rb +19 -0
 - data/spec/xenon/headers/if_none_match_spec.rb +79 -0
 - data/spec/xenon/headers/if_range_spec.rb +45 -0
 - data/spec/xenon/headers/if_unmodified_since_spec.rb +19 -0
 - data/spec/xenon/headers/user_agent_spec.rb +67 -0
 - data/spec/xenon/headers/www_authenticate_spec.rb +43 -0
 - data/xenon.gemspec +4 -3
 - metadata +60 -10
 - data/lib/xenon/routing.rb +0 -133
 
    
        data/lib/xenon/errors.rb
    CHANGED
    
    
    
        data/lib/xenon/etag.rb
    ADDED
    
    | 
         @@ -0,0 +1,48 @@ 
     | 
|
| 
      
 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
    CHANGED
    
    | 
         @@ -106,9 +106,7 @@ module Xenon 
     | 
|
| 
       106 
106 
     | 
    
         
             
                    @value
         
     | 
| 
       107 
107 
     | 
    
         
             
                  end
         
     | 
| 
       108 
108 
     | 
    
         
             
                end
         
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
                [:Accept, :AcceptCharset, :AcceptEncoding, :CacheControl, :ContentType].each do |sym|
         
     | 
| 
       111 
     | 
    
         
            -
                  autoload sym, "xenon/headers/#{sym.to_s.underscore}"
         
     | 
| 
       112 
     | 
    
         
            -
                end
         
     | 
| 
       113 
109 
     | 
    
         
             
              end
         
     | 
| 
       114 
110 
     | 
    
         
             
            end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
            Dir[File.join(__dir__, 'headers', '*.rb')].each { |f| require f }
         
     | 
    
        data/lib/xenon/headers/accept.rb
    CHANGED
    
    | 
         @@ -1,4 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'xenon/headers'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'xenon/parsers/header_rules'
         
     | 
| 
       2 
3 
     | 
    
         
             
            require 'xenon/parsers/media_type'
         
     | 
| 
       3 
4 
     | 
    
         | 
| 
       4 
5 
     | 
    
         
             
            module Xenon
         
     | 
| 
         @@ -20,8 +21,8 @@ module Xenon 
     | 
|
| 
       20 
21 
     | 
    
         | 
| 
       21 
22 
     | 
    
         
             
              module Parsers
         
     | 
| 
       22 
23 
     | 
    
         
             
                class AcceptHeader < Parslet::Parser
         
     | 
| 
       23 
     | 
    
         
            -
                  include MediaTypeRules
         
     | 
| 
       24 
     | 
    
         
            -
                  rule(:accept) { (media_range >> ( 
     | 
| 
      
 24 
     | 
    
         
            +
                  include HeaderRules, MediaTypeRules
         
     | 
| 
      
 25 
     | 
    
         
            +
                  rule(:accept) { (media_range >> (list_sep >> media_range).repeat).as(:accept) }
         
     | 
| 
       25 
26 
     | 
    
         
             
                  root(:accept)
         
     | 
| 
       26 
27 
     | 
    
         
             
                end
         
     | 
| 
       27 
28 
     | 
    
         | 
| 
         @@ -41,17 +41,17 @@ module Xenon 
     | 
|
| 
       41 
41 
     | 
    
         | 
| 
       42 
42 
     | 
    
         
             
              module Parsers
         
     | 
| 
       43 
43 
     | 
    
         
             
                class AcceptCharsetHeader < Parslet::Parser
         
     | 
| 
       44 
     | 
    
         
            -
                  include  
     | 
| 
      
 44 
     | 
    
         
            +
                  include HeaderRules
         
     | 
| 
       45 
45 
     | 
    
         
             
                  rule(:charset) { token.as(:charset) >> sp? }
         
     | 
| 
       46 
46 
     | 
    
         
             
                  rule(:wildcard) { str('*').as(:charset) >> sp? }
         
     | 
| 
       47 
47 
     | 
    
         
             
                  rule(:charset_range) { (charset | wildcard) >> weight.maybe }
         
     | 
| 
       48 
     | 
    
         
            -
                  rule(:accept_charset) { (charset_range >> ( 
     | 
| 
      
 48 
     | 
    
         
            +
                  rule(:accept_charset) { (charset_range >> (list_sep >> charset_range).repeat).as(:accept_charset) }
         
     | 
| 
       49 
49 
     | 
    
         
             
                  root(:accept_charset)
         
     | 
| 
       50 
50 
     | 
    
         
             
                end
         
     | 
| 
       51 
51 
     | 
    
         | 
| 
       52 
     | 
    
         
            -
                class AcceptCharsetHeaderTransform <  
     | 
| 
       53 
     | 
    
         
            -
                  rule(charset: simple(:c), q: simple(:q)) { CharsetRange.new(c 
     | 
| 
       54 
     | 
    
         
            -
                  rule(charset: simple(:c)) { CharsetRange.new(c 
     | 
| 
      
 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 
55 
     | 
    
         
             
                  rule(accept_charset: sequence(:cr)) { Headers::AcceptCharset.new(*cr) }
         
     | 
| 
       56 
56 
     | 
    
         
             
                  rule(accept_charset: simple(:cr)) { Headers::AcceptCharset.new(cr) }
         
     | 
| 
       57 
57 
     | 
    
         
             
                end
         
     | 
| 
         @@ -41,20 +41,20 @@ module Xenon 
     | 
|
| 
       41 
41 
     | 
    
         | 
| 
       42 
42 
     | 
    
         
             
              module Parsers
         
     | 
| 
       43 
43 
     | 
    
         
             
                class AcceptEncodingHeader < Parslet::Parser
         
     | 
| 
       44 
     | 
    
         
            -
                  include  
     | 
| 
      
 44 
     | 
    
         
            +
                  include HeaderRules
         
     | 
| 
       45 
45 
     | 
    
         
             
                  %w(identity compress x-compress deflate gzip x-gzip).each do |c|
         
     | 
| 
       46 
46 
     | 
    
         
             
                    rule(c.tr('-', '_').to_sym) { str(c).as(:coding) >> sp? }
         
     | 
| 
       47 
47 
     | 
    
         
             
                  end
         
     | 
| 
       48 
48 
     | 
    
         
             
                  rule(:coding) { compress | x_compress | deflate | gzip | x_gzip }
         
     | 
| 
       49 
49 
     | 
    
         
             
                  rule(:wildcard) { str('*').as(:coding) >> sp? }
         
     | 
| 
       50 
50 
     | 
    
         
             
                  rule(:coding_range) { (coding | identity | wildcard) >> weight.maybe }
         
     | 
| 
       51 
     | 
    
         
            -
                  rule(:accept_encoding) { (coding_range >> ( 
     | 
| 
      
 51 
     | 
    
         
            +
                  rule(:accept_encoding) { (coding_range >> (list_sep >> coding_range).repeat).maybe.as(:accept_encoding) }
         
     | 
| 
       52 
52 
     | 
    
         
             
                  root(:accept_encoding)
         
     | 
| 
       53 
53 
     | 
    
         
             
                end
         
     | 
| 
       54 
54 
     | 
    
         | 
| 
       55 
     | 
    
         
            -
                class AcceptEncodingHeaderTransform <  
     | 
| 
       56 
     | 
    
         
            -
                  rule(coding: simple(:c), q: simple(:q)) { ContentCodingRange.new(c 
     | 
| 
       57 
     | 
    
         
            -
                  rule(coding: simple(:c)) { ContentCodingRange.new(c 
     | 
| 
      
 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 
58 
     | 
    
         
             
                  rule(accept_encoding: sequence(:er)) { Headers::AcceptEncoding.new(*er) }
         
     | 
| 
       59 
59 
     | 
    
         
             
                  rule(accept_encoding: simple(:cc)) { Headers::AcceptEncoding.new(cc) }
         
     | 
| 
       60 
60 
     | 
    
         
             
                  rule(accept_encoding: nil) { Headers::AcceptEncoding.new }
         
     | 
| 
         @@ -41,17 +41,17 @@ module Xenon 
     | 
|
| 
       41 
41 
     | 
    
         | 
| 
       42 
42 
     | 
    
         
             
              module Parsers
         
     | 
| 
       43 
43 
     | 
    
         
             
                class AcceptLanguageHeader < Parslet::Parser
         
     | 
| 
       44 
     | 
    
         
            -
                  include  
     | 
| 
      
 44 
     | 
    
         
            +
                  include HeaderRules
         
     | 
| 
       45 
45 
     | 
    
         
             
                  rule(:language) { (alpha.repeat(1, 8) >> (str('-') >> alphanum.repeat(1, 8)).maybe).as(:language) >> sp? }
         
     | 
| 
       46 
46 
     | 
    
         
             
                  rule(:wildcard) { str('*').as(:language) >> sp? }
         
     | 
| 
       47 
47 
     | 
    
         
             
                  rule(:language_range) { (language | wildcard) >> weight.maybe }
         
     | 
| 
       48 
     | 
    
         
            -
                  rule(:accept_language) { (language_range >> ( 
     | 
| 
      
 48 
     | 
    
         
            +
                  rule(:accept_language) { (language_range >> (list_sep >> language_range).repeat).as(:accept_language) }
         
     | 
| 
       49 
49 
     | 
    
         
             
                  root(:accept_language)
         
     | 
| 
       50 
50 
     | 
    
         
             
                end
         
     | 
| 
       51 
51 
     | 
    
         | 
| 
       52 
     | 
    
         
            -
                class AcceptLanguageHeaderTransform <  
     | 
| 
       53 
     | 
    
         
            -
                  rule(language: simple(:e), q: simple(:q)) { LanguageRange.new(e 
     | 
| 
       54 
     | 
    
         
            -
                  rule(language: simple(:e)) { LanguageRange.new(e 
     | 
| 
      
 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 
55 
     | 
    
         
             
                  rule(accept_language: sequence(:lr)) { Headers::AcceptLanguage.new(*lr) }
         
     | 
| 
       56 
56 
     | 
    
         
             
                  rule(accept_language: simple(:lr)) { Headers::AcceptLanguage.new(lr) }
         
     | 
| 
       57 
57 
     | 
    
         
             
                end
         
     | 
| 
         @@ -1,51 +1,9 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'base64'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'xenon/auth'
         
     | 
| 
       2 
3 
     | 
    
         
             
            require 'xenon/headers'
         
     | 
| 
       3 
4 
     | 
    
         
             
            require 'xenon/parsers/header_rules'
         
     | 
| 
       4 
     | 
    
         
            -
            require 'xenon/quoted_string'
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            module Xenon
         
     | 
| 
       7 
     | 
    
         
            -
              class BasicCredentials
         
     | 
| 
       8 
     | 
    
         
            -
                attr_reader :username, :password
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                def initialize(username, password)
         
     | 
| 
       11 
     | 
    
         
            -
                  @username = username
         
     | 
| 
       12 
     | 
    
         
            -
                  @password = password
         
     | 
| 
       13 
     | 
    
         
            -
                end
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
                def token
         
     | 
| 
       16 
     | 
    
         
            -
                  Base64.strict_encode64("#{@username}:#{@password}")
         
     | 
| 
       17 
     | 
    
         
            -
                end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
                def self.decode(s)
         
     | 
| 
       20 
     | 
    
         
            -
                  str = Base64.strict_decode64(s)
         
     | 
| 
       21 
     | 
    
         
            -
                  username, password = str.split(':', 2)
         
     | 
| 
       22 
     | 
    
         
            -
                  BasicCredentials.new(username, password)
         
     | 
| 
       23 
     | 
    
         
            -
                end
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
                def to_s
         
     | 
| 
       26 
     | 
    
         
            -
                  "Basic #{token}"
         
     | 
| 
       27 
     | 
    
         
            -
                end
         
     | 
| 
       28 
     | 
    
         
            -
              end
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
              class GenericCredentials
         
     | 
| 
       31 
     | 
    
         
            -
                using QuotedString
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
                attr_reader :scheme, :token, :params
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
                def initialize(scheme, token: nil, params: {})
         
     | 
| 
       36 
     | 
    
         
            -
                  @scheme = scheme
         
     | 
| 
       37 
     | 
    
         
            -
                  @token = token
         
     | 
| 
       38 
     | 
    
         
            -
                  @params = params
         
     | 
| 
       39 
     | 
    
         
            -
                end
         
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
                def to_s
         
     | 
| 
       42 
     | 
    
         
            -
                  s = @scheme.dup
         
     | 
| 
       43 
     | 
    
         
            -
                  s << ' ' << @token if @token
         
     | 
| 
       44 
     | 
    
         
            -
                  s << ' ' << @params.map { |n, v| "#{n}=#{v.quote}" }.join(', ')
         
     | 
| 
       45 
     | 
    
         
            -
                  s
         
     | 
| 
       46 
     | 
    
         
            -
                end
         
     | 
| 
       47 
     | 
    
         
            -
              end
         
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
7 
     | 
    
         
             
              class Headers
         
     | 
| 
       50 
8 
     | 
    
         
             
                # http://tools.ietf.org/html/rfc7235#section-4.2
         
     | 
| 
       51 
9 
     | 
    
         
             
                class Authorization < Header 'Authorization'
         
     | 
| 
         @@ -58,6 +16,8 @@ module Xenon 
     | 
|
| 
       58 
16 
     | 
    
         
             
                  def self.parse(s)
         
     | 
| 
       59 
17 
     | 
    
         
             
                    tree = Parsers::AuthorizationHeader.new.parse(s)
         
     | 
| 
       60 
18 
     | 
    
         
             
                    Parsers::AuthorizationHeaderTransform.new.apply(tree)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  rescue Parslet::ParseFailed
         
     | 
| 
      
 20 
     | 
    
         
            +
                    raise Xenon::ParseError.new("Invalid Authorization header (#{s}).")
         
     | 
| 
       61 
21 
     | 
    
         
             
                  end
         
     | 
| 
       62 
22 
     | 
    
         | 
| 
       63 
23 
     | 
    
         
             
                  def to_s
         
     | 
| 
         @@ -68,25 +28,19 @@ module Xenon 
     | 
|
| 
       68 
28 
     | 
    
         | 
| 
       69 
29 
     | 
    
         
             
              module Parsers
         
     | 
| 
       70 
30 
     | 
    
         
             
                class AuthorizationHeader < Parslet::Parser
         
     | 
| 
       71 
     | 
    
         
            -
                  include  
     | 
| 
       72 
     | 
    
         
            -
                  rule(:token68) { ((alpha | digit | match(/[\-\._~\+\/]/)) >> str('=').repeat).repeat(1).as(:token) }
         
     | 
| 
       73 
     | 
    
         
            -
                  rule(:auth_scheme) { token.as(:auth_scheme) }
         
     | 
| 
       74 
     | 
    
         
            -
                  rule(:name) { token.as(:name) }
         
     | 
| 
       75 
     | 
    
         
            -
                  rule(:value) { token.as(:value) }
         
     | 
| 
       76 
     | 
    
         
            -
                  rule(:auth_param) { (name >> bws >> str('=') >> bws >> (token | quoted_string).as(:value)).as(:auth_param) } 
         
     | 
| 
       77 
     | 
    
         
            -
                  rule(:auth_params) { (auth_param.maybe >> (ows >> comma >> ows >> auth_param).repeat).as(:auth_params) }
         
     | 
| 
      
 31 
     | 
    
         
            +
                  include AuthHeaderRules
         
     | 
| 
       78 
32 
     | 
    
         
             
                  rule(:credentials) { auth_scheme >> sp >> (token68 | auth_params) }
         
     | 
| 
       79 
33 
     | 
    
         
             
                  rule(:authorization) { credentials.as(:authorization) }
         
     | 
| 
       80 
34 
     | 
    
         
             
                  root(:authorization)
         
     | 
| 
       81 
35 
     | 
    
         
             
                end
         
     | 
| 
       82 
36 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
                class AuthorizationHeaderTransform <  
     | 
| 
      
 37 
     | 
    
         
            +
                class AuthorizationHeaderTransform < HeaderTransform
         
     | 
| 
       84 
38 
     | 
    
         
             
                  rule(auth_param: { name: simple(:n), value: simple(:v) }) { [n, v] }
         
     | 
| 
       85 
39 
     | 
    
         
             
                  rule(auth_params: subtree(:x)) { { foo: x } }
         
     | 
| 
       86 
     | 
    
         
            -
                  rule(auth_scheme: simple(:s), token: simple(:t)) { 
     | 
| 
      
 40 
     | 
    
         
            +
                  rule(auth_scheme: simple(:s), token: simple(:t)) {
         
     | 
| 
       87 
41 
     | 
    
         
             
                    case s
         
     | 
| 
       88 
42 
     | 
    
         
             
                    when 'Basic' then BasicCredentials.decode(t)
         
     | 
| 
       89 
     | 
    
         
            -
                    else GenericCredentials.new(s, token: t) 
     | 
| 
      
 43 
     | 
    
         
            +
                    else GenericCredentials.new(s, token: t)
         
     | 
| 
       90 
44 
     | 
    
         
             
                    end
         
     | 
| 
       91 
45 
     | 
    
         
             
                  }
         
     | 
| 
       92 
46 
     | 
    
         
             
                  rule(auth_scheme: simple(:s), auth_params: subtree(:p)) { GenericCredentials.new(s, params: Hash[p]) }
         
     | 
| 
         @@ -38,15 +38,15 @@ module Xenon 
     | 
|
| 
       38 
38 
     | 
    
         | 
| 
       39 
39 
     | 
    
         
             
              module Parsers
         
     | 
| 
       40 
40 
     | 
    
         
             
                class CacheControlHeader < Parslet::Parser
         
     | 
| 
       41 
     | 
    
         
            -
                  include  
     | 
| 
      
 41 
     | 
    
         
            +
                  include HeaderRules
         
     | 
| 
       42 
42 
     | 
    
         
             
                  rule(:name) { token.as(:name) }
         
     | 
| 
       43 
43 
     | 
    
         
             
                  rule(:value) { str('=') >> (token | quoted_string).as(:value) }
         
     | 
| 
       44 
44 
     | 
    
         
             
                  rule(:directive) { (name >> value.maybe).as(:directive) >> sp? }
         
     | 
| 
       45 
     | 
    
         
            -
                  rule(:cache_control) { (directive >> ( 
     | 
| 
      
 45 
     | 
    
         
            +
                  rule(:cache_control) { (directive >> (list_sep >> directive).repeat).as(:cache_control) }
         
     | 
| 
       46 
46 
     | 
    
         
             
                  root(:cache_control)
         
     | 
| 
       47 
47 
     | 
    
         
             
                end
         
     | 
| 
       48 
48 
     | 
    
         | 
| 
       49 
     | 
    
         
            -
                class CacheControlHeaderTransform <  
     | 
| 
      
 49 
     | 
    
         
            +
                class CacheControlHeaderTransform < HeaderTransform
         
     | 
| 
       50 
50 
     | 
    
         
             
                  rule(directive: { name: simple(:n), value: simple(:v) }) { CacheDirective.new(n, v) }
         
     | 
| 
       51 
51 
     | 
    
         
             
                  rule(directive: { name: simple(:n) }) { CacheDirective.new(n) }
         
     | 
| 
       52 
52 
     | 
    
         
             
                  rule(cache_control: sequence(:d)) { Headers::CacheControl.new(*d) }
         
     | 
| 
         @@ -0,0 +1,53 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'xenon/headers'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'xenon/parsers/header_rules'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'xenon/errors'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'xenon/etag'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Xenon
         
     | 
| 
      
 7 
     | 
    
         
            +
              class Headers
         
     | 
| 
      
 8 
     | 
    
         
            +
                # http://tools.ietf.org/html/rfc7232#section-3.1
         
     | 
| 
      
 9 
     | 
    
         
            +
                class IfMatch < ListHeader 'If-Match'
         
     | 
| 
      
 10 
     | 
    
         
            +
                  def initialize(*etags)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    super(etags)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  alias_method :etags, :values
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def self.wildcard
         
     | 
| 
      
 17 
     | 
    
         
            +
                    new
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def self.parse(s)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    tree = Parsers::IfMatchHeader.new.parse(s)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    Parsers::IfMatchHeaderTransform.new.apply(tree)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def wildcard?
         
     | 
| 
      
 26 
     | 
    
         
            +
                    etags.empty?
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def merge(other)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    raise Xenon::ProtocolError.new('Cannot merge wildcard headers') if wildcard? || other.wildcard?
         
     | 
| 
      
 31 
     | 
    
         
            +
                    super
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def to_s
         
     | 
| 
      
 35 
     | 
    
         
            +
                    wildcard? ? '*' : super
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              module Parsers
         
     | 
| 
      
 41 
     | 
    
         
            +
                class IfMatchHeader < Parslet::Parser
         
     | 
| 
      
 42 
     | 
    
         
            +
                  include ETagHeaderRules
         
     | 
| 
      
 43 
     | 
    
         
            +
                  rule(:if_match) { (wildcard | (etag >> (list_sep >> etag).repeat)).as(:if_match) }
         
     | 
| 
      
 44 
     | 
    
         
            +
                  root(:if_match)
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                class IfMatchHeaderTransform < ETagHeaderTransform
         
     | 
| 
      
 48 
     | 
    
         
            +
                  rule(if_match: { wildcard: simple(:w) }) { Headers::IfMatch.new }
         
     | 
| 
      
 49 
     | 
    
         
            +
                  rule(if_match: sequence(:et)) { Headers::IfMatch.new(*et) }
         
     | 
| 
      
 50 
     | 
    
         
            +
                  rule(if_match: simple(:et)) { Headers::IfMatch.new(et) }
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'xenon/headers'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Xenon
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Headers
         
     | 
| 
      
 5 
     | 
    
         
            +
                # http://tools.ietf.org/html/rfc7232#section-3.3
         
     | 
| 
      
 6 
     | 
    
         
            +
                class IfModifiedSince < Header 'If-Modified-Since'
         
     | 
| 
      
 7 
     | 
    
         
            +
                  attr_reader :date
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def initialize(date)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @date = date
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def self.parse(s)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    new(Time.httpdate(s))
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def to_s
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @date.httpdate
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,53 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'xenon/headers'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'xenon/parsers/header_rules'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'xenon/errors'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'xenon/etag'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Xenon
         
     | 
| 
      
 7 
     | 
    
         
            +
              class Headers
         
     | 
| 
      
 8 
     | 
    
         
            +
                # http://tools.ietf.org/html/rfc7232#section-3.2
         
     | 
| 
      
 9 
     | 
    
         
            +
                class IfNoneMatch < ListHeader 'If-None-Match'
         
     | 
| 
      
 10 
     | 
    
         
            +
                  def initialize(*etags)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    super(etags)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  alias_method :etags, :values
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def self.wildcard
         
     | 
| 
      
 17 
     | 
    
         
            +
                    new
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def self.parse(s)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    tree = Parsers::IfNoneMatchHeader.new.parse(s)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    Parsers::IfNoneMatchHeaderTransform.new.apply(tree)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def wildcard?
         
     | 
| 
      
 26 
     | 
    
         
            +
                    etags.empty?
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def merge(other)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    raise Xenon::ProtocolError.new('Cannot merge wildcard headers') if wildcard? || other.wildcard?
         
     | 
| 
      
 31 
     | 
    
         
            +
                    super
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def to_s
         
     | 
| 
      
 35 
     | 
    
         
            +
                    wildcard? ? '*' : super
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              module Parsers
         
     | 
| 
      
 41 
     | 
    
         
            +
                class IfNoneMatchHeader < Parslet::Parser
         
     | 
| 
      
 42 
     | 
    
         
            +
                  include ETagHeaderRules
         
     | 
| 
      
 43 
     | 
    
         
            +
                  rule(:if_none_match) { (wildcard | (etag >> (list_sep >> etag).repeat)).as(:if_none_match) }
         
     | 
| 
      
 44 
     | 
    
         
            +
                  root(:if_none_match)
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                class IfNoneMatchHeaderTransform < ETagHeaderTransform
         
     | 
| 
      
 48 
     | 
    
         
            +
                  rule(if_none_match: { wildcard: simple(:w) }) { Headers::IfNoneMatch.new }
         
     | 
| 
      
 49 
     | 
    
         
            +
                  rule(if_none_match: sequence(:et)) { Headers::IfNoneMatch.new(*et) }
         
     | 
| 
      
 50 
     | 
    
         
            +
                  rule(if_none_match: simple(:et)) { Headers::IfNoneMatch.new(et) }
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,45 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'xenon/headers'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'xenon/parsers/header_rules'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'xenon/errors'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'xenon/etag'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Xenon
         
     | 
| 
      
 7 
     | 
    
         
            +
              class Headers
         
     | 
| 
      
 8 
     | 
    
         
            +
                # http://tools.ietf.org/html/rfc7233#section-3.2
         
     | 
| 
      
 9 
     | 
    
         
            +
                class IfRange < Header 'If-Range'
         
     | 
| 
      
 10 
     | 
    
         
            +
                  attr_reader :date, :etag
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def initialize(value)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    case value
         
     | 
| 
      
 14 
     | 
    
         
            +
                    when Time, DateTime, Date then @date = value
         
     | 
| 
      
 15 
     | 
    
         
            +
                    when ETag then @etag = value
         
     | 
| 
      
 16 
     | 
    
         
            +
                    when String then @etag = ETag.parse(value)
         
     | 
| 
      
 17 
     | 
    
         
            +
                    else raise ArgumentError, 'Value must be a time or an etag.'
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    raise ProtocolError, 'If-Range headers must use strong ETags.' if @etag && @etag.weak?
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def self.parse(s)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    tree = Parsers::IfRangeHeader.new.parse(s)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    Parsers::IfRangeHeaderTransform.new.apply(tree)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def to_s
         
     | 
| 
      
 29 
     | 
    
         
            +
                    @etag ? @etag.to_s : @date.httpdate
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              module Parsers
         
     | 
| 
      
 35 
     | 
    
         
            +
                class IfRangeHeader < Parslet::Parser
         
     | 
| 
      
 36 
     | 
    
         
            +
                  include ETagHeaderRules
         
     | 
| 
      
 37 
     | 
    
         
            +
                  rule(:if_range) { (etag | http_date).as(:if_range) }
         
     | 
| 
      
 38 
     | 
    
         
            +
                  root(:if_range)
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                class IfRangeHeaderTransform < ETagHeaderTransform
         
     | 
| 
      
 42 
     | 
    
         
            +
                  rule(if_range: simple(:v)) { Headers::IfRange.new(v) }
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
            end
         
     |