Class BowireGraphQLProtocol

Namespace
Kuestenlogik.Bowire.Protocol.GraphQL
Assembly
Kuestenlogik.Bowire.Protocol.GraphQL.dll

Bowire protocol plugin for GraphQL. Discovers a remote schema via introspection (Kuestenlogik.Bowire.Protocol.GraphQL.GraphQLIntrospectionQuery), surfaces the query / mutation / subscription root operations as services, and invokes them by building a parameterised operation string with Kuestenlogik.Bowire.Protocol.GraphQL.GraphQLQueryBuilder.

public sealed class BowireGraphQLProtocol : IBowireProtocol, IBowireProxySupport, IDisposable
Inheritance
BowireGraphQLProtocol
Implements
Inherited Members

Constructors

BowireGraphQLProtocol()

public BowireGraphQLProtocol()

Fields

BatchMetadataKey

Optional metadata key. Set to on to send several documents in one request as a JSON array, the way a batching server expects (#713).

public const string BatchMetadataKey = "X-Bowire-GraphQL-Batch"

Field Value

string

Remarks

InvokeAsync(string, string, string, List<string>, bool, Dictionary<string, string>?, CancellationToken) has always taken a list of messages, and this plugin has always read only the first. Every further one was dropped without a word. Batching is what makes that plural mean something.

Opt-in, because a server that does not batch answers an array with a parse error, and the caller would have no idea why a request that works one at a time fails together.

Not combined with GET (an array has no sensible URL form) or with APQ (a batch would need a hash per entry and a retry per miss — buildable, but nobody has asked, and guessing at the shape would pin a convention servers do not agree on).

HttpMethodMetadataKey

Optional metadata key. Set to get to send queries over GET instead of POST (#713).

public const string HttpMethodMetadataKey = "X-Bowire-GraphQL-Http-Method"

Field Value

string

Remarks

Bowire has always posted. That works against nearly every server and is the right default, but it leaves two cases unreachable: a CDN or cache in front of the API, which can only cache a GET, and a server configured to accept queries over GET alone.

Opt-in rather than automatic, because the choice has consequences a caller should make deliberately: a GET puts the whole document in the URL, where proxies and access logs keep it, and long documents meet a URL length limit nobody controls.

MultiplexMetadataKey

Optional metadata key. Set to on to share one graphql-transport-ws socket across subscriptions to the same endpoint (#713).

public const string MultiplexMetadataKey = "X-Bowire-GraphQL-Multiplex"

Field Value

string

Remarks

The protocol was built for this: every message carries an operation id so one connection can serve many. Without it each subscription opens its own socket, which is correct but wasteful against a server with a connection limit or an expensive auth handshake.

Opt-in, and deliberately so rather than for symmetry with the other flags. A shared socket means one failure reaches several callers, and the one-socket-per-subscription path has years of use behind it while this has none. The flag is how this earns the mileage to become the default.

PersistedQueryMetadataKey

Optional metadata key. Set to on to use Automatic Persisted Queries: send a SHA-256 of the document and let the server run it from its own store (#713).

public const string PersistedQueryMetadataKey = "X-Bowire-GraphQL-Persisted-Query"

Field Value

string

Remarks

The saving is the whole document on every request after the first. Behind a per-request body limit, or on a link where the document is the expensive part, that is the difference between workable and not.

Opt-in because it costs an extra round trip the first time a server sees a document, and a caller that sends one query once pays that cost for nothing.

SubscriptionTransportMetadataKey

Optional metadata key. Set to ws to force the graphql-transport-ws transport, or sse to force graphql-sse. When unset, the plugin tries WebSocket first (if the WebSocket plugin is loaded) and falls back to SSE.

public const string SubscriptionTransportMetadataKey = "X-Bowire-GraphQL-Subscription-Transport"

Field Value

string

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

string

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

string

IconSvg

SVG icon for the protocol tab.

public string IconSvg { get; }

Property Value

string

Id

Short identifier (e.g., "grpc", "signalr").

public string Id { get; }

Property Value

string

Name

Protocol name shown in UI tabs.

public string Name { get; }

Property Value

string

ProxySupport

How far this plugin's connections follow the proxy.

public BowireProxySupport ProxySupport { get; }

Property Value

BowireProxySupport

Methods

DiscoverAsync(string, bool, CancellationToken)

Discover available services and methods.

public Task<List<BowireServiceInfo>> DiscoverAsync(string serverUrl, bool showInternalServices, CancellationToken ct = default)

Parameters

serverUrl string
showInternalServices bool
ct CancellationToken

Returns

Task<List<BowireServiceInfo>>

Dispose()

Dispose the lazily-built HttpClient. Same lifecycle contract as the REST plugin — the registry that owns the plugin instance disposes it at host shutdown.

public void Dispose()

Initialize(IServiceProvider?)

Called after registration to inject the app's service provider (embedded mode).

public void Initialize(IServiceProvider? serviceProvider)

Parameters

serviceProvider IServiceProvider

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

serverUrl string
service string
method string
jsonMessages List<string>
showInternalServices bool
metadata Dictionary<string, string>
ct CancellationToken

Returns

Task<InvokeResult>

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

serverUrl string
service string
method string
jsonMessages List<string>
showInternalServices bool
metadata Dictionary<string, string>
ct CancellationToken

Returns

IAsyncEnumerable<string>

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

serverUrl string
service string
method string
showInternalServices bool
metadata Dictionary<string, string>
ct CancellationToken

Returns

Task<IBowireChannel>