grape 0.3.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grape might be problematic. Click here for more details.

Files changed (101) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +8 -0
  3. data/.rubocop.yml +70 -0
  4. data/.travis.yml +7 -6
  5. data/CHANGELOG.md +134 -4
  6. data/CONTRIBUTING.md +118 -0
  7. data/Gemfile +5 -2
  8. data/README.md +551 -116
  9. data/RELEASING.md +105 -0
  10. data/Rakefile +29 -8
  11. data/UPGRADING.md +124 -0
  12. data/grape.gemspec +3 -3
  13. data/lib/grape/api.rb +207 -88
  14. data/lib/grape/cookies.rb +4 -8
  15. data/lib/grape/endpoint.rb +198 -144
  16. data/lib/grape/error_formatter/base.rb +5 -7
  17. data/lib/grape/error_formatter/json.rb +3 -5
  18. data/lib/grape/error_formatter/txt.rb +1 -3
  19. data/lib/grape/error_formatter/xml.rb +4 -6
  20. data/lib/grape/exceptions/base.rb +9 -9
  21. data/lib/grape/exceptions/incompatible_option_values.rb +10 -0
  22. data/lib/grape/exceptions/invalid_formatter.rb +1 -4
  23. data/lib/grape/exceptions/invalid_versioner_option.rb +1 -5
  24. data/lib/grape/exceptions/invalid_with_option_for_represent.rb +1 -6
  25. data/lib/grape/exceptions/missing_mime_type.rb +1 -5
  26. data/lib/grape/exceptions/missing_option.rb +1 -4
  27. data/lib/grape/exceptions/missing_vendor_option.rb +1 -4
  28. data/lib/grape/exceptions/unknown_options.rb +1 -5
  29. data/lib/grape/exceptions/unknown_validator.rb +1 -3
  30. data/lib/grape/exceptions/validation.rb +13 -3
  31. data/lib/grape/exceptions/validation_errors.rb +43 -0
  32. data/lib/grape/formatter/base.rb +5 -7
  33. data/lib/grape/formatter/json.rb +0 -3
  34. data/lib/grape/formatter/serializable_hash.rb +15 -15
  35. data/lib/grape/formatter/txt.rb +0 -2
  36. data/lib/grape/formatter/xml.rb +0 -2
  37. data/lib/grape/http/request.rb +26 -0
  38. data/lib/grape/locale/en.yml +8 -5
  39. data/lib/grape/middleware/auth/base.rb +30 -0
  40. data/lib/grape/middleware/auth/basic.rb +3 -20
  41. data/lib/grape/middleware/auth/digest.rb +2 -19
  42. data/lib/grape/middleware/auth/oauth2.rb +31 -24
  43. data/lib/grape/middleware/base.rb +7 -7
  44. data/lib/grape/middleware/error.rb +36 -22
  45. data/lib/grape/middleware/filter.rb +3 -3
  46. data/lib/grape/middleware/formatter.rb +99 -61
  47. data/lib/grape/middleware/globals.rb +13 -0
  48. data/lib/grape/middleware/versioner/accept_version_header.rb +67 -0
  49. data/lib/grape/middleware/versioner/header.rb +22 -16
  50. data/lib/grape/middleware/versioner/param.rb +9 -11
  51. data/lib/grape/middleware/versioner/path.rb +10 -13
  52. data/lib/grape/middleware/versioner.rb +3 -1
  53. data/lib/grape/namespace.rb +23 -0
  54. data/lib/grape/parser/base.rb +3 -5
  55. data/lib/grape/parser/json.rb +0 -2
  56. data/lib/grape/parser/xml.rb +0 -2
  57. data/lib/grape/path.rb +70 -0
  58. data/lib/grape/route.rb +10 -6
  59. data/lib/grape/util/content_types.rb +2 -1
  60. data/lib/grape/util/deep_merge.rb +5 -5
  61. data/lib/grape/util/hash_stack.rb +13 -2
  62. data/lib/grape/validations/coerce.rb +11 -10
  63. data/lib/grape/validations/default.rb +25 -0
  64. data/lib/grape/validations/presence.rb +7 -3
  65. data/lib/grape/validations/regexp.rb +2 -5
  66. data/lib/grape/validations/values.rb +17 -0
  67. data/lib/grape/validations.rb +161 -54
  68. data/lib/grape/version.rb +1 -1
  69. data/lib/grape.rb +19 -4
  70. data/spec/grape/api_spec.rb +897 -268
  71. data/spec/grape/endpoint_spec.rb +283 -66
  72. data/spec/grape/entity_spec.rb +132 -29
  73. data/spec/grape/exceptions/missing_mime_type_spec.rb +3 -9
  74. data/spec/grape/exceptions/validation_errors_spec.rb +19 -0
  75. data/spec/grape/middleware/auth/basic_spec.rb +8 -8
  76. data/spec/grape/middleware/auth/digest_spec.rb +5 -5
  77. data/spec/grape/middleware/auth/oauth2_spec.rb +81 -36
  78. data/spec/grape/middleware/base_spec.rb +8 -13
  79. data/spec/grape/middleware/error_spec.rb +13 -17
  80. data/spec/grape/middleware/exception_spec.rb +47 -27
  81. data/spec/grape/middleware/formatter_spec.rb +103 -41
  82. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +121 -0
  83. data/spec/grape/middleware/versioner/header_spec.rb +76 -51
  84. data/spec/grape/middleware/versioner/param_spec.rb +18 -18
  85. data/spec/grape/middleware/versioner/path_spec.rb +6 -6
  86. data/spec/grape/middleware/versioner_spec.rb +5 -2
  87. data/spec/grape/path_spec.rb +229 -0
  88. data/spec/grape/util/hash_stack_spec.rb +31 -32
  89. data/spec/grape/validations/coerce_spec.rb +116 -51
  90. data/spec/grape/validations/default_spec.rb +123 -0
  91. data/spec/grape/validations/presence_spec.rb +42 -44
  92. data/spec/grape/validations/regexp_spec.rb +9 -9
  93. data/spec/grape/validations/values_spec.rb +138 -0
  94. data/spec/grape/validations/zh-CN.yml +4 -3
  95. data/spec/grape/validations_spec.rb +681 -48
  96. data/spec/shared/versioning_examples.rb +22 -6
  97. data/spec/spec_helper.rb +3 -2
  98. data/spec/support/basic_auth_encode_helpers.rb +0 -1
  99. data/spec/support/content_type_helpers.rb +11 -0
  100. data/spec/support/versioned_helpers.rb +13 -5
  101. metadata +34 -84
