Module: Sinatra::Swagger::ParamValidator

Defined in:
lib/sinatra/swagger/param_validator.rb

Class Method Summary collapse

Class Method Details

.registered(app) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/sinatra/swagger/param_validator.rb', line 6

def self.registered(app)
  app.register Swagger::SwaggerLinked

  app.helpers do
    def invalid_params(invalidities)
      error_response(
        'invalid_params',
        'Some of the given parameters were invalid according to the Swagger spec.',
        details: { invalidities: invalidities },
        status: 400
      )
    end

    def invalid_content_type(acceptable)
      error_response(
        'invalid_content',
        'The ',
        details: {
          content_types: {
            acceptable: acceptable,
            given: request.content_type
          }
        },
        status: 400
      )
    end

    def error_response(code, dev_message, details: {}, status: 400)
      content_type :json
      halt(status,{
        error: code,
        developerMessage: dev_message,
        details: details
      }.to_json)
    end
  end

  app.before do
    next if swagger_spec.nil?
    _, captures, spec = swagger_spec.values
    invalid_content_type(spec['consumes']) if spec['consumes'] && !spec['consumes'].include?(request.content_type)

    unknown_params = params.keys.select { |k| k.is_a?(String) }

    invalidities = Hash[(spec['parameters'] || []).map { |details|
      param_name = details['name']
      unknown_params.delete(param_name)

      parameter = case details['in']
      when "query"
        params[param_name]
      when "path"
        captures[param_name]
      when "body"
        request.body.rewind
        params[:body] = request.body.read
        next nil unless request.content_type =~ %r{^application/(?:.+\+)?json}

        begin
          params[:body] = JSON.parse(params[:body])
        rescue JSON::ParserError
          next ['POST body', :invalid_json]
        end
        next nil unless details['schema']

        schema = details['schema'].merge('definitions' => settings.swagger['definitions'])
        errors = JSON::Validator.fully_validate(schema, params[:body])
        next errors.empty? ? nil : ['POST body', errors]
      else
        # other param types aren't dealt with at the moment
        next
      end

      if !parameter
        next [param_name, :missing] if details['required'] && details['required'] != "false"
        next unless details['default']
        parameter = details['default']
      end

      begin
        parameter = ::Swagger.cast(parameter.to_s, details['type']) if parameter
      rescue ArgumentError
        next [param_name, :incorrect_type]
      end

      if %w{integer number}.include? details['type']
        too_large = details['maximum'] && parameter > details['maximum']
        too_small = details['minimum'] && parameter < details['minimum']
        next [param_name, :out_of_range] if too_large || too_small
      end

      params[param_name] = parameter

      nil
    }.compact]

    if invalidities.any?
      unknown_params.each { |p| invalidities[p] = :unexpected_key }
      invalid_params(invalidities)
    end
  end
end