event-machine icon indicating copy to clipboard operation
event-machine copied to clipboard

Generate messagebox api docs from message json schemas

Open codeliner opened this issue 7 years ago • 12 comments

swagger would be preferred if compatible with json schema draft 4

codeliner avatar May 30 '17 16:05 codeliner

Maybe it is also possible to generate a postman collection

codeliner avatar Oct 17 '17 13:10 codeliner

Interesting blog posts and tooling.

sandrokeil avatar Oct 17 '17 18:10 sandrokeil

check: https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/

codeliner avatar Mar 04 '18 20:03 codeliner

@camuthig took a look at swagger but it cannot be used for a single http messagebox endpoint like https://my.service.com/api/messagebox

Having said this the idea was to build our own UI that shows an API documentation based on messages and query responses described with JSON Schema as well as a way to send messages to that messagebox endpoint with some support on putting together the messages (auto. generated forms based on message schema) Unfortunately, this is a lot of hard work. I evaluated available libraries but I don't think they will help us much and I can imagine that we will need to spend a lot of time to fix edge cases and wrong interpretation of JSON schema. Something I'd like to avoid because we all have limited time. And this is really no area where I want to spend more time than necessary.

@camuthig Do you think something like this can work with swagger:

POST https://my.service.com/api/messagebox/Cmd.Ns.DoSomething message/request body schema: {type: object, properties: {payload: ..., metadata: ..., ...}}

POST https://my.service.com/api/messagebox/Query.Ns.GetSomething message/request body schema: {type: object, properties: {payload: ..., metadata: ..., ...}}

Return Type/Response: {type: array, item: { ... }}

for queries we could also do something like this:

GET https://my.service.com/api/messagebox/Query.Ns.GetSomething Query Param: filter: {type: string, minLength: 3}

which is then added to the payload of the query message

We just need to tweak the http message box endpoint a bit to support such requests. What do you think? And how should the message box schema look like to get swagger support?

We can also simplify the schema and match it with http:

  • message metadata can be translated from/to http headers
  • only payload is part of request body (without payload key) or is collected from query params in case of queries
  • message uuid and created_at are added server side. The client should not care about those

codeliner avatar Apr 08 '18 19:04 codeliner

A couple of initial thoughts:

  1. It can be a bit annoying to include periods inside of a URL, specifically with a PHP server. The built-in PHP server handles them incorrectly and determines it is the end of the path. A coworker of mine just ran into this. I'm not saying we shouldn't use them, but it is something to consider when working on something that might be run using a simple PHP server. For the message type, could we instead use an attribute in the path more like POST https://my.service.com/api/messagebox/command/DoSomething?
  2. Using the query parameters can be hard to use unless it is a completely flat structure. Even for the queries, I think it would be a good idea to use POST and send the data using the HTTP body.
  3. If we want to use Swagger/Open API, we should decide on a version. The latest standard is Open API 3.0 which supports anyOf, oneOf and allOf, so I would suggest that. It is still relatively new, so there are not as many supporting libraries for editors and explorers but there should be enough support for what we need.

I'll put some effort towards a sample Open API document that might cover the needs and will link to it here.

camuthig avatar Apr 08 '18 22:04 camuthig

There are some layers of the Open API spec that don't exist in JSON schema, specifically some of the meta information, but I think we could create something similar to this using the JSON schema objects that are built inside of Event Machine:

https://app.swaggerhub.com/apis/camuthig/event_machine/1.0.0

camuthig avatar Apr 08 '18 23:04 camuthig

The sample looks great! I think we're on the right track.

Can you list the tasks needed to add swagger support to event machine?

It can be a bit annoying to include periods inside of a URL

We don't make any assumptions on the namespace separator. User can decide what they want to use. Other characters are possible because for Event Machine and the message factory it is just a string. If someone wants to map "-" in Url to "." in message name this can be done with either a custom MessageFactory or a PSR-15 middleware piped before our message box request handler.

Using the query parameters can be hard to use unless it is a completely flat structure.

Agreed. Let's support POST requests only.

If we want to use Swagger/Open API, we should decide on a version.

Definitely 3.0.

Another question: Your example includes two models: User and CreateUserInput. The distinction between input model and return type model was caused by GraphQL limitations. We no longer need to distinguish between input models and return type models, so one user model could be enough (Event Machine refactoring is no problem). Question is: do we want to force separate input and response models? If we do that, optional GraphQL support would still be possible. If we don't force it (my preference because it makes things easier) GraphQL support is nearly impossible.

Thoughts?

codeliner avatar Apr 09 '18 10:04 codeliner

I'm fine with moving input types into standard types. The different provides less support with regards to JSON schema than it did for GraphQL. GraphQL could always be handled as a separate project, but I think it is best to focus on a single, solid API format for now.

With that in mind, I think the needed work to get us towards Swagger docs is:

  • [x] Determine root schema information (servers, tags, info, etc)
  • [x] Move definitions to #/components/schemas or dereference all schemas
  • [ ] Add description/summary to query/command/event objects (? This can be a nice-to-have for Swagger docs)
  • [x] Add ability to convert JSON schemas to valid Swagger objects like this but for draft 6
  • [x] Collapse InputTypes and Types into a single class
  • [x] Add schema function/compilation to event machine

I may have missed some things, but that will definitely get us much closer.

camuthig avatar Apr 11 '18 01:04 camuthig

thx for the list @camuthig :+1:

codeliner avatar Apr 11 '18 20:04 codeliner

The master branch of event-machine-skeleton contains Swagger/OpenAPI support:

  • it uses rm_graphql branch of event machine
  • GraphQL endpoint is removed
  • /api/messagebox-schema returns the OpenAPI v3 schema
  • Swagger UI is available http://localhost:8080/swagger/index.html and uses the messagebox schema

I did not modify internal JSON Schema handling of Event Machine but instead rewrite the JSON Schema returned by $eventMachine->messageBoxSchema(). For now it only moves definitions to components/schemas and rewrites nullable types. This is all done in the MessageSchemaMiddleware

Doing it this way Event Machine does not need to know anything about OpenAPI v3. It can just use JSON Schema.

The Event Machine message box already supports requests like /api/messagebox/<message_name> and the skeleton router is set up to forward those requests to the message box. To keep Event Machine as-is I decided to require the payload property for every message.

Let me know what you think about it!

codeliner avatar Apr 14 '18 22:04 codeliner

new dev versions of event machine and skeleton released so we have a new base for further work.

  • [ ] Add JSON Schema title as summary
  • [ ] Test if JSON Schema description is used as OpenAPI descriptpion
  • [ ] Move JSON Schema to OpenAPI spec conversion from middleware to util class and provide tests (util class is maybe better placed in Event Machine repo)
  • [ ] Enhance schema conversion. Definitions and nullable types are handled, but not dependencies. See https://github.com/wework/json-schema-to-openapi-schema for inspiration (node.js package, needs to ported to PHP)

codeliner avatar Apr 15 '18 14:04 codeliner