hanami/controller

validation symbolises params but only in test env

Closed this issue · 6 comments

diawl commented

I have an endpoint accepts messages from a queue.
If I use the following messages in post request with postman(post body format is raw, application/json):

{
	"Records": 
	[
		{
			"eventName": "ObjectCreated:Put", 
			"s3": {
				"bucket": {
					"name": "some bucket"
				}, 
				"object": {
					"key": "blahblahblah.csv"
				}
			}
		}
	]
}

in my controller, params[:Records] will give me:

[{"eventName"=>"ObjectCreated:Put", "s3"=>{"bucket"=>{"name"=>"some bucket"}, "object"=>{"key"=>"blahblahblah.csv"}}}]

all keys are still string like input.
In my unit test, I have params and action like below:

let(:params) do
  {
    'Records' =>
    [
      {
        'eventName' => 'ObjectCreated',
        's3' => {
          'bucket' => {
            'name' => 'bucket name'
          },
          'object' => {
            'key' => 'file name'
          }
        }
      }
    ]
  }
end
subject { Worker::Controllers::Events::Create.new.call(params) }

if I call the action, I will get:

[{:eventName=>"ObjectCreated", :s3=>{:bucket=>{:name=>"bucket name"}, :object=>{:key=>"file name"}}}]

All keys are symbolised.

I found out this will only happen if I have params validation.
Here is my validation:

required(:Records).each do
  schema do
    required(:eventName).filled { str? }
    optional(:s3).filled do
      schema do
        required(:bucket).filled do
          schema do
            required(:name).filled
          end
        end
        required(:object).filled do
          schema do
            required(:key).filled
          end
        end
      end
    end
  end
end

The different behaviours between a real request and a test call make me confused. I don't know whether I wrote my test in the right way. Based on what I saw in action guides, I expect those two inputs give me the same format of params.

Heya @diawl ! Thanks for your report. A couple of questions:

  • What is the version of controller that are you using?
  • Did you setup a body parser on your hanami application?
diawl commented

hi @mereghost

to answer your questions:

  • I'm using hanami-controller (1.0.0).

  • I didn't know about parser until you mentioned it. Then I searched parser in my codebase, here is something I found might be related, it's in application.rb:

# Default format for the requests that don't specify an HTTP_ACCEPT header
# Argument: A symbol representation of a mime type, defaults to :html
#
default_request_format :json

# Default format for responses that don't consider the request format
# Argument: A symbol representation of a mime type, defaults to :html
#
default_response_format :json

# HTTP Body parsers
# Parse non GET responses body for a specific mime type
# Argument: Symbol, which represent the format of the mime type
#             (only `:json` is supported)
#           Object, the parser
#
body_parsers :json

@diawl If you call params.validate do you get the correct behaviour?

@diawl I implemented a fix for your problem. Could you check if it fixes your problem?

diawl commented

@mereghost
It works well if I call params.valid?
This is the only validation method I called.

I will check the commit and come back to you soon, thank you.

diawl commented

@mereghost I tested your commit. It works well. Params are whitelisted and symbolised properly.