moonrope 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ec14194988474a3b6e4e0d3e40ffafb64a3fb4c1
4
- data.tar.gz: 968649b6047917e0713c0510ed32d2c66d4265d9
2
+ SHA256:
3
+ metadata.gz: e34dcc98aecf5558f04b21b81aeb19c419597a21d7c736363ed681a322feee06
4
+ data.tar.gz: b4ad2c14aed545aefa3be780e8d0e778c75d0828d3426ebc022a3d540a05e023
5
5
  SHA512:
6
- metadata.gz: dbda03f158543eb581faf08fe4954ce4ac567bf03017e0e33dcef295da04b28d262eaa0038facc3e8c62e84f42fdd79f41580e571ba01a659a335c0ff564a1bf
7
- data.tar.gz: 64e355f2ef7a89bd545e951070737d2668de5a38c60013b1355c2277a4f0b02318e4d0e7223bd675e2a5364d2d1f9c887b30c3fb3730b9c170c8eddbaf432058
6
+ metadata.gz: 7395cad7eb23fe964de419d8daf4cfb9fbf4009160dd51e8bec84fe278301be830e822da463ddd139d02c47c0ca805f51d1273777419151a65c1b3168bc68ee0
7
+ data.tar.gz: 3bbd5d843bf9f608057374c147f056e4a16e1afa2f2928cc2bf99de51e1d274a59317d8524827150e7ffad00a5b208a9efa3edf9ebd037d25935fe596bf00925
@@ -1,17 +1,17 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- moonrope (2.0.0)
4
+ moonrope (2.0.2)
5
5
  deep_merge (~> 1.0)
6
- json (~> 1.7)
6
+ json
7
7
  rack (>= 1.4)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- deep_merge (1.0.1)
12
+ deep_merge (1.2.1)
13
13
  diff-lcs (1.2.5)
14
- json (1.8.3)
14
+ json (2.3.1)
15
15
  rack (1.5.2)
16
16
  rack-test (0.6.3)
17
17
  rack (>= 1.0)
@@ -35,7 +35,7 @@ PLATFORMS
35
35
  DEPENDENCIES
36
36
  moonrope!
37
37
  rack-test (~> 0)
38
- rake (~> 10.3)
38
+ rake
39
39
  rspec
40
40
  rspec-core
41
41
  rspec-expectations
@@ -44,4 +44,4 @@ DEPENDENCIES
44
44
  yard (~> 0.8)
45
45
 
46
46
  BUNDLED WITH
47
- 1.10.6
47
+ 1.17.2
@@ -48,6 +48,9 @@ module Moonrope
48
48
  # @return [Proc] a proc to execute before every request
49
49
  attr_accessor :on_request
50
50
 
51
+ # @return [Boolean] is SSL forced?
52
+ attr_accessor :force_ssl
53
+
51
54
  #
52
55
  # Initialize a new instance of the Moonrope::Base
53
56
  #
@@ -68,6 +71,7 @@ module Moonrope
68
71
  @environment = other.environment
69
72
  @load_directories = other.load_directories
70
73
  @on_request = other.on_request
74
+ other.request_callbacks.each { |block| self.register_request_callback(&block) }
71
75
  other.request_error_callbacks.each { |block| self.register_request_error_callback(&block) }
72
76
  other.external_errors.each { |error, block| self.register_external_error(error, &block) }
73
77
  end
@@ -231,5 +235,27 @@ module Moonrope
231
235
  @request_error_callbacks ||= []
232
236
  end
233
237
 
238
+ #
239
+ # Set a block which will be executed whenever a request is received by moonrope.
240
+ #
241
+ #
242
+ def register_request_callback(&block)
243
+ request_callbacks << block
244
+ end
245
+
246
+ #
247
+ # Return an array of request callbacks
248
+ #
249
+ def request_callbacks
250
+ @request_callbacks ||= []
251
+ end
252
+
253
+ #
254
+ # Should SSL be forced?
255
+ #
256
+ def force_ssl?
257
+ @force_ssl || false
258
+ end
259
+
234
260
  end
235
261
  end
@@ -52,27 +52,33 @@ module Moonrope
52
52
  # Reload if needed
53
53
  #
54
54
  if @options[:reload_on_each_request]
55
- base = @base.copy
55
+ @base = @base.copy
56
56
  begin
57
- base.load
57
+ @base.load
58
58
  rescue => e
59
- return generate_error_triplet(@base, e, global_headers)
59
+ return generate_error_triplet(@base, nil, e, global_headers)
60
60
  end
