Understanding WebSocket API description's query and Chanels Object keys
bali182 opened this issue · 11 comments
Hello, I'm raising this issue to have a better understanding how the ws protocol is described. I'm looking at this example:
https://github.com/asyncapi/spec/blob/master/examples/2.0.0/websocket-gemini.yml
- When using websockets, the keys in
Channels Object
are the URLs to connect to right? So this:
channels:
/v1/marketdata/{symbol}:
Would mean connect to this URI (where symbol is a parameter), right?:
// in servers in the channel
new WebSocket("wss://api.gemini.com" + "/v1/marketdata/{symbol}")
If we have multiple entries in the Channels Object
does that mean we can connect to multiple endpoints with their respective parameters and available subscriptions/publishes?
- What is query under ws bindings? Is that something that has to be turned into a query string when establishing the connection? So this:
query:
type: object
properties:
heartbeat:
type: boolean
default: false
top_of_book:
type: boolean
default: false
bids:
type: boolean
default: true
...
Would also go into the URI?
new WebSocket("wss://api.gemini.com" + "/v1/marketdata/{symbol}?heartbeat=...&top_of_book=...")
In case yes, how to serialize the fields of this object? I saw that it must be an object with properties in the docs, but can the properties objects themselves? If so how deeply nested can this structure go and what would be the serialization method for it? OpenAPI has a nightmarish amount of parameter serialization methods, I hope you went with a simpler approach :D
In case I'm completely wrong please advise!
Hey @bali182
If we have multiple entries in the Channels Object does that mean we can connect to multiple endpoints with their respective parameters and available subscriptions/publishes?
yes, it means you have have multiple connections with the server. Have a look at this example I've build with one of our code generators.
What is query under ws bindings? Is that something that has to be turned into a query string when establishing the connection
exactly. You have few examples in official Gemini docs https://docs.gemini.com/websocket-api/#market-data
but can the properties objects themselves
what do you mean?
If so how deeply nested can this structure go
in the end it describes a list of available query params. The question is how complex can this get. For me it is always flat. This means one level, no nesting. Can be, as I used, object type JSON Schema, but you can go with array too if you think it is better
Hey @derberg thanks for getting back to me! Let me elaborate what I meant by parameter serialization.
OpenAPI describes parameter serialization here: https://swagger.io/docs/specification/serialization/
It basically says parameters can be primitive types (string, number or boolean) or 1 level, non nested objects or arrays.
What I'm asking here is if there is a (possibly nested) object or array schema for the schema of the path or query parameters, for example (first 2 examples look like they are nested but they are not as the root schema replaces the need for a list of parameters):
Non nested object (valid according to OpenAPI spec):
query:
type: object
properties:
heartbeat:
type: object
properties:
foo:
type: string
bar:
type: number
Non nested array (valid according to OpenAPI spec):
query:
type: object
properties:
heartbeat:
type: array
items:
type: string
Nested object (invalid according to OpenAPI spec):
query:
type: object
properties:
heartbeat:
type: object
properties:
foo:
type: object
properties:
... so on
Nested array (invalid according to OpenAPI spec):
query:
type: object
properties:
heartbeat:
type: array
items:
type: object
properties:
foo:
type: array
items:
type: string
Is this valid according to AsyncAPI spec, or not, and if it is what's the protocol for serializing and deserializing these in query/path?
Since there is no style
option for parameters, like OpenAPI, I assumed there is only one format for each, but for tools its kinda important to know what that format is.
Thank you,
Balazs
At the moment, this specific binding information is described in the WebSocket binding spec -> https://github.com/asyncapi/bindings/tree/master/websockets
So the schema must be of type: object
and have properties
key. The Gemini example that I provided shows a non nested flat structure. For me the example that you provided is already nested:
query:
type: object
properties:
heartbeat:
type: object
properties:
foo:
type: string
bar:
type: number
it is object in object.
Does it even make sense from technical point of view? I mean, how would the resulting query param look like for such example?
I movie this issue to binding repo as it is discussion about the binding
Welcome to AsyncAPI. Thanks a lot for reporting your first issue. Please check out our contributors guide and the instructions about a basic recommended setup useful for opening a pull request.
Keep in mind there are also other channels you can use to interact with AsyncAPI community. For more details check out this issue.
Cool thank you for moving it!
I mean, how would the resulting query param look like for such example?
That is exactly my question :) JSON Schema allows it. AsyncAPI docs don't say as far as I have seen that you can't do this. So my question is:
A) Is nesting not allowed, and this info missing from the docs?
B) If nesting is allowed are there specs on serialization?
Assume we have the schema you mentioned:
query:
type: object
properties:
heartbeat:
type: object
properties:
foo:
type: string
bar:
type: number
OpenAPI would prescribe serializition of the equivalent like:
style: form, explode: true -> ?foo=someString&bar=1
style: form, explode: false -> ?heartbeat=foo,someString,bar,1
style: deepObject, explode: true -> ?heartbeat[foo]=someString&heartbeat[bar]=1
Its described here: https://swagger.io/docs/specification/serialization/
The purpose of their ParameterObject
is to describe this.
However if it would look like this (so nested object in a parameter):
...
foo:
type: object
properties:
foobar:
type: string
OpenAPI does not allow this according to spec.
I'm looking for the AsyncAPI equivalent of this doc basically: https://swagger.io/docs/specification/serialization/ if it exists.
Thank you:
Balazs
In other words lets assume the following scenario:
- I'm the maintainer of a code generating tool for AsyncAPI.
- Someone tries to use an object or array as a path or query parameter.
- What do I do?
- Say it's not allowed according to spec
- Implement serialization/deserialization for it, but how?
I have to say ?heartbeat[foo]=someString&heartbeat[bar]=1
is interesting to see. Never actually saw it in any API
I would say that better clearly set limitations in the WebSocket binding rather than come up with some complex serialization guidelines really.
We already had a sentence that it must be an object with properties, we just need to add that properties of the object cannot be of type object
and array
, right?
I think that would definitely clarify things! If the object schema is interpreted as the collection of query params, and it the properties cannot be arrays or objects, serialization becomes pretty simple, as the only thing to do is url encode/decode the key/values and we are done. Thank you!
Does the same apply to the path parameters too? Meaning the schema for a Parameter Object describing a path parameter cannot be an object or array? I think that would be a good idea, as for OpenAPI that's just as messy as the query params.
I think that would definitely clarify things! If the object schema is interpreted as the collection of query params, and it the properties cannot be arrays or objects, serialization becomes pretty simple, as the only thing to do is url encode/decode the key/values and we are done. Thank you!
This is just my opinion though 😄 I just like to keep things simple. Would you open a PR to clarify this? I could engage other maintainers
Does the same apply to the path parameters too? Meaning the schema for a Parameter Object describing a path parameter cannot be an object or array? I think that would be a good idea, as for OpenAPI that's just as messy as the query params.
you mean Parameters in the Channel name? this is different story, recommend separate issue in spec
repo. For me, schema for parameter is definitely not array or object as again, it would not make sense
Awesome, thank you, I'll dig into the docs more and come up with a PR, based on my understanding, and then it's easier to critique, if that's how it is/supposed to be or not!