@@ -1,9 +1,9 @@
1
1
  module Grape
2
2
  module Exceptions
3
3
  class Base < StandardError
4
-
5
4
  BASE_MESSAGES_KEY = 'grape.errors.messages'
6
5
  BASE_ATTRIBUTES_KEY = 'grape.errors.attributes'
6
+ FALLBACK_LOCALE = :en
7
7
 
8
8
  attr_reader :status, :message, :headers
9
9
 
@@ -14,20 +14,21 @@ module Grape
14
14
  end
15
15
 
16
16
  def [](index)
17
- self.send(index)
17
+ send index
18
18
  end
19
19
 
20
20
  protected
21
+
21
22
  # TODO: translate attribute first
22
23
  # if BASE_ATTRIBUTES_KEY.key respond to a string message, then short_message is returned
23
24
  # if BASE_ATTRIBUTES_KEY.key respond to a Hash, means it may have problem , summary and resolution
24
- def compose_message(key, attributes = {} )
25
+ def compose_message(key, attributes = {})
25
26
  short_message = translate_message(key, attributes)
26
27
  if short_message.is_a? Hash
27
28
  @problem = problem(key, attributes)
28
29
  @summary = summary(key, attributes)
29
30
  @resolution = resolution(key, attributes)
30
- [ ["Problem", @problem], ["Summary", @summary], ["Resolution", @resolution]].reduce("") do |message, detail_array|
31
+ [["Problem", @problem], ["Summary", @summary], ["Resolution", @resolution]].reduce("") do |message, detail_array|
31
32
  message << "\n#{detail_array[0]}:\n #{detail_array[1]}" unless detail_array[1].blank?
