Open dilanSachi opened 3 months ago
There is no standard way of depicting SSEs in openapi-spec [1]. However, there are some approaches that we can look on (Suggested by gemini).
Use produces or content to indicate text/event-stream
as a potential media type for the response.
However, this doesn't explicitly convey the SSE nature of the response.
Create custom extensions to the OpenAPI specification to add specific properties for SSE. This requires agreement on the extensions within your organization or community. (This does not work for us)
Clearly document the SSE nature of the endpoint in the operation's summary and description. While not ideal, it provides some information to API consumers. (This is not useful for the tools)
Include example responses in the examples or content property to demonstrate the SSE format. This can help clarify the expected output. (This is not useful for the tools)
For the first suggestion above, we can do something like this [1].
/events:
get:
responses:
200:
content:
text/event-stream:
schema:
type: array # eventually also stream as new type, to mean unboundness, or a new parameter of array
format: chunked # or whatever other keyword to mean chunks separated by empty lines
# another use could be jsonlines, one line per JSON object, with no [ , ]
items:
type: object
format: text # assuming this means "key: value", one per line, for each key
# or we may introduce yaml !! 🥇
required:
- id # not strictly required by SSE, but it's an example
- event # not strictly required by SSE, but it's an example
- data
properties: # also possible to model with oneOf+discriminator
id:
type: integer
description: my event id
event:
type: string
description: my event type
data:
type: object # object in case we have a complex structure, otherwise string, integer, ..., as usual
format: json # JSON is the default, but we may have different format as proposed above for the array
required:
- a
- b
properties: # as usual
a: # ...
b: # ...
c: # ...
[1] https://github.com/OAI/OpenAPI-Specification/issues/396#issuecomment-492287488
We will first support the client generation side. When the input yaml is as below,
paths:
/events:
get:
responses:
200:
description: desc
content:
text/event-stream:
schema:
type: string
The generated client will be,
resource isolated function get events(map<string|string[]> headers = {}) returns stream<http:SseEvent, error?>|error {
string resourcePath = string `/events`;
return self.clientEp->get(resourcePath, headers);
}
or
remote isolated function getEvent(map<string|string[]> headers = {}) returns stream<http:SseEvent, error?>|error {
string resourcePath = string `/events`;
return self.clientEp->get(resourcePath, headers);
}
In the case of status code binding,
resource isolated function get events(map<string|string[]> headers = {}, typedesc<OkString> targetType = <>) returns targetType|error;
public type OkString record {|
*http:Ok;
stream<http:SseEvent, error?> body;
map<string|string[]> headers;
|};
With the current SSE implementation, we are not supporting status code response binding yet. So we can ignore that for now. So we cannot generate status code binding client for SSE. We could ignore that specific resource and give a warning for now.
There can be additional content-types which translates to union return type. But I am not sure we are handling that union part in the current SSE implementation. Adding @MohamedSabthar
paths:
/events:
get:
responses:
200:
description: desc
content:
text/event-stream:
...
application/json:
...
resource isolated function get events(map<string|string[]> headers = {}) returns stream<http:SseEvent, error?>|json|error {
string resourcePath = string `/events`;
return self.clientEp->get(resourcePath, headers);
}
Had an offline discussion with @MohamedSabthar. As per him, it is not currently supported. In that case, I think we will have to support only single type returns.
resource isolated function get events(map<string|string[]> headers = {}) returns stream<http:SseEvent, error?>|json|error { string resourcePath = string `/events`; return self.clientEp->get(resourcePath, headers); }
+1, we are not handling this. In the case of a union of stream and anydata types being present, we return an error.
Description: In this task, we need to support,