AsyncAPI
AsyncAPI is the OpenAPI analogue for event-driven APIs. Where OpenAPI describes HTTP request / response, AsyncAPI describes channels, operations, messages, and the transport bindings (MQTT, Kafka, AMQP, WebSocket, HTTP, NATS, …) those channels use.
In Bowire, AsyncAPI is a discovery source, not a wire. The plugin parses the document, builds the method tree, and dispatches each invocation through the matching wire plugin. The mental model matches bowire --url ./openapi.yaml: hand Bowire the contract, it builds the method list, calls go out over the right transport.
Package
dotnet add package Kuestenlogik.Bowire.AsyncApi
The package id has no .Protocol. segment on purpose — AsyncAPI never speaks a wire itself.
Quick start
Point Bowire at a local file:
bowire --url ./asyncapi.yaml
…or a remote one:
bowire --url https://api.example.com/asyncapi.yaml
The sidebar now shows every channel as a service, every operation as a method, every message as a typed input. Hit Send — the call routes through whichever wire plugin the doc's bindings: block declares.
Supported bindings
Every binding key below resolves to a resolver that maps the AsyncAPI channel and its bindings.* fields onto a wire plugin's call. What each can do differs by direction: a send operation is a unary publish, a receive operation is a subscription that streams into the response pane. Nothing here throws at you: a binding without a subscribe shape yet answers a receive with one {"error": …} frame that says so, and a binding whose wire plugin is not loaded says which package to add.
bindings: key |
Dispatched via | send |
receive |
Channel address → |
|---|---|---|---|---|
mqtt / mqtt5 |
Kuestenlogik.Bowire.Protocol.Mqtt |
publish | subscribe | Topic. QoS / retain / will fields ride on the metadata bag. |
nats |
Kuestenlogik.Bowire.Protocol.Nats |
publish | subscribe | Subject. queue / replyTo map onto the plugin's queue_group / reply_to. |
kafka |
Kuestenlogik.Bowire.Protocol.Kafka |
produce | not yet | Topic. Schema-Registry hints + key / partition on metadata. |
amqp (0.9.1) |
Kuestenlogik.Bowire.Protocol.Amqp |
send | not yet | Exchange / routing key. |
amqp1 (1.0) |
Kuestenlogik.Bowire.Protocol.Amqp |
send | not yet | Address. |
ws |
Kuestenlogik.Bowire.Protocol.WebSocket |
open + send + close | not yet | Channel address as URL path. |
http |
Built-in HttpClient (no extra wire needed) |
request | not yet | URL path + verb. |
sns |
degrades — no wire plugin yet | error result | error frame | Topic ARN. |
sqs |
degrades — no wire plugin yet | error result | error frame | Queue URL. |
"not yet" on the receive column means the wire plugin has no subscribe shape for that binding today; the stream pane shows the sentence instead of a stack trace. A binding key that no resolver claims is reported the same way, naming the shipped resolvers.
Spec coverage
- AsyncAPI 2.x and 3.0 — both YAML and JSON.
$refresolution — local + remote;components.messages/components.schemasare expanded inline.- Multi-server documents —
servers[]becomes multiple Bowire targets in one discovery pass; the same shape as--url X --url Y. - Operation polarity — AsyncAPI tags
send/receivefrom the application's perspective; Bowire is the test client, so the polarity inverts once in the mapping layer rather than per binding. - Per-message overloads — operations declaring multiple
messages[]emit one method per message, namedopKey::messageName.
Architecture
+-------------------+
| asyncapi.yaml |
| asyncapi.json |
+-------------------+
|
v
+-------------------+ +-----------------------+
| AsyncAPI plugin | --> | BindingResolver |
| (channels + | | per bindings.* key |
| operations) | +-----------------------+
+-------------------+ |
v
+------------+ +------------+ +------------+ +------------+ +------------+
| Protocol. | | Protocol. | | Protocol. | | Protocol. | | built-in |
| Mqtt | | Kafka | | Amqp | | WebSocket | | HTTP |
+------------+ +------------+ +------------+ +------------+ +------------+
The benefit: an AsyncAPI doc travels as the contract surface (review it in PRs, version it in Git), but the runtime is whatever wire the broker speaks. Switch from Kafka to MQTT by editing the bindings: block; no Bowire-side changes needed.
Building blocks
Built on the official AsyncAPI .NET SDK (Neuroglia.AsyncApi.Core + .IO). The Client.Bindings.* packages are not used — they ship their own MQTT / Kafka clients that would duplicate Bowire's existing wire plugins. Neuroglia is the schema reader; wire calls go through BowireProtocolRegistry at runtime.
Schema export (planned)
Inverse of the loader: emit an AsyncAPI 3.0 document from the discovered topics / methods of running MQTT / Kafka / WebSocket targets. Mirrors the planned OpenAPI export from REST discovery. Tracked in the roadmap.
Related
- MQTT — wire dispatched by
bindings.mqtt/mqtt5 - Kafka — wire dispatched by
bindings.kafka - WebSocket — wire dispatched by
bindings.ws - Custom protocols — how to add a new
BindingResolverfor an unsupported binding key