swagger-api / swagger-parser

Swagger Spec to Java POJOs
http://swagger.io
Apache License 2.0
777 stars 525 forks source link

Unable to parse Parameter $ref with cross-path references #2116

Open ludovicianul opened 1 month ago

ludovicianul commented 1 month ago
Description

When parsing the Parameters section from an operation, cross-path reference parameters are ignored. This is not consistent with other elements which are properly included in the final OpenAPI object.

swagger-parser version

Version 2.1.22

OpenAPI declaration file content or url
"/attribute/{namespace}":
    delete:
      description: |
        Delete an attribute namespace and all attributes below.

        This operation is the same as the one defined with [DELETE /attribute/{namespace}/_meta](#/Attributes/delete_attribute__namespace___meta).
      parameters:
        - $ref: "#/paths/~1attribute~1%7Bnamespace%7D/get/parameters/0"

Full spec file is here: https://github.com/APIs-guru/openapi-directory/blob/main/APIs/opensuse.org/obs/2.10.50/openapi.yaml

Generation Details

Use the following code:

        OpenAPIParser openAPIV3Parser = new OpenAPIParser();
        ParseOptions options = new ParseOptions();
        options.setResolve(true);
        options.setFlatten(true);

        OpenAPI openAPI = openAPIV3Parser.readContents(Files.readString(Paths.get("openapi.yaml")), null, options).getOpenAPI();
        PathItem pathItem = openAPI.getPaths().get("/attribute/{namespace}");

You can then check the Parameters list of the DELETE operation is empty instead of having one parameter.

Steps to reproduce

See above

Suggest a fix

The issue seems to be this code from the io.swagger.v3.parser.processors.ParameterProcessor class:

    if (parameter.get$ref().startsWith("#") && parameter.get$ref().indexOf("#/components/parameters") <= -1) {
                    //TODO: Not possible to add warning during resolve doesn't accept result as an input. Hence commented below line.
                    //result.warning(location, "The parameter should use Reference Object to link to parameters that are defined at the OpenAPI Object's components/parameters.");
                    continue;
                }

Which only includes refs that are from the components section. One possible fix is that it should just include parameters that are referencing other paths 'as is' rather than trying to solve it.

ludovicianul commented 1 month ago

This is a simpler yaml to reproduce the issue:

openapi: "3.0.0"
info:
  version: 1.0.0
  title: Swagger Petstore
  description: A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.0 specification
  termsOfService: http://swagger.io/terms/
  contact:
    name: Swagger API Team
    email: apiteam@swagger.io
    url: http://swagger.io
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html
servers:
  - url: http://petstore.swagger.io/api
paths:
  "/attribute/{namespace}":
    delete:
      description: |
        Delete an attribute namespace and all attributes below.

        This operation is the same as the one defined with [DELETE /attribute/{namespace}/_meta](#/Attributes/delete_attribute__namespace___meta).
      parameters:
        - $ref: "#/paths/~1attribute~1%7Bnamespace%7D/get/parameters/0"
      responses:
        "200":
          content:
            application/xml; charset=utf-8:
              example:
                code: ok
                summary: Ok
              schema:
                $ref: "#/paths/~1architectures/get/responses/401/content/application~1xml;%20charset=utf-8/schema"
          description: |
            OK. The request has succeeded.

            XML Schema used for body validation: [status.xsd](../schema/status.xsd)
        "401":
          $ref: "#/paths/~1architectures/get/responses/401"
      security:
        - basic_authentication: [ ]
      summary: Delete an attribute namespace and all attributes below.
      tags:
        - Attribute Namespaces
    get:
      description: List all attributes under a given attribute namespace.
      parameters:
        - description: The namespace
          example: OBS_TEST
          in: path
          name: namespace
          required: true
          schema:
            type: string
      responses:
        "200":
          content:
            application/xml; charset=utf-8:
              example:
                count: "2"
                entry:
                  - name: AutoCleanup
                  - name: OwnerRootProject
              schema:
                $ref: "#/paths/~1architectures/get/responses/200/content/application~1xml;%20charset=utf-8/schema"
          description: |
            OK. The request has succeeded.

            XML Schema used for body validation: [directory.xsd](../schema/directory.xsd)
        "401":
          $ref: "#/paths/~1architectures/get/responses/401"
        "404":
          content:
            application/xml; charset=utf-8:
              example:
                code: not_found
                summary: Couldn't find AttribNamespace
              schema:
                $ref: "#/paths/~1architectures/get/responses/401/content/application~1xml;%20charset=utf-8/schema"
          description: Not Found.
      security:
        - basic_authentication: [ ]
      summary: List all attributes below a namespace.
      tags:
        - Attribute Namespaces
  /architectures:
    get:
      description: |
        Get a list of all known architectures known to OBS in general. This is not the list of architectures provided by this instance. Check the schedulers element from the `/configuration` route for this.
      responses:
        "200":
          content:
            application/xml; charset=utf-8:
              example:
                count: "4"
                entry:
                  - name: aarch64
                  - name: armv7l
                  - name: s390x
                  - name: x86_64
              schema:
                properties:
                  count:
                    type: integer
                    xml:
                      attribute: true
                  entry:
                    items:
                      properties:
                        name:
                          type: string
                          xml:
                            attribute: true
                      type: object
                    type: array
                type: object
                xml:
                  name: directory
          description: OK. The request has succeeded.
        "401":
          content:
            application/xml; charset=utf-8:
              examples:
                anonymous_user:
                  summary: Anonymous User
                  value:
                    code: anonymous_user
                    summary: Anonymous user is not allowed here - please login
                authentication_required:
                  summary: Authentication Required
                  value:
                    code: authentication_required
                    summary: Unknown user 'Admin' or invalid password
              schema:
                properties:
                  code:
                    type: string
                    xml:
                      attribute: true
                  data:
                    items:
                      type: string
                    type: array
                  details:
                    type: string
                  summary:
                    type: string
                type: object
                xml:
                  name: status
          description: |
            Unauthorized.

            XML Schema used for body validation: [status.xsd](../schema/status.xsd)
      security:
        - basic_authentication: [ ]
      summary: List all known architectures.
      tags:
        - General Information

Looking with debug, Parameters are not parsed:

Screenshot 2024-08-09 at 14 44 07

But responses are:

[

Screenshot 2024-08-09 at 14 44 18

](url)