xenon-routing 0.0.4 → 0.0.5

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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/{xenon-routing/lib → lib}/xenon/api.rb +20 -11
  3. data/{xenon-routing/lib → lib}/xenon/marshallers.rb +24 -14
  4. data/{xenon-routing/lib → lib}/xenon/request.rb +10 -2
  5. data/{xenon-routing/lib → lib}/xenon/response.rb +0 -0
  6. data/{xenon-routing/lib → lib}/xenon/routing.rb +0 -0
  7. data/{xenon-routing/lib → lib}/xenon/routing/context.rb +0 -0
  8. data/{xenon-routing/lib → lib}/xenon/routing/directives.rb +1 -0
  9. data/{xenon-routing/lib → lib}/xenon/routing/header_directives.rb +0 -0
  10. data/lib/xenon/routing/marshalling_directives.rb +24 -0
  11. data/{xenon-routing/lib → lib}/xenon/routing/method_directives.rb +10 -4
  12. data/{xenon-routing/lib → lib}/xenon/routing/param_directives.rb +0 -0
  13. data/{xenon-routing/lib → lib}/xenon/routing/path_directives.rb +0 -0
  14. data/{xenon-routing/lib → lib}/xenon/routing/route_directives.rb +0 -0
  15. data/{xenon-routing/lib → lib}/xenon/routing/security_directives.rb +6 -0
  16. data/{xenon-routing/lib → lib}/xenon/routing_version.rb +0 -0
  17. data/{xenon-http/spec → spec}/spec_helper.rb +0 -0
  18. data/{xenon-routing/xenon-routing.gemspec → xenon-routing.gemspec} +2 -2
  19. metadata +25 -80
  20. data/.codeclimate.yml +0 -18
  21. data/.gitignore +0 -25
  22. data/.rspec +0 -3
  23. data/.travis.yml +0 -6
  24. data/Gemfile +0 -20
  25. data/Guardfile +0 -16
  26. data/LICENSE +0 -22
  27. data/README.md +0 -116
  28. data/Rakefile +0 -40
  29. data/VERSION +0 -1
  30. data/examples/hello_world/config.ru +0 -3
  31. data/examples/hello_world/hello_world.rb +0 -27
  32. data/xenon-http/lib/xenon/auth.rb +0 -63
  33. data/xenon-http/lib/xenon/errors.rb +0 -5
  34. data/xenon-http/lib/xenon/etag.rb +0 -48
  35. data/xenon-http/lib/xenon/headers.rb +0 -112
  36. data/xenon-http/lib/xenon/headers/accept.rb +0 -34
  37. data/xenon-http/lib/xenon/headers/accept_charset.rb +0 -59
  38. data/xenon-http/lib/xenon/headers/accept_encoding.rb +0 -63
  39. data/xenon-http/lib/xenon/headers/accept_language.rb +0 -59
  40. data/xenon-http/lib/xenon/headers/authorization.rb +0 -50
  41. data/xenon-http/lib/xenon/headers/cache_control.rb +0 -56
  42. data/xenon-http/lib/xenon/headers/content_type.rb +0 -23
  43. data/xenon-http/lib/xenon/headers/if_match.rb +0 -53
  44. data/xenon-http/lib/xenon/headers/if_modified_since.rb +0 -22
  45. data/xenon-http/lib/xenon/headers/if_none_match.rb +0 -53
  46. data/xenon-http/lib/xenon/headers/if_range.rb +0 -45
  47. data/xenon-http/lib/xenon/headers/if_unmodified_since.rb +0 -22
  48. data/xenon-http/lib/xenon/headers/user_agent.rb +0 -65
  49. data/xenon-http/lib/xenon/headers/www_authenticate.rb +0 -71
  50. data/xenon-http/lib/xenon/http.rb +0 -7
  51. data/xenon-http/lib/xenon/http_version.rb +0 -3
  52. data/xenon-http/lib/xenon/media_type.rb +0 -162
  53. data/xenon-http/lib/xenon/parsers/basic_rules.rb +0 -86
  54. data/xenon-http/lib/xenon/parsers/header_rules.rb +0 -60
  55. data/xenon-http/lib/xenon/parsers/media_type.rb +0 -53
  56. data/xenon-http/lib/xenon/quoted_string.rb +0 -20
  57. data/xenon-http/spec/xenon/etag_spec.rb +0 -19
  58. data/xenon-http/spec/xenon/headers/accept_charset_spec.rb +0 -31
  59. data/xenon-http/spec/xenon/headers/accept_encoding_spec.rb +0 -40
  60. data/xenon-http/spec/xenon/headers/accept_language_spec.rb +0 -33
  61. data/xenon-http/spec/xenon/headers/accept_spec.rb +0 -54
  62. data/xenon-http/spec/xenon/headers/authorization_spec.rb +0 -47
  63. data/xenon-http/spec/xenon/headers/cache_control_spec.rb +0 -64
  64. data/xenon-http/spec/xenon/headers/if_match_spec.rb +0 -73
  65. data/xenon-http/spec/xenon/headers/if_modified_since_spec.rb +0 -19
  66. data/xenon-http/spec/xenon/headers/if_none_match_spec.rb +0 -79
  67. data/xenon-http/spec/xenon/headers/if_range_spec.rb +0 -45
  68. data/xenon-http/spec/xenon/headers/if_unmodified_since_spec.rb +0 -19
  69. data/xenon-http/spec/xenon/headers/user_agent_spec.rb +0 -67
  70. data/xenon-http/spec/xenon/headers/www_authenticate_spec.rb +0 -43
  71. data/xenon-http/spec/xenon/media_type_spec.rb +0 -267
  72. data/xenon-http/xenon-http.gemspec +0 -25
  73. data/xenon-routing/spec/spec_helper.rb +0 -94
  74. data/xenon.gemspec +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 385808aff014a3ce0b190e485996e21566ba4a96
