praxis 0.11.2 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/lib/api_browser/app/js/controllers/action.js +2 -2
  4. data/lib/api_browser/app/js/controllers/type.js +2 -2
  5. data/lib/praxis/action_definition.rb +11 -0
  6. data/lib/praxis/api_definition.rb +2 -0
  7. data/lib/praxis/bootloader_stages/environment.rb +1 -0
  8. data/lib/praxis/controller.rb +2 -11
  9. data/lib/praxis/media_type.rb +12 -3
  10. data/lib/praxis/media_type_collection.rb +0 -2
  11. data/lib/praxis/plugins/praxis_mapper_plugin.rb +27 -5
  12. data/lib/praxis/request_stages/request_stage.rb +53 -32
  13. data/lib/praxis/request_stages/response.rb +2 -3
  14. data/lib/praxis/resource_definition.rb +11 -1
  15. data/lib/praxis/responses/http.rb +108 -20
  16. data/lib/praxis/responses/internal_server_error.rb +1 -1
  17. data/lib/praxis/responses/validation_error.rb +1 -1
  18. data/lib/praxis/restful_doc_generator.rb +27 -3
  19. data/lib/praxis/router.rb +16 -2
  20. data/lib/praxis/skeletor/restful_routing_config.rb +3 -0
  21. data/lib/praxis/stage.rb +1 -1
  22. data/lib/praxis/tasks/api_docs.rb +1 -1
  23. data/lib/praxis/tasks/console.rb +21 -3
  24. data/lib/praxis/tasks/routes.rb +19 -7
  25. data/lib/praxis/version.rb +1 -1
  26. data/praxis.gemspec +3 -5
  27. data/spec/functional_spec.rb +12 -0
  28. data/spec/praxis/action_definition_spec.rb +17 -0
  29. data/spec/praxis/media_type_spec.rb +22 -2
  30. data/spec/praxis/plugins/praxis_mapper_plugin_spec.rb +62 -15
  31. data/spec/praxis/request_stage_spec.rb +147 -67
  32. data/spec/praxis/resource_definition_spec.rb +18 -2
  33. data/spec/praxis/restful_routing_config_spec.rb +1 -1
  34. data/spec/praxis/router_spec.rb +115 -37
  35. data/spec/spec_app/design/resources/instances.rb +1 -1
  36. data/spec/support/spec_media_types.rb +2 -0
  37. metadata +8 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: faa4c7b780be253c8aa05ac8f9969d2d9754efbf
4
- data.tar.gz: 4b71e46c0337fc3c6346ca6d1da68512155d0712
3
+ metadata.gz: 4684312c88071162f3525b9ee7c88c9f9a7587d2
4
+ data.tar.gz: fcf53c832ebc5f430dc37b9944ccc334b7ec3678
5
5
  SHA512:
6
- metadata.gz: 3914c19d0fdbc50d4aaa949dc0dfc4df0c8a602abd9313cc9c1bf12a17d73e667a024e2299b83d0f6b19697d808de5ab721d5089b36a658200979be680e78c6b
7
- data.tar.gz: f692e9d7e62f5fe2ed80899f1b0c63ecbf0b01ec987a95bf157f78b4a373583a07720063c04a3bfea486cafae89340e3686f3b2f95ca4c91a5e2976461a62230
6
+ metadata.gz: a600f9e9857b338f87c3dbec975e016a7f3bee940b0a9c590cfc241e7b05e81825877a92a6b49049089ef76ecabcf127ef978d3d545d828b8d7ce197a0b792d8
7
+ data.tar.gz: 115db171ee75c4569beab2277e4c917bcd768e444e264b769862373936365a54cff1eaa154c21cf7543b59816756e45aafddbc0dd0c95714afdc392f95cae006
data/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # praxis changelog
2
2
 