61
- else
62
- base = @base
63
61
  end
64
62
 
65
63
  #
66
- # Call the on request block if one has been defined for the base.
64
+ # Create a new request object
67
65
  #
68
- if base.on_request.is_a?(Proc)
69
- base.on_request.call(base, env)
66
+ request = base.request(env, $1)
67
+
68
+ #
69
+ # If force SSL is enabled, don't allow requests to proceed if they're
70
+ # not SSL
71
+ #
72
+ if base.force_ssl? && !request.ssl?
73
+ return [400, global_headers, [{:status => 'http-not-supported', :message => "Non-secure HTTP connections are not supported. Requests should be made using https:// rather than http://."}.to_json]]
70
74
  end
71
75
 
72
76
  #
73
- # Create a new request object
77
+ # Call the on request block if one has been defined for the base.
74
78
  #
75
- request = base.request(env, $1)
79
+ if base.on_request.is_a?(Proc)
80
+ base.on_request.call(base, env)
81
+ end
76
82
 
77
83
  #
78
84
  # Check the request is valid
@@ -87,13 +93,22 @@ module Moonrope
87
93
  begin
88
94
  result = request.execute
89
95
  json = result.to_json
90
- Moonrope.logger.info "[#{Time.now.utc.strftime("%Y-%m-%d %H:%M:%S")}] controller=#{request.controller.name} action=#{request.action.name} status=#{result.status} time=#{result.time} ip=#{request.ip} size=#{json.bytesize}"
96
+
91
97
  global_headers['Content-Length'] = json.bytesize.to_s
92
- [200, global_headers.merge(result.headers), [json]]
98
+ headers = global_headers.merge(result.headers)
99
+ Moonrope.logger.info "[#{Time.now.utc.strftime("%Y-%m-%d %H:%M:%S")}] controller=#{request.controller.name} action=#{request.action.name} status=#{result.status} time=#{result.time} ip=#{request.ip} size=#{json.bytesize}"
100
+
101
+ base.request_callbacks.each do |callback|
102
+ # Call each request callback and provide the request, the result
103
+ # and the raw that's being returned to the user.
104
+ callback.call(request, result, json, headers)
105
+ end
106
+
107
+ [200, headers, [json]]
93
108
  rescue JSON::ParserError => e
94
109
  [400, global_headers, [{:status => 'invalid-json', :details => e.message}.to_json]]
95
110
  rescue => e
96
- generate_error_triplet(base, e, global_headers)
111
+ generate_error_triplet(base, request, e, global_headers)
97
112
  end
98
113
 
99
114
  else
@@ -105,7 +120,7 @@ module Moonrope
105
120
  end
106
121
  end
107
122
 
108
- def generate_error_triplet(base, exception, headers = {})
123
+ def generate_error_triplet(base, request, exception, headers = {})
109
124
  Moonrope.logger.info exception.class
110
125
  Moonrope.logger.info exception.message
111
126
  Moonrope.logger.info exception.backtrace.join("\n")
@@ -164,6 +164,14 @@ module Moonrope
164
164
  rack_request.ip
165
165
  end
166
166
 
167
+ #
168
+ # Is this request on SSL?
169
+ #
170
+ # @return [Boolean]
171
+ def ssl?
172
+ rack_request.ssl?
173
+ end
174
+
167
175
  private
168
176
 
169
177
  #
@@ -95,7 +95,7 @@ module Moonrope
95
95
  if options[:expansions].is_a?(Array)
96
96
  expansions_to_include = options[:expansions].each_with_object({}) do |expan, hash|
97
97
  if expan.is_a?(Symbol) || expan.is_a?(String)
98
- hash[expan.to_sym] = {}
98
+ hash[expan.to_sym] = nil
99
99
  elsif expan.is_a?(Hash)
100
100
  hash[expan.first.first.to_sym] = expan.first.last
101
101
  end
@@ -233,7 +233,7 @@ module Moonrope
233
233
  # hash value as appropriate.
234
234
  if structure = self.base.structure(attribute.structure)
235
235
  structure_opts = options[:structure_opts] || attribute.structure_opts || {}
236
- if value.respond_to?(:map)
236
+ if value.is_a?(Enumerable) && value.respond_to?(:map)
237
237
  value.map do |v|
238
238
  structure.hash(v, structure_opts.merge(:request => environment.request))
239
239
  end
@@ -42,7 +42,7 @@ module Moonrope
42
42
  when :timestamp