4
- data.tar.gz: 8230baa459671431db3a9728b1df184606b2a8d2
3
+ metadata.gz: cb288967fc9c8037e293c38a4a2c2a79d8b041eb
4
+ data.tar.gz: 0909342647be6e9b87b7c93798807bcea0616342
5
5
  SHA512:
6
- metadata.gz: b902c768fb0dc9dfec74cef1426a1fb7eef41c5be1be85717d60d16918282a2c1fbe6ee4d8f1763f01fcb1efd6df76c8b36f295183ee10e3a0554bd1cf461508
7
- data.tar.gz: fdbeec5753727366d84cf827456c09f68ee3a6d55a4cd2375fc23418ca79cf5fc5423c7952d7962a20aa12480b66b01e2234713eead71768981790e6d40d59d3
6
+ metadata.gz: d2fbf928ab206470ec7e41d4af82cd9062ffba745d1afcad5d44bef9b9c41a9c8fe055ae59c8927358f0e4b56c1c690996bcf02530893fb9d71242c87b00329b
7
+ data.tar.gz: f65bec15d95854ce7be553057a5de95605b14d44149997e2718186a1328df4023b7d01e7ab02e77b5bfc36ec2b41b5a3f1cf61268adfd3b061366bfbc8d1fbac
@@ -14,9 +14,13 @@ module Xenon
14
14
  (@marshallers.nil? || @marshallers.empty?) ? DEFAULT_MARSHALLERS : @marshallers
15
15
  end
16
16
 
17
- def select_marshaller(media_ranges)
17
+ def request_marshaller(content_type)
18
+ marshallers.find { |m| m.unmarshal?(content_type.media_type) }
19
+ end
20
+
21
+ def response_marshaller(media_ranges)
18
22
  weighted = marshallers.map do |marshaller|
19
- media_range = media_ranges.find { |media_range| marshaller.marshal_to?(media_range) }
23
+ media_range = media_ranges.find { |media_range| marshaller.marshal?(media_range) }
20
24
  [marshaller, media_range ? media_range.q : 0]
21
25
  end
