xenon-routing 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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