43
43
  value.is_a?(Time) ? value.to_s : value
44
44
  when :unix_timestamp
45
- value.to_i
45
+ value.nil? ? nil : value.to_i
46
46
  else
47
47
  value
48
48
  end
@@ -1,3 +1,3 @@
1
1
  module Moonrope
2
- VERSION = '2.0.1'
2
+ VERSION = '2.0.2'
3
3
  end
@@ -14,8 +14,8 @@ Gem::Specification.new do |s|
14
14
  s.files = Dir["**/*"]
15
15
  s.bindir = "bin"
16
16
  s.executables << 'moonrope'
17
- s.add_dependency "json", "~> 1.7"
17
+ s.add_dependency "json"
18
18
  s.add_dependency "rack", ">= 1.4"
19
19
  s.add_dependency "deep_merge", "~> 1.0"
20
- s.add_development_dependency "rake", '~> 10.3'
20
+ s.add_development_dependency "rake"
21
21
  end
@@ -6,7 +6,7 @@
6
6
  <div class='tryForm__header'>
7
7
  <input type='text' id='host' name='host' value='<%= host %>'>
8
8
  /api/
9
- <input type='text' id='version' name='version' value='v1' class='v'>
9
+ <input type='text' id='version' name='version' value='<%= version %>' class='v'>
10
10
  /<%= controller.name %>/<%= action.name %>
11
11
  </div>
12
12
 
@@ -107,6 +107,20 @@ class RackMiddlewareTest < Test::Unit::TestCase
107
107
  assert_equal 2, request_count
108
108
  end
109
109
 
110
+ def test_force_ssl
111
+ begin
112
+ app.base.force_ssl = true
113
+ get "/api/v1/users/list"
114
+ assert_equal 400, last_response.status
115
+ assert response_json = JSON.parse(last_response.body)
116
+ assert_equal 'http-not-supported', response_json['status']
117
+
118
+ get "/api/v1/users/list", {}, {'HTTPS' => 'on'}
119
+ assert_equal 200, last_response.status
120
+ ensure
121
+ app.base.force_ssl = false
122
+ end
123
+ end
110
124
 
111
125
  private
112
126
 
@@ -160,6 +160,14 @@ class StructuresTest < Test::Unit::TestCase
160
160
  assert_equal 'Fido', hash[:animals][0][:name]
161
161
  assert_equal 'Boris', hash[:animals][1][:name]
162
162
  assert_equal 'Black', hash[:animals][1][:hair_color]
163
+
164
+ # a full user hash with named extensions
165
+ hash = base.structure(:user).hash(user, :full => true, :expansions => [:animals])
166
+ # arrays
167
+ assert_equal Array, hash[:animals].class
168
+ assert_equal 'Fido', hash[:animals][0][:name]
169
+ assert_equal 'Boris', hash[:animals][1][:name]
170
+ assert_equal 'Black', hash[:animals][1][:hair_color]
163
171
  end
164
172
 
165
173
  def test_ifs
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moonrope
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Cooke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-01 00:00:00.000000000 Z
11
+ date: 2020-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.7'
19
+ version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.7'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rack
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '10.3'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '10.3'
68
+ version: '0'
69
69
  description: A full library allowing you to create sexy DSLs to define your RPC-like
70
70
  APIs.
71
71
  email:
@@ -91,23 +91,6 @@ files:
91
91
  - example/controllers/users_controller.rb
92
92
  - example/structures/pet_structure.rb
93
93
  - example/structures/user_structure.rb
94
- - html/assets/lock.svg
95
- - html/assets/reset.css
96
- - html/assets/style.css
97
- - html/assets/tool.svg
98
- - html/assets/try.js
99
- - html/authenticators/default.html
100
- - html/controllers/meta.html
101
- - html/controllers/meta/version.html
102
- - html/controllers/users.html
103
- - html/controllers/users/create.html
104
- - html/controllers/users/list.html
105
- - html/controllers/users/show.html
106
- - html/controllers/users/update.html
107
- - html/index.html
108
- - html/moonrope.txt
109
- - html/structures/pet.html
110
- - html/structures/user.html
111
94
  - lib/moonrope.rb
112
95
  - lib/moonrope/action.rb
113
96
  - lib/moonrope/action_result.rb
@@ -191,10 +174,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
191
174
  - !ruby/object:Gem::Version
192
175
  version: '0'
193
176
  requirements: []