22
26
  weighted.select { |_, q| q > 0 }.sort_by { |_, q| q }.map { |m, _| m }.last
@@ -47,11 +51,11 @@ module Xenon
47
51
  @context = Routing::Context.new(Request.new(Rack::Request.new(env)), Response.new)
48
52
 
49
53
  accept = @context.request.header('Accept')
50
- marshaller = accept ? self.class.select_marshaller(accept.media_ranges) : self.class.marshallers.first
54
+ response_marshaller = accept ? self.class.response_marshaller(accept.media_ranges) : self.class.marshallers.first
51
55
 
52
- catch (:complete) do
56
+ catch :complete do
53
57
  begin
54
- if marshaller
58
+ if response_marshaller
55
59
  self.class.routes.each do |route|
56
60
  name, args, block = route
57
61
  route_block = proc { instance_eval(&block) }
@@ -66,10 +70,15 @@ module Xenon
66
70
  end
67
71
  end
68
72
 
69
- marshaller ||= self.class.marshallers.first
70
- resp = @context.response.copy(
71
- headers: @context.response.headers.set(Headers::ContentType.new(marshaller.content_type)),
72
- body: marshaller.marshal(@context.response.body))
73
+ response_marshaller ||= self.class.marshallers.first
74
+ headers = @context.response.headers.set(Headers::ContentType.new(response_marshaller.content_type))
75
+ if @context.request.allow_response_body?
76
+ body = response_marshaller.marshal(@context.response.body)
77
+ else
78
+ # TODO: Suppress the Content-Lenth heder
79
+ body = []
80
+ end
81
+ resp = @context.response.copy(headers: headers, body: body)
73
82
  [resp.status, resp.headers.map { |h| [h.name, h.to_s] }.to_h, resp.body]
74
83
  end
75
84
 
@@ -97,8 +106,8 @@ module Xenon
97
106
  when :header
98
107
  fail 400, "Missing required header: #{rejection[:required]}"
99
108
  when :method
100
- supported = rejections.take_while { |r| r.reason == :method }.map { |r| r[:supported].upcase }
101
- fail 405, "Supported methods: #{supported.join(", ")}"
109
+ supported = rejections.take_while { |r| r.reason == :method }.flat_map { |r| r[:supported] }
110
+ fail 405, "Supported methods: #{supported.map(&:upcase).join(", ")}"
102
111
  when :unauthorized
103
112
  if rejection[:scheme]
104
113
  challenge = Headers::Challenge.new(rejection[:scheme], rejection.info.except(:scheme))
@@ -1,25 +1,39 @@
1
1
  require 'xenon/media_type'
2
2
 
3
3
  module Xenon
4
- class JsonMarshaller
5
- def media_type
6
- MediaType::JSON
7
- end
8
-
4
+ module Marshaller
9
5
  def content_type
10
6
  media_type.with_charset(Encoding::UTF_8)
11
7
  end
12
8
 
13
- def marshal_to?(media_range)
9
+ def unmarshal?(media_type)
10
+ media_type == self.media_type
11
+ end
12
+
13
+ def marshal?(media_range)
14
14
  media_range =~ media_type
15
15
  end
16
+ end
17
+
18
+ class JsonMarshaller
19
+ include Marshaller
20
+
21
+ def media_type
22
+ MediaType::JSON
23
+ end
16
24
 
17
25
  def marshal(obj)
18
26
  [obj.to_json]
19
27
  end
28
+
29
+ def unmarshal(body, as:)
30
+ as ? as.new.from_json(body.read) : JSON.load(body)
31
+ end
20
32
  end
21
33
 
22
34
  class XmlMarshaller
35
+ include Marshaller
36
+
23
37
  def initialize
24
38
  gem 'builder'
25
39
  require 'active_support/core_ext/array/conversions'
@@ -32,17 +46,13 @@ module Xenon
32
46
  MediaType::XML
33
47
  end
34
48
 
