xerions / phoenix_swagger

Swagger integration to Phoenix framework
Mozilla Public License 2.0
693 stars 182 forks source link

Type :file and validation does not work #231

Open scflode opened 5 years ago

scflode commented 5 years ago

I am not sure if this is related to this library or more to the ex_json_schema.

If you have an endpoint with a multipart/form-data file upload everything works fine when the validation is disabled. If the validation gets enabled (e.g. PhoenixSwagger.Validator.parse_swagger_schema/1 called in MyApp.Application.start/2) the application cannot start anymore.

The error is as follows:

[info] Application ex_swagger_playground exited: exited in: ExSwaggerPlayground.Application.start(:normal, [])
    ** (EXIT) an exception was raised:
        ** (ExJsonSchema.Schema.InvalidSchemaError) schema did not pass validation against its meta-schema: [%ExJsonSchema.Validator.Error{error: %ExJsonSchema.Validator.Error.AnyOf{invalid: [%ExJsonSchema.Validator.Error.InvalidAtIndex{errors: [%ExJsonSchema.Validator.Error{error: %ExJsonSchema.Validator.Error.Enum{}, path: "#"}], index: 0}, %ExJsonSchema.Validator.Error.InvalidAtIndex{errors: [%ExJsonSchema.Validator.Error{error: %ExJsonSchema.Validator.Error.Type{actual: "string", expected: ["array"]}, path: "#"}], index: 1}]}, path: "#/properties/contents/type"}]
            (ex_json_schema) lib/ex_json_schema/schema.ex:80: ExJsonSchema.Schema.assert_valid_schema/1
            (ex_json_schema) lib/ex_json_schema/schema.ex:67: ExJsonSchema.Schema.resolve_root/1
            (phoenix_swagger) lib/phoenix_swagger/validator.ex:137: anonymous fn/4 in PhoenixSwagger.Validator.collect_schema_attrs/1
            (elixir) lib/enum.ex:1327: Enum."-map/2-lists^map/1-0-"/2
            (elixir) lib/enum.ex:1331: anonymous fn/3 in Enum.map/2
            (stdlib) maps.erl:257: :maps.fold_1/3
            (elixir) lib/enum.ex:1956: Enum.map/2
            (phoenix_swagger) lib/phoenix_swagger/validator.ex:99: PhoenixSwagger.Validator.collect_schema_attrs/1
            (ex_swagger_playground) lib/ex_swagger_playground/application.ex:14: ExSwaggerPlayground.Application.start/2
            (kernel) application_master.erl:277: :application_master.start_it_old/4
** (Mix) Could not start application ex_swagger_playground: exited in: ExSwaggerPlayground.Application.start(:normal, [])
    ** (EXIT) an exception was raised:
        ** (ExJsonSchema.Schema.InvalidSchemaError) schema did not pass validation against its meta-schema: [%ExJsonSchema.Validator.Error{error: %ExJsonSchema.Validator.Error.AnyOf{invalid: [%ExJsonSchema.Validator.Error.InvalidAtIndex{errors: [%ExJsonSchema.Validator.Error{error: %ExJsonSchema.Validator.Error.Enum{}, path: "#"}], index: 0}, %ExJsonSchema.Validator.Error.InvalidAtIndex{errors: [%ExJsonSchema.Validator.Error{error: %ExJsonSchema.Validator.Error.Type{actual: "string", expected: ["array"]}, path: "#"}], index: 1}]}, path: "#/properties/contents/type"}]
            (ex_json_schema) lib/ex_json_schema/schema.ex:80: ExJsonSchema.Schema.assert_valid_schema/1
            (ex_json_schema) lib/ex_json_schema/schema.ex:67: ExJsonSchema.Schema.resolve_root/1
            (phoenix_swagger) lib/phoenix_swagger/validator.ex:137: anonymous fn/4 in PhoenixSwagger.Validator.collect_schema_attrs/1
            (elixir) lib/enum.ex:1327: Enum."-map/2-lists^map/1-0-"/2
            (elixir) lib/enum.ex:1331: anonymous fn/3 in Enum.map/2
            (stdlib) maps.erl:257: :maps.fold_1/3
            (elixir) lib/enum.ex:1956: Enum.map/2
            (phoenix_swagger) lib/phoenix_swagger/validator.ex:99: PhoenixSwagger.Validator.collect_schema_attrs/1
            (ex_swagger_playground) lib/ex_swagger_playground/application.ex:14: ExSwaggerPlayground.Application.start/2
            (kernel) application_master.erl:277: :application_master.start_it_old/4

It looks like either I am doing something silly or the JSON schema library cannot cope with the type :file being set in the swagger_path macro call. If the type is anything else (e.g. :string) it works.

For reproduction I set up a small sample app with the different steps as separate commits (boilerplate, adding Swagger lib, enabling validation): https://github.com/scflode/ex_swagger_playground

It would be cool if someone can have a look and maybe show me a workaround or in the best case come up with a fix (or an idea therefore).

mbuhot commented 5 years ago

@scflode I think the error is related to the :file type used on the body parameter.

It is a valid type for swagger 2.0, but not for Json Schema (https://swagger.io/specification/v2/#dataTypeType)

Primitive data types in the Swagger Specification are based on the types supported by the JSON-Schema Draft 4. Models are described using the Schema Object which is a subset of JSON Schema Draft 4.

An additional primitive data type "file" is used by the Parameter Object and the Response Object to set the parameter type or the response as being a file.

As a workaround perhaps the :file type should be internally replaced with :binary for validation purposes in lib/phoenix_swagger/validator.ex?

naps62 commented 4 years ago

@scflode I hit the same issue, and worked around it by using :formData instead of :body for this particular endpoint

I'm not too familiar with this package, or swagger in general, so I'm not sure if this is even semantically correct. But it sort of works for now