194
- rubyforge_project:
195
- rubygems_version: 2.5.1
177
+ rubygems_version: 3.0.3
196
178
  signing_key:
197
179
  specification_version: 4
198
180
  summary: An API server DSL.
199
181
  test_files: []
200
- has_rdoc:
@@ -1,3 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
2
- <path fill="#ed4300" d="M3 0c-1.1 0-2 .9-2 2v1h-1v4h6v-4h-1v-1c0-1.1-.9-2-2-2zm0 1c.56 0 1 .44 1 1v1h-2v-1c0-.56.44-1 1-1z" transform="translate(1)" />
3
- </svg>
@@ -1,101 +0,0 @@
1
- html, body, body div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header, hgroup, menu, nav, section, time, mark, audio, video {
2
- margin: 0;
3
- padding: 0;
4
- border: 0;
5
- outline: 0;
6
- font-size: 100%;
7
- letter-spacing:0;
8
- vertical-align: baseline;
9
- background: transparent;
10
- font-weight:inherit;
11
- }
12
-
13
- * {
14
- -webkit-box-sizing: border-box;
15
- -moz-box-sizing: border-box;
16
- box-sizing: border-box;
17
- }
18
- u { text-decoration: none;}
19
- b { font-weight:normal;}
20
- article, aside, figure, footer, header, hgroup, nav, section {display: block;}
21
-
22
- object,embed {max-width: 100%;}
23
- ul {list-style: none;}
24
- blockquote, q {quotes: none;}
25
- b,strong { font-weight:bold;}
26
- blockquote:before, blockquote:after, q:before, q:after {content: ''; content: none;}
27
-
28
- a {margin: 0; padding: 0; font-size: 100%; vertical-align: baseline; background: transparent;}
29
-
30
- del {text-decoration: line-through;}
31
-
32
- abbr[title], dfn[title] {border-bottom: 1px dotted #000; cursor: help;}
33
-
34
- /* tables still need cellspacing="0" in the markup */
35
- table {border-collapse: collapse; border-spacing: 0;}
36
- mark { color:inherit;}
37
-
38
- hr {display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0;}
39
-
40
- input, select {vertical-align: middle;}
41
-
42
- pre {
43
- white-space: pre; /* CSS2 */
44
- white-space: pre-wrap; /* CSS 2.1 */
45
- white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */
46
- word-wrap: break-word; /* IE */
47
- }
48
-
49
- input[type="radio"] {vertical-align: text-bottom;}
50
- input[type="checkbox"] {vertical-align: bottom; *vertical-align: baseline;}
51
- .ie6 input {vertical-align: text-bottom;}
52
-
53
- select, input, textarea {font: 99% sans-serif;}
54
-
55
- table {font-size: inherit; font: 100%;}
56
-
57
- /* Accessible focus treatment
58
- people.opera.com/patrickl/experiments/keyboard/test */
59
- a:hover, a:active {outline: none;}
60
-
61
- small {font-size: 85%;}
62
-
63
- strong, th {font-weight: bold;}
64
-
65
- td, td img {vertical-align: top;}
66
-
67
- /* Make sure sup and sub don't screw with your line-heights
68
- gist.github.com/413930 */
69
- sub, sup {font-size: 75%; line-height: 0; position: relative;}
70
- sup {top: -0.5em;}
71
- sub {bottom: -0.25em;}
72
-
73
- /* standardize any monospaced elements */
74
- pre, code, kbd, samp {font-family: monospace, sans-serif;}
75
-
76
- /* hand cursor on clickable elements */
77
- .clickable,
78
- label,
79
- input[type=button],
80
- input[type=submit],
81
- button {cursor: pointer;}
82
-
83
- /* Webkit browsers add a 2px margin outside the chrome of form elements */
84
- button, input, select, textarea {margin: 0;}
85
-
86
- /* make buttons play nice in IE */
87
- button {width: auto; overflow: visible;}
88
-
89
- /* scale images in IE7 more attractively */
90
- .ie7 img {-ms-interpolation-mode: bicubic;}
91
-
92
- /* prevent BG image flicker upon hover */
93
- .ie6 html {filter: expression(document.execCommand("BackgroundImageCache", false, true));}
94
-
95
- /* let's clear some floats */
96
- .clearfix:before, .clearfix:after { content: "\0020"; display: block; height: 0; overflow: hidden; }
97
- .clearfix:after { clear: both; }
98
- .clearfix { zoom: 1; }
99
-
100
- select, input, textarea, a { outline: none;}
101
- a { color:inherit;}