3
+ ## next
4
+
5
+ ## 0.13.0
6
+
7
+ * Added `nodoc!` method to `ActionDefinition`, `ResourceDefinition` to hide actions and resources from the generated documentation.
8
+ * Default HTTP responses:
9
+ * Added descriptions
10
+ * Added 408 RequestTimeout response
11
+ * Replaced Ruport dependency in `praxis:routes` rake task with TerminalTable.
12
+ * Fixed doc browser issue when attributes defaulting to false wouldn't display the default section.
13
+ * Enhanced several logging aspects of the PraxisMapper plugin:
14
+ * The log-level of the stats is now configurable in the plugin (see the comments [here](https://github.com/rightscale/praxis/blob/master/lib/praxis/plugins/praxis_mapper_plugin.rb) for details)
15
+ * Added a "silence_mapper_stats" attribute in the Request objects so, actions and/or controllers can selectively skip logging stats (for example, health check controllers, etc)
16
+ * It now logs a compact message (with the same heading) when the identity map has had no interactions.
17
+ * Added X-Cascade header support
18
+ * Configured with boolean `praxis.x_cascade` that defaults to true.
19
+ * When enabled, Praxis will add an 'X-Cascade: pass' header to the response when the request was not routable to an action. It is not added if the action explicitly returns a `NotFound` response.
20
+ * Fixed bug in request handling where `after` callbacks were being executed, even if the stage returned a response.
21
+ * Added a handy option to tie an action route to match any HTTP verb.
22
+ * Simply use `any` as the verb when you define it (i.e. any '/things/:id' )
23
+ * Allow a MediaType to define a custom `links` attribute like any other.
24
+ * This is not compatible if it also wants to use the `links` DSL.
25
+
26
+
3
27
  ## 0.11.2
4
28
 
5
29
  * The Doc Browser will now not change the menu when refreshing.
@@ -18,8 +18,8 @@ app.controller("ActionCtrl", function($scope, $stateParams, Documentation) {
18
18
  var example = set.example ? JSON.stringify(set.example[name], null, 2) : '';
19
19
  if (!attribute.options) attribute.options = {};
20
20
  if (example) attribute.options.example = example;
21
- if (attribute.values) attribute.options.values = attribute.values;
22
- if (attribute.default) attribute.options.default = attribute.default;
21
+ if (attribute.values != null) attribute.options.values = attribute.values;
22
+ if (attribute.default != null) attribute.options.default = attribute.default;
23
23
  });
24
24
  }
25
25
  });
@@ -15,8 +15,8 @@
15
15
  var example = JSON.stringify($scope.type.example[name], null, 2);
16
16
  if (!attribute.options) attribute.options = {};
17
17
  if (example) attribute.options.example = example;
18
- if (attribute.values) attribute.options.values = attribute.values;
19
- if (attribute.default) attribute.options.default = attribute.default;
18
+ if (attribute.values != null) attribute.options.values = attribute.values;
19
+ if (attribute.default != null) attribute.options.default = attribute.default;
20
20
  });
21
21
 
