Core: Swagger doc normalizer does not handle definitions correctly

Created on 5 Apr 2017  ยท  10Comments  ยท  Source: api-platform/core

Hi!

I am trying to define custom swagger docs, definitions are not parsed correctly. For example: If I have only one custom endpoint for resource (PUT), and I define in swagger_context fields parameters and responses, getDefinition never will be called, so definition will not be generated to swagger dump also!

bug unconfirmed โญ EU-FOSSA Hackathon

Most helpful comment

Let's say we have only one endpoint in the entire application. It is defined as custom endpoint (_api_receive: false).

resources:
    My\Bundle\ApiBundle\Model\Category:
        collectionOperations:
            put:
                route_name: api_category_put
                swagger_context:
                    summary: Replaces all existing categories by new array of categories.
                    consumes:
                        - application/json
                    parameters:
                        -
                            name: body
                            in: body
                            schema:
                                $ref: '#/definitions/Category'
                    definitions:
                        Category:
                            type: string
                            required:
                                - id
                            schema:
                                id:
                                    type: string
                                parent_id:
                                    type: string
                    responses:
                        200:
                            description: Operations successful.
                        400:
                            description: Bad request (failed validation).
        itemOperations: []

As a result, DataType definition will not be resolved. (Also not dumped with bin/console api:swagger:export)

screenshot

All 10 comments

Can you provide some failing code?

Let's say we have only one endpoint in the entire application. It is defined as custom endpoint (_api_receive: false).

resources:
    My\Bundle\ApiBundle\Model\Category:
        collectionOperations:
            put:
                route_name: api_category_put
                swagger_context:
                    summary: Replaces all existing categories by new array of categories.
                    consumes:
                        - application/json
                    parameters:
                        -
                            name: body
                            in: body
                            schema:
                                $ref: '#/definitions/Category'
                    definitions:
                        Category:
                            type: string
                            required:
                                - id
                            schema:
                                id:
                                    type: string
                                parent_id:
                                    type: string
                    responses:
                        200:
                            description: Operations successful.
                        400:
                            description: Bad request (failed validation).
        itemOperations: []

As a result, DataType definition will not be resolved. (Also not dumped with bin/console api:swagger:export)

screenshot

I'm having the same issue, $ref is never resolved.

resources:
    App\Entity\SocialLogin:
# ...
        collectionOperations:
# ...
            check:
# ...
                swagger_context:
# ...
                    responses:
                        200:
                            description: "Successful authentication with OAuth2 provider, returning new token"
                            schema:
                                $ref: '#/definitions/Token'
                        201:
                            description: "New user account has been created and confirmed, returning new token"
                            schema:
                                $ref: '#/definitions/Token'
                        401:
                            description: "Connection with existing user's account is not confirmed or was disabled"
definitions:
    Token:
        type: object
        properties:
            token:
                type: string
                description: "JWT authentication token"

Responses has only descriptions, without definitions
screen shot 2018-04-25 at 11 30 41

Could you please provide a little project to reproduce this issue ?

@Simperfit
just put somewhere in resources yaml file root section with definitions and $ref: at place where this definition should be shown - in my example I tried to show definition in Response section - and it is not shown. Please take a look at my example above.

Same issue here too. If you define a 'swagger_definition_name' for a (de)normalization_context and try to use it as $ref in 'parameters' or 'responses' sections won't work.

Case 1: don't overwrite the parameters or responses sections.

resources:
    App\Entity\User:
        normalizationContext: {groups: ['read']}
        denormalizationContext: {groups: ['write']}
        itemOperations:
            get: ~
            delete: ~
            put: ~
            login:
                method: 'POST'
                path: '/auth'
                controller: 'App\Controller\AuthController'
                normalization_context: {groups: ['get_token'], swagger_definition_name: 'GetToken'}
                denormalization_context: {groups: ['login'], swagger_definition_name: 'Login'}
                swagger_context:
                    summary: Generates user access token.
                    description: >
                        General description
        collectionOperations:
            get: ~
            post: ~

Result:

screen shot 2018-08-13 at 16 38 00

screen shot 2018-08-13 at 16 38 15

screen shot 2018-08-13 at 16 44 17

Case 2: overwrite the parameters and responses sections to display the correct name/code and description

resources:
    App\Entity\User:
        normalizationContext: {groups: ['read']}
        denormalizationContext: {groups: ['write']}
        itemOperations:
            get: ~
            delete: ~
            put: ~
            login:
                method: 'POST'
                path: '/auth'
                controller: 'App\Controller\AuthController'
                normalization_context: {groups: ['get_token'], swagger_definition_name: 'GetToken'}
                denormalization_context: {groups: ['login'], swagger_definition_name: 'Login'}
                swagger_context:
                    summary: Generates user access token.
                    description: >
                        General description
                    parameters:
                        - in: body
                          name: credentials
                          required: true
                          schema:
                            $ref: '#/definitions/User-Login'
                          description: The account username and password
                    responses:
                        '200':
                            description: User access token generated
                            schema:
                                $ref: '#/definitions/User-GetToken' 
                        '401':
                            description: 'Bad credentials'
                        '404':
                            description: 'Resource not found'
        collectionOperations:
            get: ~
            post: ~

Result:

screen shot 2018-08-13 at 16 50 12

screen shot 2018-08-13 at 16 50 24

screen shot 2018-08-13 at 16 50 34

Did anyone work this one out? Having the same trouble.

I believe to have the same trouble ;

When you use custom swagger_definition_name, the DocumentationNormalizer will be confused when trying to build resources definitions, especially for sub/children resources :

Let say I have :

/**
 * @ORM\Entity
 *
 * @ApiResource(
 *     collectionOperations={"get"={
 *          "normalization_context"={"groups"={"foo","bar"}, 
             "swagger_definition_name"="list"}
 *     }}
 * )
 */
class Parent {
  /**
   * @var Child
   */
    private $child;

    // ...
}

/**
 * @ORM\Entity
 *
 * @ApiResource(
 *     collectionOperations={"get"={
 *          "normalization_context"={"groups"={"foo","bar"}, 
             "swagger_definition_name"="read"}
 *     }}
 * )
 */
class Child {}

In DocumentationNormalizer::l389, when looking for/generate the child attribute definition, it will look for a swagger_definition_name = Child-list (entityName+swagger def name), and break because none exists (or generate something broken anyway).

I believe the autogen definitionKey should be kept until the end of the doc normalization process where the custom names should be set.

@trsteel88, I ended taking my own advice :
I removed all swagger_definition_name & in a SwaggerDecorator I added a correspondence table between the autogenerated def names & the ones I wanted to use.

Quick & dirty example :

public function normalize($object, $format = null, array $context = array())
{
    /** @var Documentation $docs */
    $docs = $this->decorated->normalize($object, $format, $context);

    // change definitions names
    $docStr = json_encode($docs);
    foreach(self::CUSTOM_DEF_NAMES as $oldDefName => $newDefName) {
        $docStr = str_replace('"#\/definitions\/'. $oldDefName .'"', '"#\/definitions\/'. $newDefName .'"', $docStr);
        $docStr = str_replace('"'. $oldDefName .'"', '"'. $newDefName .'"', $docStr);
    }
    $docs = json_decode($docStr, true);
}

Hope this helps!

Closing this as it seems to be resolved.

Was this page helpful?
0 / 5 - 0 ratings