35
- def content_type
36
- media_type.with_charset(Encoding::UTF_8)
37
- end
38
-
39
- def marshal_to?(media_range)
40
- media_range =~ media_type
41
- end
42
-
43
49
  def marshal(obj)
44
50
  raise "#{obj.class} does not support #to_xml" unless obj.respond_to?(:to_xml)
45
51
  [obj.to_xml]
46
52
  end
53
+
54
+ def unmarshal(body, as:)
55
+ as.new.from_xml(body.read)
56
+ end
47
57
  end
48
58
  end
@@ -23,18 +23,26 @@ module Xenon
23
23
  end
24
24
 
25
25
  def header(name)
26
- snake_name = name.to_s.tr('-', '_')
27
- value = @rack_req.env['HTTP_' + snake_name.upcase]
26
+ snake_name = name.to_s.tr('-', '_').upcase
27
+ value = @rack_req.env['HTTP_' + snake_name] || @rack_req.env[snake_name]
28
28
  return nil if value.nil?
29
29
 
30
30
  klass = Xenon::Headers.header_class(name)
31
31
  klass ? klass.parse(value) : Xenon::Headers::Raw.new(name, value)
32
32
  end
33
33
 
34
+ def body
35
+ @rack_req.body
36
+ end
37
+
34
38
  def copy(changes = {})
35
39
  r = dup
36
40
  changes.each { |k, v| r.instance_variable_set("@#{k}", v.freeze) }
37
41
  r
38
42
  end
43
+
44
+ def allow_response_body?
45
+ request_method != :head
46
+ end
39
47
  end
40
48
  end
@@ -5,6 +5,7 @@ module Xenon
5
5
  module Directives
6
6
  include RouteDirectives
7
7
  include HeaderDirectives
8
+ include MarshallingDirectives
8
9
  include MethodDirectives
9
10
  include ParamDirectives
10
11
  include PathDirectives
@@ -0,0 +1,24 @@
1
+ require 'xenon/routing/route_directives'
2
+
3
+ module Xenon
4
+ module Routing
5
+ module MarshallingDirectives
6
+ include RouteDirectives
7
+
8
+ def body(as: nil)
9
+ extract_request do |request|
10
+ if as == IO
11
+ yield request.body
12
+ elsif as == String
13
+ yield request.body.read
14
+ else
15
+ content_type = request.header('Content-Type')
16
+ marshaller = Xenon::API.request_marshaller(content_type.content_type) # yuk
17
+ yield marshaller.unmarshal(request.body, as: as)
18
+ end
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -5,17 +5,23 @@ module Xenon
5
5
  module MethodDirectives
6
6
  include RouteDirectives
7
7
 
8
- def request_method(method)
8
+ def request_method(*methods)
9
9
  extract_request do |request|
10
- if request.request_method == method
10
+ if methods.include?(request.request_method)
11
11
  yield
12
12
  else
13
- reject Rejection.new(:method, { supported: method })
13
+ reject Rejection.new(:method, { supported: methods })
14
14
  end
15
15
  end
16
16
  end
17
17
 
18
- %i(delete get head options patch post put).each do |method|
18
+ def get
19
+ request_method :get, :head do
20
+ yield
21
+ end
22
+ end
23
+
24
+ %i(delete head options patch post put).each do |method|
19
25
  define_method(method) do |&inner|
20
26
  request_method(method, &inner)
21
27
  end
@@ -15,6 +15,12 @@ module Xenon
15
15
  end
16
16
  end
17
17
 
18
+ def optional_authenticate(authenticator)
19
+ extract_request(authenticator) do |user|
20
+ yield user
21
+ end
22
+ end
23
+
18
24
  def authorize(check)
19
25
  if check.respond_to?(:call)
20
26
  extract_request(check) do |authorized|
File without changes
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Xenon::ROUTING_VERSION
9
9
  spec.authors = ['Greg Beech']
10
10
  spec.email = ['greg@gregbeech.com']