32
33
  message
33
34
  end
@@ -48,19 +49,18 @@ module Grape
48
49
  translate_message("#{key}.resolution", attributes)
49
50
  end
50
51
 
51
-
52
52
  def translate_attribute(key, options = {})
53
- translate("#{BASE_ATTRIBUTES_KEY}.#{key}", { :default => key }.merge(options))
53
+ translate("#{BASE_ATTRIBUTES_KEY}.#{key}", { default: key }.merge(options))
54
54
  end
55
55
 
56
56
  def translate_message(key, options = {})
57
- translate("#{BASE_MESSAGES_KEY}.#{key}", {:default => '' }.merge(options))
57
+ translate("#{BASE_MESSAGES_KEY}.#{key}", { default: '' }.merge(options))
58
58
  end
59
59
 
60
60
  def translate(key, options = {})
61
- ::I18n.translate(key, options)
61
+ message = ::I18n.translate(key, options)
62
+ message.present? ? message : ::I18n.translate(key, options.merge(locale: FALLBACK_LOCALE))
62
63
  end
63
-
64
64
  end
65
65
  end
66
66
  end
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+ module Grape
3
+ module Exceptions
4
+ class IncompatibleOptionValues < Base
5
+ def initialize(option1, value1, option2, value2)
6
+ super(message: compose_message("incompatible_option_values", option1: option1, value1: value1, option2: option2, value2: value2))
7
+ end
8
+ end
9
+ end
10
+ end
@@ -2,12 +2,9 @@
2
2
  module Grape
3
3
  module Exceptions
4
4
  class InvalidFormatter < Base
5
-
6
5
  def initialize(klass, to_format)
7
- super(:message => compose_message("invalid_formatter", :klass => klass, :to_format => to_format))
6
+ super(message: compose_message("invalid_formatter", klass: klass, to_format: to_format))
8
7
  end
9
-
10
8
  end
11
-
12
9
  end
13
10
  end
@@ -1,14 +1,10 @@
1
1
  # encoding: utf-8
2
2
  module Grape
3
3
  module Exceptions
4
-
5
4
  class InvalidVersionerOption < Base
6
-
7
5
  def initialize(strategy)
8
- super(:message => compose_message("invalid_versioner_option", :strategy => strategy))
6
+ super(message: compose_message("invalid_versioner_option", strategy: strategy))
9
7
  end
10
-
11
8
  end
12
-
13
9
  end
14
10
  end
@@ -2,14 +2,9 @@
2
2
  module Grape
3
3
  module Exceptions
4
4
  class InvalidWithOptionForRepresent < Base
5
-
6
5
  def initialize
7
- super(:message => compose_message("invalid_with_option_for_represent"))
6
+ super(message: compose_message("invalid_with_option_for_represent"))
8
7
  end
9
-
10
8
  end
11
-
12
9
  end
13
-
14
10
  end
15
-
@@ -2,13 +2,9 @@
2
2
  module Grape
3
3
  module Exceptions
4
4
  class MissingMimeType < Base
5
-
6
5
  def initialize(new_format)
7
- super(:message => compose_message("missing_mime_type", :new_format => new_format))
6
+ super(message: compose_message("missing_mime_type", new_format: new_format))
8
7
  end
9
-
10
8
  end
11
-
12
9
  end
13
-
14
10
  end
@@ -2,12 +2,9 @@
2
2
  module Grape
3
3
  module Exceptions
4
4
  class MissingOption < Base
5
-
6
5
  def initialize(option)
7
- super(:message => compose_message("missing_option", :option => option))
6
+ super(message: compose_message("missing_option", option: option))
8
7
  end
9
-
10
8
  end
11
-
12
9
  end
13
10
  end
@@ -2,12 +2,9 @@
2
2
  module Grape
3
3
  module Exceptions
4
4
  class MissingVendorOption < Base
5
-
6
5
  def initialize
7
- super(:message => compose_message("missing_vendor_option"))
6
+ super(message: compose_message("missing_vendor_option"))
8
7
  end
9
-
10
8
  end
11
-
12
9
  end
13
10
  end
