tfranzel / drf-spectacular

Sane and flexible OpenAPI 3 schema generation for Django REST framework.
https://drf-spectacular.readthedocs.io
BSD 3-Clause "New" or "Revised" License
2.4k stars 266 forks source link

SimpleJWT Endpoints Incorrectly Using The Same Component Schema #1333

Open JPGarCar opened 6 hours ago

JPGarCar commented 6 hours ago

Describe the bug The schema yml file created by running the spectacular CLI is using the same component for the requestBody and response when each one should be different as they each have different values.

For example, SimpleJWT's token/refresh endpoint only needs the "refresh" value, and the response should only include the "access" value.

However, the created schema creates the following Component Schema:

    TokenRefresh:
      type: object
      properties:
        access:
          type: string
          readOnly: true
        refresh:
          type: string
          writeOnly: true
      required:
      - access
      - refresh

and both the requestBody and response reference that component schema.

  /api/token/refresh/:
    post:
      operationId: token_refresh_create
      description: |-
        Takes a refresh type JSON web token and returns an access type JSON web
        token if the refresh token is valid.
      tags:
      - token
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TokenRefresh'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/TokenRefresh'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/TokenRefresh'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenRefresh'
          description: ''

This leads to my API Client to think I need both the access and refresh values when calling this endpoint.

To Reproduce

DRF and SimpleJWT are both installed and in use.

This is the command I used to create the yml file: python manage.py spectacular --color --file schema.yml

My Spectacular Settings:

SPECTACULAR_SETTINGS = {
    "TITLE": "Intramural Information Management Ecosystem API",
    "DESCRIPTION": "Intramural Information Management API",
    "VERSION": "0.0.1",
    "SERVE_INCLUDE_SCHEMA": False,
}

My REST Framework Settings:

REST_FRAMEWORK = {
    "DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.DjangoModelPermissions"],
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "rest_framework_simplejwt.authentication.JWTAuthentication",
    ),
    "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
}

Expected behavior The schema should use two different components, one for the requestBody and one for the response.

Thank you in advance :).

tfranzel commented 6 hours ago

Hi, the TokenRefresh is perfectly fine like that. It is just that your generated client is buggy, which is not that uncommon.

Many code generators have trouble with this aspect, which is why we generally recommend enabling component split ('COMPONENT_SPLIT_REQUEST': True) globally for schemas that are to be used with code generators. Usually this will produce vastly better generated code.

https://drf-spectacular.readthedocs.io/en/latest/client_generation.html