Class BowireSseProtocol
- Namespace
- Kuestenlogik.Bowire.Protocol.Sse
- Assembly
- Kuestenlogik.Bowire.Protocol.Sse.dll
Bowire protocol plugin for Server-Sent Events (SSE).
Discovers SSE endpoints via SseEndpointAttribute, Produces("text/event-stream")
metadata, or manual registration. Auto-discovered by BowireProtocolRegistry.
Also implements IInlineSseSubscriber so other plugins (MCP
notifications, GraphQL graphql-sse subscriptions) can reuse the SSE
event-stream parser via FindSseSubscriber()
without taking a compile-time dependency on this assembly.
public sealed class BowireSseProtocol : IBowireProtocol, IBowireProxySupport, IInlineSseSubscriber
- Inheritance
-
BowireSseProtocol
- Implements
- Inherited Members
Constructors
BowireSseProtocol()
public BowireSseProtocol()
Properties
Description
One-line description shown next to the plugin's display name
in Settings → Plugins. Optional; defaults to empty so
the row falls back to "DisplayName + version" without the
description line. Keep it short (≤ 100 characters) — the row
truncates anything wider than the manage panel.
public string Description { get; }
Property Value
DescriptionKey
#691 — optional catalogue key for Description. When the workbench's active locale has an entry for it, that entry is shown; otherwise Description is, exactly as before. Third-party plugins leave it empty and keep today's behaviour.
public string DescriptionKey { get; }
Property Value
IconSvg
SVG icon for the protocol tab.
public string IconSvg { get; }
Property Value
Id
Short identifier (e.g., "grpc", "signalr").
public string Id { get; }
Property Value
Name
Protocol name shown in UI tabs.
public string Name { get; }
Property Value
ProxySupport
How far this plugin's connections follow the proxy.
public BowireProxySupport ProxySupport { get; }
Property Value
Methods
DiscoverAsync(string, bool, IReadOnlyDictionary<string, string>?, CancellationToken)
Same, with the per-call metadata InvokeAsync(string, string, string, List<string>, bool, Dictionary<string, string>?, CancellationToken) already receives.
public Task<List<BowireServiceInfo>> DiscoverAsync(string serverUrl, bool showInternalServices, IReadOnlyDictionary<string, string>? metadata, CancellationToken ct = default)
Parameters
serverUrlstringshowInternalServicesboolmetadataIReadOnlyDictionary<string, string>ctCancellationToken
Returns
Remarks
Discovery was the one operation with no way to carry configuration, and it is the operation that decides whether anything else can run at all. A gRPC server with reflection switched off could be invoked once a descriptor set was supplied, but could not be enumerated — so a scan could not find the methods it was meant to test, and mTLS-protected servers could not be reflected against at all.
A default implementation that drops the metadata, so a plugin with no
per-environment configuration to honour stays exactly as it is. Only a
plugin that already reads a marker out of metadata elsewhere has
any reason to override it.
DiscoverAsync(string, bool, CancellationToken)
Side-channel marker the discovery endpoint appends to the URL when
the caller explicitly hinted sse@…. DiscoverAsync has no
hint parameter, and the ad-hoc fallback below must never fire on
the hint-less all-plugins fan-out (any URL that happens to answer
text/event-stream — legacy MCP SSE transport, graphql-sse — would
grow a phantom "SSE Endpoints" service next to the owning
plugin's real one).
public Task<List<BowireServiceInfo>> DiscoverAsync(string serverUrl, bool showInternalServices, CancellationToken ct = default)
Parameters
serverUrlstringshowInternalServicesboolctCancellationToken
Returns
Remarks
Reads the shared PluginHint marker rather than a private one. The private version needed a constant here and a matching literal in BowireDiscoveryEndpoints, kept together by a comment; SignalR had a second copy of the same arrangement, and the third plugin to want this bit got it wrong instead.
Initialize(IServiceProvider?)
Called after registration to inject the app's service provider (embedded mode).
public void Initialize(IServiceProvider? serviceProvider)
Parameters
serviceProviderIServiceProvider
InvokeAsync(string, string, string, List<string>, bool, Dictionary<string, string>?, CancellationToken)
Invoke a unary or client-streaming call.
public Task<InvokeResult> InvokeAsync(string serverUrl, string service, string method, List<string> jsonMessages, bool showInternalServices, Dictionary<string, string>? metadata = null, CancellationToken ct = default)
Parameters
serverUrlstringservicestringmethodstringjsonMessagesList<string>showInternalServicesboolmetadataDictionary<string, string>ctCancellationToken
Returns
InvokeStreamAsync(string, string, string, List<string>, bool, Dictionary<string, string>?, CancellationToken)
Invoke a server-streaming or duplex call.
public IAsyncEnumerable<string> InvokeStreamAsync(string serverUrl, string service, string method, List<string> jsonMessages, bool showInternalServices, Dictionary<string, string>? metadata = null, CancellationToken ct = default)
Parameters
serverUrlstringservicestringmethodstringjsonMessagesList<string>showInternalServicesboolmetadataDictionary<string, string>ctCancellationToken
Returns
OpenChannelAsync(string, string, string, bool, Dictionary<string, string>?, CancellationToken)
Open an interactive channel (for duplex/client-streaming).
public Task<IBowireChannel?> OpenChannelAsync(string serverUrl, string service, string method, bool showInternalServices, Dictionary<string, string>? metadata = null, CancellationToken ct = default)
Parameters
serverUrlstringservicestringmethodstringshowInternalServicesboolmetadataDictionary<string, string>ctCancellationToken
Returns
RegisterEndpoint(SseEndpointInfo)
Register an SSE endpoint for Bowire discovery.
Call before MapBowire() or during startup.
public static void RegisterEndpoint(SseEndpointInfo endpoint)
Parameters
endpointSseEndpointInfo
SubscribeAsync(string, Dictionary<string, string>?, CancellationToken)
Open an SSE connection to url with the given
request headers and yield each parsed event as a JSON envelope of the
form { id, event, data, retry }. The stream stays open until
the server closes it or ct is cancelled.
public IAsyncEnumerable<string> SubscribeAsync(string url, Dictionary<string, string>? headers, CancellationToken ct = default)
Parameters
urlstringheadersDictionary<string, string>ctCancellationToken