@@ -2,13 +2,9 @@
2
2
  module Grape
3
3
  module Exceptions
4
4
  class UnknownOptions < Base
5
-
6
5
  def initialize(options)
7
- super(:message => compose_message("unknown_options", :options => options))
6
+ super(message: compose_message("unknown_options", options: options))
8
7
  end
9
-
10
8
  end
11
-
12
9
  end
13
-
14
10
  end
@@ -2,11 +2,9 @@
2
2
  module Grape
3
3
  module Exceptions
4
4
  class UnknownValidator < Base
5
-
6
5
  def initialize(validator_type)
7
- super(:message => compose_message("unknown_validator", :validator_type => validator_type))
6
+ super(message: compose_message("unknown_validator", validator_type: validator_type))
8
7
  end
9
-
10
8
  end
11
9
  end
12
10
  end
@@ -6,11 +6,21 @@ module Grape
6
6
  attr_accessor :param
7
7
 
8
8
  def initialize(args = {})
9
- @param = args[:param].to_s if args.has_key? :param
10
- attribute = translate_attribute(@param)
11
- args[:message] = translate_message(args[:message_key], :attribute => attribute)
9
+ raise "Param is missing:" unless args.has_key? :param
10
+ @param = args[:param]
11
+ args[:message] = translate_message(args[:message_key]) if args.has_key? :message_key
12
12
  super
13
13
  end
14
+
15
+ # remove all the unnecessary stuff from Grape::Exceptions::Base like status
16
+ # and headers when converting a validation error to json or string
17
+ def as_json(*args)
18
+ to_s
19
+ end
20
+
21
+ def to_s
22
+ message
23
+ end
14
24
  end
15
25
  end
16
26
  end
@@ -0,0 +1,43 @@
1
+ require 'grape/exceptions/base'
2
+
3
+ module Grape
4
+ module Exceptions
5
+ class ValidationErrors < Grape::Exceptions::Base
6
+ include Enumerable
7
+
8
+ attr_reader :errors
9
+
10
+ def initialize(args = {})
11
+ @errors = {}
12
+ args[:errors].each do |validation_error|
13
+ @errors[validation_error.param] ||= []
14
+ @errors[validation_error.param] << validation_error
15
+ end
16
+ super message: full_messages.join(', '), status: 400
17
+ end
18
+
19
+ def each
20
+ errors.each_pair do |attribute, errors|
21
+ errors.each do |error|
22
+ yield attribute, error
23
+ end
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def full_messages
30
+ map { |attribute, error| full_message(attribute, error) }.uniq
31
+ end
32
+
33
+ def full_message(attribute, error)
34
+ I18n.t(
35
+ "grape.errors.format".to_sym,
36
+ default: "%{attribute} %{message}",
37
+ attribute: translate_attribute(attribute),
38
+ message: error.message
39
+ )
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,14 +1,13 @@
1
1
  module Grape
2
2
  module Formatter
3
3
  module Base
4
-
5
4
  class << self
6
-
7
5
  FORMATTERS = {
8
- :json => Grape::Formatter::Json,
9
- :serializable_hash => Grape::Formatter::SerializableHash,
10
- :txt => Grape::Formatter::Txt,
11
- :xml => Grape::Formatter::Xml
6
+ json: Grape::Formatter::Json,
7
+ jsonapi: Grape::Formatter::Json,
8
+ serializable_hash: Grape::Formatter::SerializableHash,
9
+ txt: Grape::Formatter::Txt,
10
+ xml: Grape::Formatter::Xml
12
11
  }
13
12
 
14
13
  def formatters(options)
@@ -26,7 +25,6 @@ module Grape
26
25
  spec
27
26
  end
28
27
  end
29
-
30
28
  end
31
29
  end
32
30
  end
@@ -2,13 +2,10 @@ module Grape
2
2
  module Formatter
3
3
  module Json
4
4
  class << self
5
-
6
5
  def call(object, env)
7
- return object if object.is_a?(String)
8
6
  return object.to_json if object.respond_to?(:to_json)
9
7
  MultiJson.dump(object)
10
8
  end
11
-
12
9
  end
13
10
  end
