An SSE Proposal #4171
Replies: 5 comments 22 replies
-
I'm not familiar with server-sent events, can you say something about why something like AsyncAPI for websockets doesn't serve this use case? Is a server-sent event "response" (from server to client) sent in response to a request? If not, does the existing webhook feature work for this use case? |
Beta Was this translation helpful? Give feedback.
-
To quickly follow up on the call - thanks all for discussing this relatively niche feature! I thought it would be good to gather the above options for how to describe SSE. Assume JSON messages; infer event typeE.g. responses:
"200":
description: "Activity in progress"
content:
text/event-stream:
schema:
anyOf:
- $ref: "#/components/schemas/EventProgess"
- $ref: "#/components/schemas/EventWithCompletionData" This is lovely and simple. The issue it has is it does not have a way to associate an event type with a particular message format. This could be perhaps convention-based, so Assume JSON messages; specify event typeE.g. (may not be idiomatic OpenAPI, but hopefully it gets the point across) responses:
"200":
description: "Activity in progress"
content:
text/event-stream:
anyOf:
"event_in_progress":
schema:
$ref: "#/components/schemas/EventProgess"
"event_completed":
schema:
$ref: "#/components/schemas/EventWithCompletionData" This specifies event types, but is limited to JSON. Specify content-type; specify event typeE.g. (again may not be idiomatic OpenAPI) responses:
"200":
description: "Activity in progress"
content:
text/event-stream:
anyOf:
"event_in_progress":
eventContentType: "application/json"
schema:
$ref: "#/components/schemas/EventProgess"
"event_completed":
eventContentType: "text/plain"
schema:
$ref: "#/components/schemas/EventWithCompletionData" This is fully flexible, but probably has the downside of clients having to decide how to deal with different content types in messages! |
Beta Was this translation helpful? Give feedback.
-
Hi there, wanted to share that we (Speakeasy) added an SSE feature to our code generator driven through OpenAPI. We were able to describe this kind of API neatly without funky extensions with OpenAPI and JSON Schema. You can read about it here: https://www.speakeasy.com/docs/runtime/server-sent-events#modeling-sse-in-openapi |
Beta Was this translation helpful? Give feedback.
-
@disintegrator I'm going to start a new thread here so that the previous one can keep going on It's clear that you put a lot of thought into this, and have proven its utility through implementation. That definitely carries weight. However... TL;DR: You've done a great job of modeling the EventSource Web API (which I'll call ESW), but the OAS Media Type Object does not operate at that level. It only operates at the level of documents (even indefinite-length ones) based on the media type format ( I'll go into more detail here, but do also read the last bit after the next horizontal divider as I talk about some other possibilities. SSE has both an application-level interface (ESW) and a wire-level interface ( The OAS is only concerned with the wire-level interface. We do model data based on its in-memory, parsed form, so there is some distinction between that and the wire format, most notably for form data. But even there, the Media Type Object models documents (whether finite or indefinite) of a given media type. Hence the name. The only place where we model at a different level is the Parameter Object, and that has generally been a source of pain that we hope to address in 3.3 (modeling SSE as a whole, and ESW in particular, are among many higher-level protocols/APIs/conventions built on top of HTTP. Encapsulating such higher-level usage is a great thing for an SDK to do, but the OAS does not model any of these things, and it would be an enormous undertaking and expansion of scope to do so. On the other hand, AsyncAPI is much more about these sorts of higher interfaces. My impression is that AsyncAPI isn't about non-HTTP things, it's about async things, which might be implemented on HTTP or some other protocol. If you want to model events, that's AsyncAPI. Getting back to the OAS perspective, the only new thing for us to model is documents of the So we really would model Media Type Objects need to model media types, not an application interface built on top of a media type. That said if AsyncAPI is not suitable for SSE (and I really do not keep up with that project so I'm not clear on that point), someone could make a spec that sits on top of the OAS and describes a higher-level interface. The Arazzo workflows specificaton essentially does just that, and it is better as a separate spec than as part of the OAS. We're only just starting to figure out how to build an ecosystem of API specs that work together to model what people need, preferably without a lot of redundancy. We would not want a system that requires modeling the low-level details of |
Beta Was this translation helpful? Give feedback.
-
One thing that occurs to me is that, even with |
Beta Was this translation helpful? Give feedback.
-
Introduction
Server-Sent Events are an HTTP-based way for servers to push data to clients as "events", blessed with an official specification in Javascript on the client side. Unlikely websockets or gRPC it can't do bidirectional communication, but it also sticks to text-based HTTP rather than "upgrading" to a binary protocol.
The latter point I believe makes it suitable for description as a REST resource. For example it allows the description of complex resources such as "progress" - the server performs a long-running activity; this activity's progress can be modelled as a REST resource using SSE.
Given SSE is a free-text medium, just as HTTP is, I believe it would be wise to add certain opinions to the OpenAPI way of specifying it. This proposal is of what I think those opinions could be and why, and a possible resulting OpenAPI description.
The proposed opinions
The proposed format
The format tries to incorporate standard OpenAPI semantics.
The only deviation is how the event type is specified, as a key under the
anyOf
node. I considered anx-
property, such asx-event-name
in the component schema, but that would be difficult with any resources that are used in multiple event types. It also makes the event name appear optional, which I think would be a mistake. Open to alternatives, of course.Additional comments:
anyOf
may not be what that is intended for, but it appears to be the best fit to my current understanding.Thanks for reading
I'd love feedback on this proposal. Very happy to work asynchonously in the Github-style, but also happy to join the calls and talk through it at some point, if there's time available in them.
P.s.
There was an issue opened on this already. I believe I've read the entire thing, but thought a new discussion might be a better (re)-starting place. Many thanks to nikojpapa's comment that the proposed format was originally based on.
Beta Was this translation helpful? Give feedback.
All reactions