Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Request params parser #9

Merged
merged 13 commits into from

2 participants

@myronmarston

This is a new interpol tool that does two things:

  • Validates request params according to a schema definition.
  • Parses request params based on a schema definition.

Can I get a code review, @proby? /cc @waltjones @tithonium @dudleycarr

@proby proby commented on the diff
lib/interpol/request_params_parser.rb
((103 lines not shown))
+ def no_additional_properties?
+ [
+ @endpoint_definition.path_params,
+ @endpoint_definition.query_params
+ ].none? { |params| params['additionalProperties'] }
+ end
+
+ STRING_EQUIVALENTS = {
+ 'string' => nil,
+ 'integer' => { 'type' => 'string', 'pattern' => '^\-?\d+$' },
+ 'number' => { 'type' => 'string', 'pattern' => '^\-?\d+(\.\d+)?$' },
+ 'boolean' => { 'type' => 'string', 'enum' => %w[ true false ] },
+ 'null' => { 'type' => 'string', 'enum' => [''] }
+ }
+
+ def adjusted_schema(schema)
@proby
proby added a note

This method name + parameter seems a little clumsy. I don't have a better suggestion off the top of my head though.

@myronmarston Owner

I agree but don't have any better ideas.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@proby proby commented on the diff
lib/interpol/request_params_parser.rb
((33 lines not shown))
+
+ def validate!(params)
+ @validator.validate!(params)
+ end
+
+ # Private: This takes care of the validation.
+ class ParamValidator
+ def initialize(endpoint_definition)
+ @endpoint_definition = endpoint_definition
+ @params_schema = build_params_schema
+ end
+
+ def validate_path_params_valid_for_route!
+ route = @endpoint_definition.route
+ invalid_params = property_defs_from(:path_params).keys.reject do |param|
+ route =~ %r</:#{Regexp.escape(param)}(/|$)>
@proby
proby added a note

It's initially confusing what this does.

@myronmarston Owner

This looks at your route definition and validates that every defined path_param is actually a :blah param in the route string. Maybe it's not needed but I figured it was good to verify that the path_params you have defined are in fact part of the routing path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@proby proby commented on the diff
lib/interpol/request_params_parser.rb
((176 lines not shown))
+ end
+ end
+
+ NULLS = { '' => nil, nil => nil }
+ def self.convert_null(value)
+ NULLS.fetch(value) do
+ raise ArgumentError, "#{value} is not convertable to null"
+ end
+ end
+
+ def self.convert_date(value)
+ unless value =~ /\A\d{4}\-\d{2}\-\d{2}\z/
+ raise ArgumentError, "Not in iso8601 format"
+ end
+
+ Date.new(*value.split('-').map(&:to_i))
@proby
proby added a note

Why did you use this instead of Date.parse(value)?

@myronmarston Owner

Historically, Date.parse has been quite slow. I think it's a lot better in 1.9.3 than prior versions of ruby (I think I heard it's in C now), but this should still be faster, I think. Date.parse handles many different date formats, and it has to be tolerant of you using any of them. Here we know that we have 3 integers, which is exactly what the normal constructor needs, so we can bypass the complicated parsing logic entirely.

@myronmarston Owner

BTW, I originally used Date.iso8601(value) but that doesn't work on 1.8.7.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@proby proby commented on the diff
lib/interpol/sinatra/request_params_parser.rb
((49 lines not shown))
+ available_versions ||= endpoint.available_versions
+ interpol_config.api_version_for(env, endpoint).tap do |_version|
+ version ||= _version
+ end
+ end
+
+ if definition == DefinitionFinder::NoDefinitionFound
+ interpol_config.request_version_unavailable(self, version, available_versions)
+ end
+
+ definition
+ end
+ end
+
+ def params
+ @_parsed_params || super
@proby
proby added a note

Why did you add the first underscore to this variable name?

@myronmarston Owner

These instance variables live in the same space as the instance variables in an end-user's Sinatra application. I used the underscore prefix to minimize the likelihood of a naming collision.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@myronmarston myronmarston merged commit f8605e9 into master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.