14
11
  end
@@ -2,7 +2,6 @@ module Grape
2
2
  module Formatter
3
3
  module SerializableHash
4
4
  class << self
5
-
6
5
  def call(object, env)
7
6
  return object if object.is_a?(String)
8
7
  return MultiJson.dump(serialize(object)) if serializable?(object)
@@ -12,23 +11,24 @@ module Grape
12
11
 
13
12
  private
14
13
 
15
- def serializable?(object)
16
- object.respond_to?(:serializable_hash) ||
17
- object.kind_of?(Array) && !object.map {|o| o.respond_to? :serializable_hash }.include?(false) ||
18
- object.kind_of?(Hash)
19
- end
14
+ def serializable?(object)
15
+ object.respond_to?(:serializable_hash) || object.kind_of?(Array) && !object.map { |o| o.respond_to? :serializable_hash }.include?(false) || object.kind_of?(Hash)
16
+ end
20
17
 
21
- def serialize(object)
22
- if object.respond_to? :serializable_hash
23
- object.serializable_hash
24
- elsif object.kind_of?(Array) && !object.map {|o| o.respond_to? :serializable_hash }.include?(false)
25
- object.map {|o| o.serializable_hash }
26
- elsif object.kind_of?(Hash)
27
- object.inject({}) { |h,(k,v)| h[k] = serialize(v); h }
28
- else
29
- object
18
+ def serialize(object)
19
+ if object.respond_to? :serializable_hash
20
+ object.serializable_hash
21
+ elsif object.kind_of?(Array) && !object.map { |o| o.respond_to? :serializable_hash }.include?(false)
22
+ object.map { |o| o.serializable_hash }
23
+ elsif object.kind_of?(Hash)
24
+ object.inject({}) do |h, (k, v)|
25
+ h[k] = serialize(v)
26
+ h
30
27
  end
28
+ else
29
+ object
31
30
  end
31
+ end
32
32
  end
33
33
  end
34
34
  end
@@ -2,11 +2,9 @@ module Grape
2
2
  module Formatter
3
3
  module Txt
4
4
  class << self
5
-
6
5
  def call(object, env)
7
6
  object.respond_to?(:to_txt) ? object.to_txt : object.to_s
8
7
  end
9
-
10
8
  end
11
9
  end
12
10
  end
@@ -2,12 +2,10 @@ module Grape
2
2
  module Formatter
3
3
  module Xml
4
4
  class << self
5
-
6
5
  def call(object, env)
7
6
  return object.to_xml if object.respond_to?(:to_xml)
8
7
  raise Grape::Exceptions::InvalidFormatter.new(object.class, 'xml')
9
8
  end
10
-
11
9
  end
12
10
  end
13
11
  end
@@ -0,0 +1,26 @@
1
+ module Grape
2
+ class Request < Rack::Request
3
+ def params
4
+ @params ||= begin
5
+ params = Hashie::Mash.new(super)
6
+ if env['rack.routing_args']
7
+ args = env['rack.routing_args'].dup
8
+ # preserve version from query string parameters
9
+ args.delete(:version)
10
+ params.deep_merge!(args)
11
+ end
12
+ params
13
+ end
14
+ end
15
+
16
+ def headers
17
+ @headers ||= env.dup.inject({}) do |h, (k, v)|
18
+ if k.to_s.start_with? 'HTTP_'
19
+ k = k[5..-1].gsub('_', '-').downcase.gsub(/^.|[-_\s]./) { |x| x.upcase }
20
+ h[k] = v
21
+ end
22
+ h
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,18 +1,20 @@
1
1
  en:
2
2
  grape:
3
3
  errors:
4
+ format: ! '%{attribute} %{message}'
4
5
  messages:
5
- coerce: 'invalid parameter: %{attribute}'
6
- presence: 'missing parameter: %{attribute}'
7
- regexp: 'invalid parameter: %{attribute}'
6
+ coerce: 'is invalid'
7
+ presence: 'is missing'
8
+ regexp: 'is invalid'
9
+ values: 'does not have a valid value'
8
10
  missing_vendor_option:
9
11
  problem: 'missing :vendor option.'