11
- spec.summary = %q{An HTTP framework for building RESTful APIs.}
12
- spec.description = %q{Provides a model for the HTTP protocol and a tree-based routing syntax.}
11
+ spec.summary = %q{Tree-based routing to build RESTful APIs on Rack.}
12
+ spec.description = %q{Provides tree-based routing syntax for building RESTful APIs.}
13
13
  spec.homepage = 'https://github.com/gregbeech/xenon'
14
14
  spec.license = 'MIT'
15
15
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xenon-routing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Beech
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-17 00:00:00.000000000 Z
11
+ date: 2016-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -30,92 +30,38 @@ dependencies:
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 0.0.4
33
+ version: 0.0.5
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 0.0.4
41
- description: Provides a model for the HTTP protocol and a tree-based routing syntax.
40
+ version: 0.0.5
41
+ description: Provides tree-based routing syntax for building RESTful APIs.
42
42
  email:
43
43
  - greg@gregbeech.com
44
44
  executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
- - ".codeclimate.yml"
49
- - ".gitignore"
50
- - ".rspec"
51
- - ".travis.yml"
52
- - Gemfile
53
- - Guardfile
54
- - LICENSE
55
- - README.md
56
- - Rakefile
57
- - VERSION
58
- - examples/hello_world/config.ru
59
- - examples/hello_world/hello_world.rb
60
- - xenon-http/lib/xenon/auth.rb
61
- - xenon-http/lib/xenon/errors.rb
62
- - xenon-http/lib/xenon/etag.rb
63
- - xenon-http/lib/xenon/headers.rb
64
- - xenon-http/lib/xenon/headers/accept.rb
65
- - xenon-http/lib/xenon/headers/accept_charset.rb
66
- - xenon-http/lib/xenon/headers/accept_encoding.rb
67
- - xenon-http/lib/xenon/headers/accept_language.rb
68
- - xenon-http/lib/xenon/headers/authorization.rb
69
- - xenon-http/lib/xenon/headers/cache_control.rb
70
- - xenon-http/lib/xenon/headers/content_type.rb
71
- - xenon-http/lib/xenon/headers/if_match.rb
72
- - xenon-http/lib/xenon/headers/if_modified_since.rb
73
- - xenon-http/lib/xenon/headers/if_none_match.rb
74
- - xenon-http/lib/xenon/headers/if_range.rb
75
- - xenon-http/lib/xenon/headers/if_unmodified_since.rb
76
- - xenon-http/lib/xenon/headers/user_agent.rb
77
- - xenon-http/lib/xenon/headers/www_authenticate.rb
78
- - xenon-http/lib/xenon/http.rb
79
- - xenon-http/lib/xenon/http_version.rb
80
- - xenon-http/lib/xenon/media_type.rb
81
- - xenon-http/lib/xenon/parsers/basic_rules.rb
82
- - xenon-http/lib/xenon/parsers/header_rules.rb
83
- - xenon-http/lib/xenon/parsers/media_type.rb
84
- - xenon-http/lib/xenon/quoted_string.rb
85
- - xenon-http/spec/spec_helper.rb
86
- - xenon-http/spec/xenon/etag_spec.rb
87
- - xenon-http/spec/xenon/headers/accept_charset_spec.rb
88
- - xenon-http/spec/xenon/headers/accept_encoding_spec.rb
89
- - xenon-http/spec/xenon/headers/accept_language_spec.rb
90
- - xenon-http/spec/xenon/headers/accept_spec.rb
91
- - xenon-http/spec/xenon/headers/authorization_spec.rb
92
- - xenon-http/spec/xenon/headers/cache_control_spec.rb
93
- - xenon-http/spec/xenon/headers/if_match_spec.rb
94
- - xenon-http/spec/xenon/headers/if_modified_since_spec.rb
95
- - xenon-http/spec/xenon/headers/if_none_match_spec.rb
96
- - xenon-http/spec/xenon/headers/if_range_spec.rb
97
- - xenon-http/spec/xenon/headers/if_unmodified_since_spec.rb
98
- - xenon-http/spec/xenon/headers/user_agent_spec.rb
99
- - xenon-http/spec/xenon/headers/www_authenticate_spec.rb
100
- - xenon-http/spec/xenon/media_type_spec.rb
101
- - xenon-http/xenon-http.gemspec
102
- - xenon-routing/lib/xenon/api.rb
103
- - xenon-routing/lib/xenon/marshallers.rb
104
- - xenon-routing/lib/xenon/request.rb
105
- - xenon-routing/lib/xenon/response.rb
106
- - xenon-routing/lib/xenon/routing.rb
107
- - xenon-routing/lib/xenon/routing/context.rb
108
- - xenon-routing/lib/xenon/routing/directives.rb
109
- - xenon-routing/lib/xenon/routing/header_directives.rb
110
- - xenon-routing/lib/xenon/routing/method_directives.rb
111
- - xenon-routing/lib/xenon/routing/param_directives.rb
112
- - xenon-routing/lib/xenon/routing/path_directives.rb
113
- - xenon-routing/lib/xenon/routing/route_directives.rb
114
- - xenon-routing/lib/xenon/routing/security_directives.rb
115
- - xenon-routing/lib/xenon/routing_version.rb
116
- - xenon-routing/spec/spec_helper.rb
117
- - xenon-routing/xenon-routing.gemspec
118
- - xenon.gemspec
48
+ - lib/xenon/api.rb
49
+ - lib/xenon/marshallers.rb
50
+ - lib/xenon/request.rb
51
+ - lib/xenon/response.rb
52
+ - lib/xenon/routing.rb
53
+ - lib/xenon/routing/context.rb
54
+ - lib/xenon/routing/directives.rb
55
+ - lib/xenon/routing/header_directives.rb
56
+ - lib/xenon/routing/marshalling_directives.rb
57
+ - lib/xenon/routing/method_directives.rb
58
+ - lib/xenon/routing/param_directives.rb
59
+ - lib/xenon/routing/path_directives.rb
60
+ - lib/xenon/routing/route_directives.rb
61
+ - lib/xenon/routing/security_directives.rb
62
+ - lib/xenon/routing_version.rb
63
+ - spec/spec_helper.rb
64
+ - xenon-routing.gemspec
119
65
  homepage: https://github.com/gregbeech/xenon