22
22
  Documentation.getIndex().success(function(response) {
@@ -16,6 +16,10 @@ module Praxis
16
16
  attr_reader :named_routes
17
17
  attr_reader :responses
18
18
 
19
+ # opaque hash of user-defined medata, used to decorate the definition,
20
+ # and also available in the generated JSON documents
21
+ attr_reader :metadata
22
+
19
23
  class << self
20
24
  attr_accessor :doc_decorations
21
25
  end
@@ -30,6 +34,7 @@ module Praxis
30
34
  @name = name
31
35
  @resource_definition = resource_definition
32
36
  @responses = Hash.new
37
+ @metadata = Hash.new
33
38
 
34
39
  if (media_type = resource_definition.media_type)
35
40
  if media_type.kind_of?(Class) && media_type < Praxis::MediaType
@@ -147,6 +152,7 @@ module Praxis
147
152
  {}.tap do |hash|
148
153
  hash[:description] = description
149
154
  hash[:name] = name
155
+ hash[:metadata] = metadata
150
156
  # FIXME: change to :routes along with api browser
151
157
  hash[:urls] = routes.collect(&:describe)
152
158
  hash[:headers] = headers.describe if headers
@@ -162,5 +168,10 @@ module Praxis
162
168
  end
163
169
  end
164
170
 
171
+ def nodoc!
172
+ metadata[:doc_visibility] = :none
173
+ end
174
+
175
+
165
176
  end
166
177
  end
@@ -46,11 +46,13 @@ module Praxis
46
46
  api.response_template :ok do |media_type: |
47
47
  media_type media_type
48
48
  status 200
49
+ description 'Standard response for successful HTTP requests.'
49
50
  end
50
51
 
51
52
  api.response_template :created do |location: nil|
52
53
  location location
53
54
  status 201
55
+ description 'The request has been fulfilled and resulted in a new resource being created.'
54
56
  end
55
57
  end
56
58
 
@@ -43,6 +43,7 @@ module Praxis
43
43
  attribute :praxis do
44
44
  attribute :validate_responses, Attributor::Boolean, default: false
45
45
  attribute :show_exceptions, Attributor::Boolean, default: false
46
+ attribute :x_cascade, Attributor::Boolean, default: true
46
47
  end
47
48
  end
48
49
  end
@@ -4,6 +4,7 @@ require 'active_support/all'
4
4
  module Praxis
5
5
  module Controller
6
6
  extend ::ActiveSupport::Concern
7
+
7
8
  # A Controller always requires the callbacks
8
9
  include Praxis::Callbacks
9
10
 
@@ -11,6 +12,7 @@ module Praxis
11
12
  attr_reader :request
12
13
  attr_accessor :response
13
14
  end
15
+
14
16
  module ClassMethods
15
17
  def implements(definition)
16
18
  define_singleton_method(:definition) do
@@ -27,16 +29,5 @@ module Praxis
27
29
  @response = response
28
30
  end
29
31
 
30
- # def request
31
- # @request
32
- # end
33
- #
34
- # def response
35
- # @response
36
- # end
37
- #
38
- # def response=(value)
39
- # @response = value
40
- # end
41
32
  end
42
33
  end
@@ -30,11 +30,20 @@ module Praxis
30
30
  super(opts.merge(dsl_compiler: MediaType::DSLCompiler), &block)
31
31
  end
32
32
 
33
- def links
34
- self.class::Links.new(@object)
33
+ def self._finalize!
34
+ super
35
+ if @attribute && self.attributes.key?(:links) && self.attributes[:links].type < Praxis::Links
36
+ # Only define out special links accessor if it was setup using the special DSL
37
+ # (we might have an app defining an attribute called `links` on its own, in which
38
+ # case we leave it be)
39
+ module_eval <<-RUBY, __FILE__, __LINE__ + 1
40
+ def links
41
+ self.class::Links.new(@object)
42
+ end
43
+ RUBY
44
+ end
35
45
  end
36
46
 
37
-
38
47
  end
39
48
 
40
49
  end
@@ -61,13 +61,11 @@ module Praxis
61
61
  members = []
62
62
  size = rand(3) + 1
63
63
 
64
-
65
64
  size.times do |i|
66
65
  subcontext = context + ["at(#{i})"]
67
66
  members << @member_attribute.example(subcontext)
68
67
  end
69
68
 
70
-
71
69
  result.object._members = members
72
70
  result
73
71
  end
@@ -36,6 +36,7 @@ require 'terminal-table'
36
36
  # output into the Praxis::Application.instance.logger app log. Possible
37
37
  # values are: "detailed", "short", and "skip" (i.e. do not print the stats
38
38
  # at all).
39
+ # 3. stats_log_level: the logging level with which the statistics should be logged.
39
40
  #
40
41
  # See http://praxis-framework.io/reference/plugins/ for further details on how
41
42
  # to use a plugin and pass it options.
@@ -75,6 +76,7 @@ module Praxis
75
76
  def prepare_config!(node)
76
77
  node.attributes do
77
78
  attribute :log_stats, String, values: ['detailed', 'short', 'skip'], default: 'detailed'
79
+ attribute :stats_log_level, Symbol, values: [:fatal,:error,:warn,:info,:debug], default: :info
78
80
  attribute :repositories, Attributor::Hash.of(key: String, value: RepositoryConfig)
79
81
  end
80
82
  end
@@ -103,7 +105,7 @@ module Praxis
103
105
  unless log_stats == 'skip'
104
106
  Praxis::Notifications.subscribe 'praxis.request.all' do |name, *junk, payload|
105
107
  if (identity_map = payload[:request].identity_map)
106
- PraxisMapperPlugin::Statistics.log(identity_map, log_stats)
108
+ PraxisMapperPlugin::Statistics.log(payload[:request], identity_map, log_stats)
107
109
  end
108
110
  end
109
111
  end
@@ -126,6 +128,15 @@ module Praxis
126
128
  def identity_map=(map)
127
129
  @identity_map = map
128
130
  end
131
+
132
+ def silence_mapper_stats
133
+ @silence_mapper_stats
134
+ end
135
+
136
+ def silence_mapper_stats=(value)
137
+ @silence_mapper_stats = value
138
+ end
139
+
129
140
  end
130
141
 
131
142
  module Controller
@@ -133,15 +144,22 @@ module Praxis
133
144
 
134
145
  included do
135
146
  before :action do |controller|
136
- controller.request.identity_map = Praxis::Mapper::IdentityMap.setup!
147
+ controller.request.identity_map = Praxis::Mapper::IdentityMap.new
137
148
  end
138
149
  end
139
150
  end
140
151
 
141
152
  module Statistics
142
153
 
143
- def self.log(identity_map, log_stats)
154
+ def self.log(request, identity_map, log_stats)
144
155
  return if identity_map.nil?
156
+ return if request.silence_mapper_stats == true
157
+ if identity_map.queries.empty?
158
+ self.to_logger "No database interactions observed."
159
+ return
160
+ end
161
+
162
+
145
163
  case log_stats
146
164
  when 'detailed'
147
165
  self.detailed(identity_map)
@@ -187,7 +205,7 @@ module Praxis
187
205
  table.align_column(3, :right)
188
206
  table.align_column(4, :right)
189
207
  table.align_column(5, :right)
190
- Praxis::Application.instance.logger.info "Praxis::Mapper Statistics:\n#{table.to_s}"
208
+ self.to_logger "\n#{table.to_s}"
191
209
  end
192
210
 
193
211
  def self.round_fields_at(values, indices)
@@ -197,7 +215,11 @@ module Praxis
197
215
  end
198
216
 
199
217
  def self.short(identity_map)
200
- Praxis::Application.instance.logger.info "Praxis::Mapper Statistics: #{identity_map.query_statistics.sum_totals.to_s}"
218
+ self.to_logger identity_map.query_statistics.sum_totals.to_s
219
+ end
220
+
221
+ def self.to_logger(message)
222
+ Praxis::Application.instance.logger.__send__(Plugin.instance.config.stats_log_level, "Praxis::Mapper Statistics: #{message}")
201
223
  end
202
224
  end
203
225
  end
@@ -15,68 +15,89 @@ module Praxis
15
15
  end
16
16
 
17
17
  def execute_controller_callbacks(callbacks)
18
- if callbacks.has_key?(path)
18
+ if callbacks.key?(path)
19
19
  callbacks[path].each do |(conditions, block)|
20
- if conditions.has_key?(:actions)
20
+ if conditions.key?(:actions)
21
21
  next unless conditions[:actions].include? action.name
22
22
  end
23
23
  result = block.call(controller)
24
- return result if result && result.kind_of?(Praxis::Response)
24
+ if result && result.kind_of?(Praxis::Response)
25
+ controller.response = result
26
+ return result
27
+ end
25
28
  end
26
29
  end
30
+
27
31
  nil
28
32
  end
29
-
33
+
30
34
  def run
31
35
  setup!
32
36
  setup_deferred_callbacks!
33
-
37
+
38
+ # stage-level callbacks (typically empty) will never shortcut
34
39
  execute_callbacks(self.before_callbacks)
35
- # Shortcut lifecycle if filters return a response (non-nil but non-response-class response is ignored)
40
+
36
41
  r = execute_controller_callbacks(controller.class.before_callbacks)
42
+ # Shortcut lifecycle if filters return non-nil value
43
+ # (which should only be a Response)
37
44
  return r if r
38
45
 
39
46
  result = execute_with_around
40
- # Still allow the after callbacks to shortcut it if necessary.
47
+ # Shortcut lifecycle if filters return a response
48
+ # (non-nil but non-response-class response is ignored)
49
+ if result && result.kind_of?(Praxis::Response)
50
+ controller.response = result
51
+ return result
52
+ end
53
+
41
54
  r = execute_controller_callbacks(controller.class.after_callbacks)
42
- return r if r
43
- execute_callbacks(self.after_callbacks)
55
+ # Shortcut lifecycle if filters return non-nil value
56
+ # (which should only be a Response)
57
+ return r if r
58
+
59
+ # stage-level callbacks (typically empty) will never shortcut
60
+ execute_callbacks(self.after_callbacks)
44
61
 
45
62
  result
46
63
  end
47
64
 
48
65
  def execute_with_around
49
- cb = controller.class.around_callbacks[ path ]
50
- if cb == nil || cb.empty?
51
- execute
52
- else
53
- inner_proc = proc { execute }
54
-
55
- applicable = cb.select do |(conditions, handler)|
56
- if conditions.has_key?(:actions)
57
- (conditions[:actions].include? action.name) ? true : false
58
- else
59
- true
60
- end
66
+ cb = controller.class.around_callbacks[ path ]
67
+ if cb == nil || cb.empty?
68
+ execute
69
+ else
70
+ inner_proc = proc { execute }
71
+
72
+ applicable = cb.select do |(conditions, handler)|
73
+ if conditions.has_key?(:actions)
74
+ (conditions[:actions].include? action.name) ? true : false
75
+ else
76
+ true
77
+ end
78
+ end
79
+
80
+ chain = applicable.reverse.inject(inner_proc) do |blk, (conditions, handler)|
81
+ if blk
82
+ proc{ handler.call(controller,blk) }
83
+ else
84
+ proc{ handler.call }
61
85
  end
62
-
63
- chain = applicable.reverse.inject(inner_proc) do |blk, (conditions, handler)|
64
- if blk
65
- proc{ handler.call(controller,blk) }
66
- else
67
- proc{ handler.call }
68
- end
69
- end
70
- chain.call
71
86
  end
87
+ chain.call
88
+ end
72
89
  end
73
-
90
+
91
+
74
92
  def execute
75
93
  raise NotImplementedError, 'Subclass must implement Stage#execute' unless @stages.any?
76
94
 
77
95
  @stages.each do |stage|
78
96
  shortcut = stage.run
79
- return shortcut if shortcut && shortcut.kind_of?(Praxis::Response)
97
+ if shortcut && shortcut.kind_of?(Praxis::Response)
98
+ controller.response = shortcut
99
+ return shortcut
100
+ end
80
101
  end
81
102
  nil
82
103
  end
@@ -2,12 +2,11 @@ module Praxis
2
2
  module RequestStages
3
3
 
4
4
  class Response < RequestStage
5
- WHITELIST_RESPONSES = [:validation_error]
5
+ WHITELIST_RESPONSES = [:validation_error]
6
6
 
7
7
  def execute
8
8
  response = controller.response
9
9
 
10
-
11
10
  unless action.responses.include?(response.response_name) || WHITELIST_RESPONSES.include?(response.response_name)
12
11
  raise Exceptions::InvalidResponse.new(
13
12
  "Response #{response.name.inspect} is not allowed for #{action.name.inspect}"
@@ -21,7 +20,7 @@ module Praxis
21
20
  end
22
21
  rescue Exceptions::Validation => e
23
22
  controller.response = Responses::ValidationError.new(exception: e)
24
- retry
23
+ retry
25
24
  end
26
25
 
27
26
  end
@@ -12,6 +12,7 @@ module Praxis
12
12
  @responses = Hash.new
13
13
  @action_defaults = []
14
14
  @version_options = {}
15
+ @metadata = {}
15
16
  Application.instance.resource_definitions << self
16
17
  end
17
18
 
@@ -20,7 +21,11 @@ module Praxis
20
21
  attr_reader :routing_config
21
22
  attr_reader :responses
22
23
  attr_reader :version_options
23
-
24
+
25
+ # opaque hash of user-defined medata, used to decorate the definition,
26
+ # and also available in the generated JSON documents
27
+ attr_reader :metadata
28
+
24
29
  attr_accessor :controller
25
30
 
26
31
  # FIXME: this is inconsistent with the rest of the magic DSL convention.
@@ -94,6 +99,7 @@ module Praxis
94
99
  hash[:description] = description
95
100
  hash[:media_type] = media_type.name if media_type
96
101
  hash[:actions] = actions.values.map(&:describe)
102
+ hash[:metadata] = metadata
97
103
  end
98
104
  end
99
105
 
@@ -104,6 +110,10 @@ module Praxis
104
110
  self.instance_eval(&ApiDefinition.instance.traits[trait_name])
105
111
  end
106
112
 
113
+ def nodoc!
114
+ metadata[:doc_visibility] = :none
115
+ end
116
+
107
117
  end
108
118
 
109
119
  end
@@ -2,34 +2,37 @@ module Praxis
2
2
 
3
3
  module Responses
4
4
 
5
- # Standard response for successful HTTP requests.
6
- # The actual response will depend on the request method used.
7
- # In a GET request, the response will contain an entity
8
- # corresponding to the requested resource.
9
- # In a POST request the response will contain an entity
5
+ # Descriptions from http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
6
+
7
+ # Standard response for successful HTTP requests.
8
+ # The actual response will depend on the request method used.
9
+ # In a GET request, the response will contain an entity
10
+ # corresponding to the requested resource.
11
+ # In a POST request the response will contain an entity
10
12
  # describing or containing the result of the action.
11
13
  class Ok < Praxis::Response
12
14
  self.status = 200
13
15
  end
14
16
 
15
-
16
- # The request has been fulfilled and resulted in a new resource
17
+ # The request has been fulfilled and resulted in a new resource
17
18
  # being created.
18
19
  class Created < Praxis::Response
19
20
  self.status = 201
20
21
  end
21
22
 
22
23
 
23
- # The request has been accepted for processing, but the
24
- # processing has not been completed. The request might or might
25
- # not eventually be acted upon, as it might be disallowed when
24
+ # The request has been accepted for processing, but the
25
+ # processing has not been completed. The request might or might
26
+ # not eventually be acted upon, as it might be disallowed when
26
27
  # processing actually takes place.
27
28
  class Accepted < Praxis::Response
28
29
  self.status = 202
29
30
  end
30
31
 
31
32
 
32
- # The server successfully processed the request, but is not returning any content. Usually used as a response to a successful delete request.
33
+ # The server successfully processed the request, but is not
34
+ # returning any content. Usually used as a response to
35
+ # a successful delete request.
33
36
  class NoContent < Praxis::Response
34
37
  self.status = 204
35
38
  end
@@ -101,11 +104,15 @@ module Praxis
101
104
  end
102
105
 
103
106
 
104
- # A request was made of a resource using a request method not supported by that resource; for example, using GET on a form which requires data to be presented via POST, or using PUT on a read-only resource.
107
+ # The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request.
105
108
  class NotAcceptable < Praxis::Response
106
109
  self.status = 406
107
110
  end
108
111
 
112
+ # The server timed out waiting for the request.
113
+ class RequestTimeout < Praxis::Response
114
+ self.status = 408
115
+ end
109
116
 
110
117
  # Indicates that the request could not be processed because of conflict in the request, such as an edit conflict in the case of multiple updates.
111
118
  class Conflict < Praxis::Response
@@ -124,19 +131,100 @@ module Praxis
124
131
  self.status = 422
125
132
  end
126
133
 
127
-
128
134
  ApiDefinition.define do |api|
129
- self.constants.each do |class_name|
130
- response_class = self.const_get(class_name)
131
- response_name = response_class.response_name
132
- next if api.responses.key?(response_name)
133
135
 
134
- api.response_template response_name do
135
- status response_class.status
136
- end
136
+ api.response_template :accepted do
137
+ status 202
138
+ description "The request has been accepted for processing, but the processing has not been completed."
139
+ end
140
+
141
+ api.response_template :no_content do
142
+ status 204
143
+ description "The server successfully processed the request, but is not returning any content."
144
+ end
145
+
146
+ api.response_template :multiple_choices do
147
+ status 300
148
+ description "Indicates multiple options for the resource that the client may follow."
149
+ end
150
+
151
+ api.response_template :moved_permanently do
152
+ status 301
153
+ description "This and all future requests should be directed to the given URI."
154
+ end
155
+
156
+ api.response_template :found do
157
+ status 302
158
+ description "The requested resource resides temporarily under a different URI."
159
+ end
160
+
161
+ api.response_template :see_other do
162
+ status 303
163
+ description "The response to the request can be found under another URI using a GET method"
164
+ end
165
+
166
+ api.response_template :not_modified do
167
+ status 304
168
+ description "Indicates that the resource has not been modified since the version specified by the request headers If-Modified-Since or If-Match."
169
+ end
170
+
171
+ api.response_template :temporary_redirect do
172
+ status 307
173
+ description "In this case, the request should be repeated with another URI; however, future requests should still use the original URI."
174
+ end
175
+
176
+ api.response_template :bad_request do
177
+ status 400
178
+ description "The request cannot be fulfilled due to bad syntax."
179
+ end
180
+
181
+ api.response_template :unauthorized do
182
+ status 401
183
+ description "Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet been provided."
184
+ end
185
+
186
+ api.response_template :forbidden do
187
+ status 403
188
+ description "The request was a valid request, but the server is refusing to respond to it."
189
+ end
190
+
191
+ api.response_template :not_found do
192
+ status 404
193
+ description "The requested resource could not be found but may be available again in the future."
194
+ end
195
+
196
+ api.response_template :method_not_allowed do
197
+ status 405
198
+ description "A request was made of a resource using a request method not supported by that resource."
199
+ end
200
+
201
+ api.response_template :not_acceptable do
202
+ status 406
203
+ description "The requested resource is only capable of generating content not acceptable according to the Accept headers sent in the request."
204
+ end
205
+
206
+ api.response_template :request_timeout do
207
+ status 408
208
+ description "The server timed out waiting for the request."
209
+ end
210
+
211
+ api.response_template :conflict do
212
+ status 409
213
+ description "Indicates that the request could not be processed because of conflict in the request, such as an edit conflict in the case of multiple updates."
214
+ end
215
+
216
+ api.response_template :precondition_failed do
217
+ status 412
218
+ description "The server does not meet one of the preconditions that the requester put on the request."
219
+ end
137
220
 
221
+ api.response_template :unprocessable_entity do
222
+ status 422
223
+ description "The request was well-formed but was unable to be followed due to semantic errors."
138
224
  end
225
+
139
226
  end
140
227
 
228
+
141
229
  end
142
230
  end
@@ -36,7 +36,7 @@ module Praxis
36
36
 
37
37
  ApiDefinition.define do |api|
38
38
  api.response_template :internal_server_error do
39
- description "When an internal server error occurs..."
39
+ description "A generic error message, given when an unexpected condition was encountered and no more specific message is suitable."
40
40
  status 500
41
41
  media_type "application/json"
42
42
  end
@@ -31,7 +31,7 @@ module Praxis
31
31
 
32
32
  ApiDefinition.define do |api|
33
33
  api.response_template :validation_error do
34
- description "When parameter validation hits..."
34
+ description "An error message indicating that one or more elements of the request did not match the API specification for the action"
35
35
  status 400
36
36
  media_type "application/json"
37
37
  end