10
- summary: 'when version using header, you must specify :verdor option. '
12
+ summary: 'when version using header, you must specify :vendor option. '
11
13
  resolution: "eg: version 'v1', :using => :header, :vendor => 'twitter'"
12
14
  missing_mime_type:
13
15
  problem: 'missing mime type for %{new_format}'
14
16
  resolution:
15
- "you can choose exist mime type from Grape::ContentTypes::CONTENT_TYPES
17
+ "you can choose existing mime type from Grape::ContentTypes::CONTENT_TYPES
16
18
  or add your own with content_type :%{new_format}, 'application/%{new_format}'
17
19
  "
18
20
  invalid_with_option_for_represent:
@@ -25,3 +27,4 @@ en:
25
27
  resolution: 'available strategy for :using is :path, :header, :param'
26
28
  unknown_validator: 'unknown validator: %{validator_type}'
27
29
  unknown_options: 'unknown options: %{options}'
30
+ incompatible_option_values: '%{option1}: %{value1} is incompatible with %{option2}: %{value2}'
@@ -0,0 +1,30 @@
1
+ require 'rack/auth/basic'
2
+
3
+ module Grape
4
+ module Middleware
5
+ module Auth
6
+ class Base < Grape::Middleware::Base
7
+ attr_reader :authenticator
8
+
9
+ def initialize(app, options = {}, &authenticator)
10
+ super(app, options)
11
+ @authenticator = authenticator
12
+ end
13
+
14
+ def base_request
15
+ raise NotImplementedError, "You must implement base_request."
16
+ end
17
+
18
+ def credentials
19
+ base_request.provided? ? base_request.credentials : [nil, nil]
20
+ end
21
+
22
+ def before
23
+ unless authenticator.call(*credentials)
24
+ throw :error, status: 401, message: "API Authorization Failed."
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -3,28 +3,11 @@ require 'rack/auth/basic'
3
3
  module Grape
4
4
  module Middleware
5
5
  module Auth
6
- class Basic < Grape::Middleware::Base
7
- attr_reader :authenticator
8
-
9
- def initialize(app, options = {}, &authenticator)
10
- super(app, options)
11
- @authenticator = authenticator
12
- end
13
-
14
- def basic_request
6
+ class Basic < Grape::Middleware::Auth::Base
7
+ def base_request
15
8
  Rack::Auth::Basic::Request.new(env)
16
9
  end
17
-
18
- def credentials
19
- basic_request.provided?? basic_request.credentials : [nil, nil]
20
- end
21
-
22
- def before
23
- unless authenticator.call(*credentials)
24
- throw :error, :status => 401, :message => "API Authorization Failed."
25
- end
26
- end
27
10
  end
28
11
  end
29
12
  end
30
- end
13
+ end
@@ -3,27 +3,10 @@ require 'rack/auth/digest/md5'
3
3
  module Grape
4
4
  module Middleware
5
5
  module Auth
6
- class Digest < Grape::Middleware::Base
7
- attr_reader :authenticator
8
-
9
- def initialize(app, options = {}, &authenticator)
10
- super(app, options)
11
- @authenticator = authenticator
12
- end
13
-
14
- def digest_request
6
+ class Digest < Grape::Middleware::Auth::Base
7
+ def base_request
15
8
  Rack::Auth::Digest::Request.new(env)
16
9
  end
17
-
18
- def credentials
19
- digest_request.provided?? digest_request.credentials : [nil, nil]
20
- end
21
-
22
- def before
23
- unless authenticator.call(*credentials)
24
- throw :error, :status => 401, :message => "API Authorization Failed."
25
- end
26
- end
27
10
  end
28
11
  end
29
12
  end
@@ -3,21 +3,30 @@ module Grape::Middleware::Auth
3
3
  class OAuth2 < Grape::Middleware::Base
4
4
  def default_options
