swagger-ui icon indicating copy to clipboard operation
swagger-ui copied to clipboard

Incorrect Representation of Webhook Payloads

Open dontic opened this issue 1 year ago • 2 comments

Q&A (please complete the following information)

  • OS: N/A
  • Browser: N/A
  • Version: N/A
  • Method of installation: N/A
  • Swagger-UI version: 5.17.14
  • Swagger/OpenAPI version: OpenAPI 3.1

Content & configuration

Example Swagger/OpenAPI definition:

openapi: 3.1.0
info:
  title: Example API with Webhook
  version: 1.0.0
paths:
  /api/data:
    get:
      summary: Get data
      responses:
        '200':
          description: Successful response
          content:
            application/json:    
              schema:
                $ref: '#/components/schemas/ComplexData'
    post:
      summary: Create data
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ComplexData'
      responses:
        '201':
          description: Successfully created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ComplexData'
webhooks:
  newData:
    post:
      summary: New data webhook
      description: Webhook for new data
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ComplexData'
      responses:
        '200':
          description: Webhook received successfully

components:
  schemas:
    NestedData:
      type: object
      properties:
        id:
          type: integer
          readOnly: true
        name:
          type: string
        internalCode:
          type: string
          writeOnly: true
      required:
        - name

    ComplexData:
      type: object
      properties:
        title:
          type: string
        description:
          type: string
        createdAt:
          type: string
          format: date-time
          readOnly: true
        nestedData:
          type: array
          items:
            $ref: '#/components/schemas/NestedData'
      required:
        - title
        - nestedData

Describe the bug you're encountering

Swagger UI seems to incorrectly display webhook payloads when using shared schemas with readOnly and writeOnly properties, or more complex schema definitions.

For webhooks, because the schema is defined from a POST perspective, the "request" version of the schema is displayed, where it should really be the "response" version of the schema. The same representation you would get from defining a GET endpoint with that schema.

This leads to inaccurate documentation of webhook payloads.

To reproduce...

You can reproduce this behavior by copying the OpenAPI definition above and pasting it in the swagger editor.

Then comparing the GET response from the data endpoint and the newData webhook payload.

You can also see how the newData webhook payload is the same as the requested data from the POST data endpoint.

Expected behavior

When documenting webhooks, Swagger UI should use the same version of the schema as a GET definition, omitting writeOnly fields, displaying readOnly fields and any other relevant aspects of a GET definition.

Impact

This issue causes confusion for API consumers, as the displayed webhook payload in Swagger UI does not accurately reflect the data that will be sent by the webhook in practice.

Possible Solution

Introduce a way to specify or infer the direction of data flow for webhooks, allowing Swagger UI to correctly interpret readOnly and writeOnly properties in this context.

Temporary workaround

The only decent workaround I found is to define specific schemas for webhook payloads. This is not ideal though as it causes code repetition and can clutter a definition while potentially confusing API consumers.

Additional context or thoughts

This issue was brought up in OpenAPI:

  • https://github.com/OAI/OpenAPI-Specification/issues/3563

The discussion seems to conclude that tools such as SwaggerUI should be the ones responsible to interpret this correctly.

Relevant issues describing similar problems:

  • https://github.com/swagger-api/swagger-ui/issues/8694
  • https://github.com/swagger-api/swagger-ui/issues/6294

Relevant issues and some fixes from other tools:

  • https://github.com/rapi-doc/RapiDoc/issues/727
  • https://github.com/tfranzel/drf-spectacular/issues/1280
  • https://github.com/Redocly/redoc/issues/1720

dontic avatar Aug 30 '24 09:08 dontic

Hi @dontic , this is a pickle :D readOnly is a weird one. To be clear, you're looking at the generated JSON samples, when you say things are "missing"?

ponelat avatar Aug 30 '24 12:08 ponelat

Hi @ponelat , I know... this topic is quite confusing and, because OpenAPI doesn't provide specific guidance, every UI tool is doing what they think is best, creating inconsistencies across them.

I'm not sure that I said there's anything missing but rather that, indeed, the JSON sample on the webhook should be the response representation of the schema rather than the request representation.

In the example of my original post you can how the sample on the GET endpoint response:

image

Compares to the JSON on the webhook payload:

image

When in reality the webhook payload should be the same data as the GET endpoint since you're sending that exact data through it, not requesting it.

Tools like Redoc and RapiDoc seem to have fixed this:

  • https://github.com/Redocly/redoc/issues/1720
  • https://github.com/rapi-doc/RapiDoc/issues/727

dontic avatar Aug 31 '24 07:08 dontic

Thanks @dontic , the team agree that this should be inverse. The changes to the code may be challenging, but will take a look to see what can be done.

ponelat avatar Dec 27 '24 12:12 ponelat

Thanks @dontic , the team agree that this should be inverse. The changes to the code may be challenging, but will take a look to see what can be done.

Please do let me know if I can help in any way, I'm not familiar with the code but I can support either with testing or docs.

dontic avatar Jan 08 '25 15:01 dontic