Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Endpoints examples ignored at AsyncAPI docs generation. #933

Closed
strobe opened this issue Jan 6, 2021 · 11 comments
Closed

[BUG] Endpoints examples ignored at AsyncAPI docs generation. #933

strobe opened this issue Jan 6, 2021 · 11 comments

Comments

@strobe
Copy link

strobe commented Jan 6, 2021

Tapir version: ***
0.17.1

Scala version: ***
2.12.12

Describe the bug

Currently, it's possible to specify custom example/s for WebSockets endpoints but that will be ignored during AsyncApi documentation generation.

For instance:

sealed trait WsMessage
case object SomeMessage extends WsMessage

sealed trait WsResponse
case object SomeResponse extends WsResponse
case object SomeResponse2 extends WsResponse

endpoint.get
  .in("ws")
  .info(info)
  .out(webSocketBody[WsMessage, CodecFormat.Json, WsResponse, CodecFormat.Json](AkkaStreams)
    .examples(
      List(
        Example(Flow.fromFunction((in: WsMessage) => SomeResponse()), name = Some("first"), summary = Some("r1")),
        Example(Flow.fromFunction((in: WsMessage) => SomeResponse2()), name = Some("second"), summary = Some("r2")
    )
  )
)

after AsyncApi generation via 'AsyncAPIInterpreter.toAsyncAPI' both examples will be ignored, seems a single example that appears in the result generated directly from WsResponse objects/classes.

What's required to do in order to implement that? Where implementation for this should be added?

@adamw
Copy link
Member

adamw commented Jan 27, 2021

@strobe can you look at the PR #973? It should fix the problem - examples where indeed ignored. To support them, I've added . requestsExample and .responsesExample as these need to be specified separately (there's no way to inspect a Flow for examples).

However, when I paste the generated YAML into the async api playground (https://playground.asyncapi.io/), I get verification errors. I think this must be a problem with the playground, though, as as far as I can see the generated yaml matches the spec.

@strobe
Copy link
Author

strobe commented Jan 27, 2021

@adamw thanks, I will try to test that in the next 2 days and will write feedback here.

I get verification errors.

seems I got those with previous versions too (with v0.17.1)

@adamw adamw closed this as completed in a5df755 Jan 29, 2021
adamw added a commit that referenced this issue Jan 29, 2021
Fix #933: add example support to AsyncAPI
@adamw
Copy link
Member

adamw commented Jan 29, 2021

This is now released in 0.17.8 - let me know how it works :)

@strobe
Copy link
Author

strobe commented Jan 30, 2021

I tested it - works for me.

@adamw Regarding those "async api playground" errors I found that at least one problem is related to wrong indentation on 'examples' and 'contentType'.

as result of docs generation I getting something like this:

asyncapi: 2.0.0
info:
  title: Account Service
  version: 1.0.0
  description: This service is in charge of processing user signups
channels:
  user/signedup:
    subscribe:
      message:
        $ref: '#/components/messages/UserSignedUp'
components:
  messages:
    UserSignedUp:
      payload:
        type: object
        properties:
          displayName:
            type: string
            description: Name of the user
          email:
            type: string
            format: email
            description: Email of the use
      contentType: application/json   
      examples:    
        - displayName: "name1"
          email: "email1@example.com"
        - displayName: "name2"
          email: "email2@example.com"
        - value: ''
          command: LogMessage

but it should be:

asyncapi: 2.0.0
info:
  title: Account Service
  version: 1.0.0
  description: This service is in charge of processing user signups
channels:
  user/signedup:
    subscribe:
      message:
        $ref: '#/components/messages/UserSignedUp'
components:
  messages:
    UserSignedUp:
      payload:
        type: object
        properties:
          displayName:
            type: string
            description: Name of the user
          email:
            type: string
            format: email
            description: Email of the use
        contentType: application/json   
        examples:    
          - displayName: "name1"
            email: "email1@example.com"
          - displayName: "name2"
            email: "email2@example.com"
          - value: ''
            command: LogMessage

@strobe
Copy link
Author

strobe commented Jan 31, 2021

actually not sure, seems the spec doesn't has much info about this. Only one example from spec that suitable looks like:
'Model with Example'

type: object
properties:
  id:
    type: integer
    format: int64
  name:
    type: string
required:
- name
example:
  name: Puma
  id: 1

'example' here at same level as 'properties'

@adamw
Copy link
Member

adamw commented Feb 1, 2021

According to: https://www.asyncapi.com/docs/specifications/2.0.0#messageObject, payload and examples are on the same level. This is reflected in the model: https://github.com/softwaremill/tapir/blob/master/apispec/asyncapi-model/src/main/scala/sttp/tapir/asyncapi/AsyncAPI.scala#L99-L114

However, schemas can also have examples (https://www.asyncapi.com/docs/specifications/2.0.0#schemaObject, https://github.com/softwaremill/tapir/blob/master/apispec/apispec-model/src/main/scala/sttp/tapir/apispec/Schema.scala#L19). These could be two different examples.

Currently tapir doesn't support schema-level examples, though we probably will in the future, when we add an example to tapir's sttp.tapir.Schema object.

The reason for this separation is probably that a single schema can be used in different contexts (e.g. as part of different messages), so you might want to both provide example for the individual building blocks, as well as for the whole message.

@strobe
Copy link
Author

strobe commented Feb 1, 2021

thanks for the clarification, seems it's asyncAPI a parser issue.

@strobe
Copy link
Author

strobe commented Feb 20, 2021

@adamw
there some new info about this issue, please check this asyncapi/spec#501 (comment)
and this example: https://github.com/asyncapi/tck/blob/master/tests/asyncapi-2.0/Message%20Object/valid.yaml

Documentation on the AsyncApi website little outdated and the new version is here https://github.com/asyncapi/asyncapi/blob/master/versions/2.0.0/asyncapi.md#messageObject

So seems the correct way to specify examples on message object is:

components:
  messages:
    UserSignedUp:
      payload:
        type: object
        properties:
          displayName:
            type: string
            description: Name of the user
          email:
            type: string
            format: email
            description: Email of the use
      examples:  
        - payload:
          - displayName: "name1"
            email: "email1@example.com"
          - displayName: "name2"
            email: "email2@example.com"            
      contentType: application/json   

and tricky part: examples that validate against the headers or payload
(schema level examples inside payload also supported)

@adamw
Copy link
Member

adamw commented Mar 4, 2021

Ah, so we need to add payload as the key under examples, right?

@strobe
Copy link
Author

strobe commented Mar 4, 2021

examples there is an array with at least two possible keys "payload" & "header", spec said:
array of key/value pairs where keys MUST be either headers and/or payload so it seems to have only "payload" it's fine but it should be preceded by '-' (maybe it's an array because they wish to allow there multiply 'headers' or 'payloads' items if the payload has something like 'oneOf').

adamw added a commit that referenced this issue Apr 6, 2021
@adamw
Copy link
Member

adamw commented Apr 6, 2021

@strobe should be fixed in next 0.18.x :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants