mattpolzin / OpenAPIKit

Codable Swift OpenAPI implementation.
MIT License
281 stars 35 forks source link

Fails to decode a `$ref` to a response component inside another response component #377

Open edonv opened 1 month ago

edonv commented 1 month ago

While using the Swift OpenAPI generator, I was having problems generating code from my spec file. Error message: Found at least one vendor extension property that does not begin with the required 'x-' prefix. Invalid properties: [ $ref ].

I finally was able to find where the problem was by setting a breakpoint inside Yams's YAMLDecoder's decode function, and inspecting the underlyingError for the CodingPath. This led to the MissingToken401's $ref field. Originally, I thought the problem was that it didn't like having an overriding description field, but with that removed, it said it was missing a description field.

The OpenAPI spec says it supports $refs in any of the components (minus the schemas component section), so this should be supported.

If I'm missing something, let me know.

Here's the section:

responses:
  AbortError:
    description: An error that conforms to Vapor's AbortError type.
    content:
      application/json:
        schema: 
          type: object
          required: 
            - error
          properties: 
            error:
              type: boolean
              enum:
                - true
            reason:
              type: string
              description: Describes the reason for the error.
    headers:
      "X-Self-Server-Error-Code":
        description: Self-Server-specific error codes.
        schema: 
          type: number
  MissingToken401:
    $ref: "#/components/responses/AbortError"
    description: Unauthorized request, either having an expired session JWT, or it's missing altogether.
  RestrictedLibraryAccessNotAssociatedDevice403:
    $ref: "#/components/responses/AbortError"
    description: Operation not accessible from device not associated with the Library specified in the session JWT.
  NoLibraryFound404:
    $ref: "#/components/responses/AbortError"
    description: Could not find a Library with the provided ID.
  UploadReqMissingMultipartBoundary400:
    $ref: "#/components/responses/AbortError"
    description: 'Could not find "boundary" parameter in multipart header.'
  UploadReqInternalError500:
    $ref: "#/components/responses/AbortError"
    description: Internal error while trying to facilitate file transfer. Need to try again.
mattpolzin commented 1 month ago

You are quite right. The current implementation in OpenAPIKit does not support reference objects for values within the components object like it should.

Superficially, this won’t be too hard to fix (though it will impact other parts of the codebase that need to know how to navigate the components object). Unfortunately, it is also a breaking change even though it fixes a bug with our adherence to the OpenAPI specification.

This should get fixed by pull request to the release/4_0 branch. I can’t say exactly when I’ll do this, but it seems important enough for me to tackle next unless someone beats me to it. Once I fix the bug, it will be a matter of collaborating with the folks working on the generator to determine when they want to switch from pointing to OpenAPIKit 3.x to an OpenAPIKit 4.0 alpha, beta, or release commit.

mattpolzin commented 1 month ago

Since there is an indeterminate horizon on the fix landing downstream where you can use it to generate code, I’d be happy to brainstorm workarounds for you if that is helpful.

edonv commented 1 month ago

Ah ok, that makes sense. I'm happy to not worry about it right now, especially as it seems to let me reference schemas from inside other schema definitions in the components object. It seemed to be a specific problem for responses, so I'll just comment it out for now and follow updates on the generator repo.