120
66
  licenses:
121
67
  - MIT
@@ -136,10 +82,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
82
  version: '0'
137
83
  requirements: []
138
84
  rubyforge_project:
139
- rubygems_version: 2.4.8
85
+ rubygems_version: 2.5.1
140
86
  signing_key:
141
87
  specification_version: 4
142
- summary: An HTTP framework for building RESTful APIs.
143
- test_files:
144
- - xenon-routing/spec/spec_helper.rb
88
+ summary: Tree-based routing to build RESTful APIs on Rack.
89
+ test_files: []
145
90
  has_rdoc:
@@ -1,18 +0,0 @@
1
- # For more details, see here:
2
- # http://docs.codeclimate.com/article/289-configuring-your-repository-via-codeclimate-yml#platform
3
-
4
- # For a list of all available engines, see here:
5
- # http://docs.codeclimate.com/article/296-engines-available-engines
6
-
7
- engines:
8
- rubocop:
9
- enabled: true
10
-
11
- ratings:
12
- paths:
13
- - lib/**/*
14
-
15
- exclude_paths:
16
- - examples/**/*
17
- - spec/**/*
18
- - vendor/**/*
data/.gitignore DELETED
@@ -1,25 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .ruby-version
4
- .ruby-gemset
5
- Gemfile.lock
6
- /.config
7
- /coverage/
8
- /InstalledFiles
9
- /pkg/
10
- /spec/reports/
11
- /test/tmp/
12
- /test/version_tmp/
13
- /tmp/
14
-
15
- ## Documentation cache and generated files:
16
- /.yardoc/
17
- /_yardoc/
18
- /doc/
19
- /rdoc/
20
-
21
- ## Environment normalisation:
22
- /.bundle/
23
- /lib/bundler/man/
24
- .ruby-gemset
25
- .ruby-version