preaction / Yancy

The Best Web Framework Deserves the Best Content Management System
http://preaction.me/yancy/
Other
54 stars 21 forks source link

swagger.io error messages on generated api spec #38

Closed mario-minati closed 5 years ago

mario-minati commented 5 years ago

I copied the generated api spec (/yanya/api) into Swagger online editor and go some errors:

Semantic error at definitions.Project.properties.description.type
Schema "type" key must be a string
Jump to line 12
Schema error at info.version
should be string
Jump to line 48
Semantic error at paths./Project.get.parameters.0.$ref
$ref values must be RFC3986-compliant percent-encoded URIs
Jump to line 70
Semantic error at paths./Project.get.parameters.1.$ref
$ref values must be RFC3986-compliant percent-encoded URIs
Jump to line 71
Semantic error at paths./Project.get.parameters.2.$ref
$ref values must be RFC3986-compliant percent-encoded URIs
Jump to line 72

The generated spec looks like this:

basePath: /yancy/api
consumes:
  - application/json
definitions:
  Project:
    properties:
      abbreviation:
        type: string
        x-order: 3
      description:
        type:
          - string
          - 'null'
        x-order: 4
      id:
        type: integer
        x-order: 1
      name:
        type: string
        x-order: 2
      projectnumber:
        type: string
        x-order: 5
    required:
      - name
      - abbreviation
      - projectnumber
    type: object
  _Error:
    properties:
      errors:
        items:
          properties:
            message:
              description: Human readable description of the error
              type: string
            path:
              description: JSON pointer to the input data where the error occur
              type: string
          required:
            - message
        type: array
    title: OpenAPI Error Object
    type: object
host: 'localhost:3000'
info:
  title: Yancy
  version: 1
parameters:
  $limit:
    description: The number of items to return
    in: query
    name: $limit
    type: integer
  $offset:
    description: The index (0-based) to start returning items
    in: query
    name: $offset
    type: integer
  $order_by:
    description: 'How to sort the list. A string containing one of "asc" (to sort in ascending order) or "desc" (to sort in descending order), followed by a ":", followed by the field name to sort by.'
    in: query
    name: $order_by
    pattern: '^(?:asc|desc):[^:,]+$'
    type: string
paths:
  /Project:
    get:
      parameters:
        - $ref: '#/parameters/$limit'
        - $ref: '#/parameters/$offset'
        - $ref: '#/parameters/$order_by'
        - description: 'Filter the list by the id field. By default, looks for rows containing the value anywhere in the column. Use ''*'' anywhere in the value to anchor the match.'
          in: query
          name: id
          type: integer
        - description: 'Filter the list by the projectnumber field. By default, looks for rows containing the value anywhere in the column. Use ''*'' anywhere in the value to anchor the match.'
          in: query
          name: projectnumber
          type: string
        - description: 'Filter the list by the name field. By default, looks for rows containing the value anywhere in the column. Use ''*'' anywhere in the value to anchor the match.'
          in: query
          name: name
          type: string
        - description: 'Filter the list by the description field. By default, looks for rows containing the value anywhere in the column. Use ''*'' anywhere in the value to anchor the match.'
          in: query
          name: description
          type: string
        - description: 'Filter the list by the abbreviation field. By default, looks for rows containing the value anywhere in the column. Use ''*'' anywhere in the value to anchor the match.'
          in: query
          name: abbreviation
          type: string
      responses:
        '200':
          description: List of items
          schema:
            properties:
              items:
                description: This page of items
                items:
                  $ref: '#/definitions/Project'
                type: array
              total:
                description: The total number of items available
                type: integer
            required:
              - items
              - total
            type: object
        '400':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '401':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '404':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '500':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '501':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/_Error'
      x-mojo-to:
        action: list_items
        collection: Project
        controller: 'Yancy::API'
    post:
      parameters:
        - in: body
          name: newItem
          required: true
          schema:
            $ref: '#/definitions/Project'
      responses:
        '201':
          description: Entry was created
          schema:
            $ref: '#/definitions/Project/properties/id'
        '400':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '401':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '404':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '500':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '501':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/_Error'
      x-mojo-to:
        action: add_item
        collection: Project
        controller: 'Yancy::API'
  '/Project/{id}':
    delete:
      description: Delete a single item
      responses:
        '204':
          description: Item was deleted
        '400':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '401':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '404':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '500':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '501':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/_Error'
      x-mojo-to:
        action: delete_item
        collection: Project
        controller: 'Yancy::API'
        id_field: id
    get:
      description: Fetch a single item
      responses:
        '200':
          description: Item details
          schema:
            $ref: '#/definitions/Project'
        '400':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '401':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '404':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '500':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '501':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/_Error'
      x-mojo-to:
        action: get_item
        collection: Project
        controller: 'Yancy::API'
        id_field: id
    parameters:
      - description: The id of the item
        in: path
        name: id
        required: true
        type: string
        x-mojo-placeholder: '*'
    put:
      description: Update a single item
      parameters:
        - in: body
          name: newItem
          required: true
          schema:
            $ref: '#/definitions/Project'
      responses:
        '200':
          description: Item was updated
          schema:
            $ref: '#/definitions/Project'
        '400':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '401':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '404':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '500':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        '501':
          description: Default response.
          schema:
            $ref: '#/definitions/_Error'
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/_Error'
      x-mojo-to:
        action: set_item
        collection: Project
        controller: 'Yancy::API'
        id_field: id
produces:
  - application/json
schemes:
  - http
swagger: '2.0'
x-bundled: {}

Especially the unescaped $limit and thelike looks like a yancy bug?

preaction commented 5 years ago

The refs can be fixed by changing the $ to %24 yes.

The type: [ ... ] is valid for JSON schema but not OpenAPI, and will need to be translated to OpenAPI (Yancy uses JSON schema, which I thought was compatible...). Except, OpenAPI 2.0 doesn't even support null as a type, so this is completely wrong. OpenAPI 3.0 supports nullable: true, but Mojolicious::Plugin::OpenAPI doesn't support OpenAPI 3.0. So I'm not sure what to do here except to remove the array while creating the OpenAPI schema, and then use the tests to find the problems that result...

mario-minati commented 5 years ago

I guess we have to live with the type: [ ... ] problem as long as final OpenAPI 3.0 spec is not here.

preaction commented 5 years ago

No, I still think the correct way forward is to consider collections as JSON schema (which will make more sense when it's renamed schema in v2), and do some translating into a proper OpenAPI spec as necessary. I'll fix the URL encoding and make a new ticket with a path forward for that part.

mario-minati commented 5 years ago

Ok, great 👍

mohawk2 commented 5 years ago

Just to link up all the issues and suchlike: #59 adds a private bit of code _openapi_spec_from_schema that converts between the two spec types. It has a bit of currently-commented code to de-array any array types. My rationale for leaving it commented is that the JSON schema for OpenAPI 2 (unlike swagger.io, and the human-readable spec) actually allows array types. If we want to uncomment the code, obviously that will be super-easy.