5
5
  {
6
- :token_class => 'AccessToken',
7
- :realm => 'OAuth API',
8
- :parameter => %w(bearer_token oauth_token),
9
- :accepted_headers => %w(HTTP_AUTHORIZATION X_HTTP_AUTHORIZATION X-HTTP_AUTHORIZATION REDIRECT_X_HTTP_AUTHORIZATION),
10
- :header => [/Bearer (.*)/i, /OAuth (.*)/i]
6
+ token_class: 'AccessToken',
7
+ realm: 'OAuth API',
8
+ parameter: %w(bearer_token oauth_token access_token),
9
+ accepted_headers: %w(HTTP_AUTHORIZATION X_HTTP_AUTHORIZATION X-HTTP_AUTHORIZATION REDIRECT_X_HTTP_AUTHORIZATION),
10
+ header: [/Bearer (.*)/i, /OAuth (.*)/i],
11
+ required: true
11
12
  }
12
13
  end
13
-
14
+
14
15
  def before
15
16
  verify_token(token_parameter || token_header)
16
17
  end
17
18
 
19
+ def request
20
+ @request ||= Grape::Request.new(env)
21
+ end
22
+
23
+ def params
24
+ @params ||= request.params
25
+ end
26
+
18
27
  def token_parameter
19
28
  Array(options[:parameter]).each do |p|
20
- return request[p] if request[p]
29
+ return params[p] if params[p]
21
30
  end
22
31
  nil
23
32
  end
@@ -25,9 +34,7 @@ module Grape::Middleware::Auth
25
34
  def token_header
26
35
  return false unless authorization_header
27
36
  Array(options[:header]).each do |regexp|
28
- if authorization_header =~ regexp
29
- return $1
30
- end
37
+ return $1 if authorization_header =~ regexp
31
38
  end
32
39
  nil
33
40
  end
@@ -38,15 +45,16 @@ module Grape::Middleware::Auth
38
45
  end
39
46
  nil
40
47
  end
41
-
48
+
42
49
  def token_class
43
- @klass ||= eval(options[:token_class])
50
+ @klass ||= eval(options[:token_class]) # rubocop:disable Eval
44
51
  end
45
-
52
+
46
53
  def verify_token(token)
47
- if token = token_class.verify(token)
54
+ token = token_class.verify(token)
55
+ if token
48
56
  if token.respond_to?(:expired?) && token.expired?
49
- error_out(401, 'expired_token')
57
+ error_out(401, 'invalid_grant')
50
58
  else
51
59
  if !token.respond_to?(:permission_for?) || token.permission_for?(env)
52
60
  env['api.token'] = token
@@ -54,19 +62,18 @@ module Grape::Middleware::Auth
54
62
  error_out(403, 'insufficient_scope')
55
63
  end
56
64
  end
57
- else
58
- error_out(401, 'invalid_token')
65
+ elsif !!options[:required]
66
+ error_out(401, 'invalid_grant')
59
67
  end
60
68
  end
61
-
69
+
62
70
  def error_out(status, error)
63
71
  throw :error,
64
- :message => error,
65
- :status => status,
66
- :headers => {
67
- 'WWW-Authenticate' => "OAuth realm='#{options[:realm]}', error='#{error}'"
68
- }
72
+ message: error,
73
+ status: status,
74
+ headers: {
75
+ 'WWW-Authenticate' => "OAuth realm='#{options[:realm]}', error='#{error}'"
76
+ }
69
77
  end
70
78
  end
71
79
  end
72
-
@@ -27,14 +27,13 @@ module Grape
27
27
 
28
28
  # @abstract
29
29
  # Called before the application is called in the middleware lifecycle.
30
- def before; end
30
+ def before
31
+ end
32
+
31
33
  # @abstract
32
34
  # Called after the application is called in the middleware lifecycle.
33
35
  # @return [Response, nil] a Rack SPEC response or nil to call the application afterwards.
34
- def after; end
35
-
36
- def request
37
- Rack::Request.new(self.env)
36
+ def after
38
37
  end
39
38
 
40
39
  def response
@@ -54,9 +53,10 @@ module Grape
54
53
  end
55
54
 
56
55
  def mime_types
57
- content_types.invert
56
+ content_types.each_with_object({}) { |(k, v), types_without_params|
57
+ types_without_params[k] = v.split(';').first
58
+ }.invert
58
59
  end
59
-
60
60
  end
61
61
  end
62
62
  end