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.
Active bindings
Today every active binding key resolves to a shipped, first- or third-party plugin:
bindings: key |
Dispatched via | Channel address → |
|---|---|---|
http |
Built-in HttpClient (no extra wire needed) |
URL path + verb |
mqtt / mqtt5 |
Kuestenlogik.Bowire.Protocol.Mqtt |
Topic. QoS / retain / will fields ride on the metadata bag. |
kafka |
Kuestenlogik.Bowire.Protocol.Kafka |
Topic. Schema-Registry hints + key / partition on metadata. |
amqp (0.9.1) |
Kuestenlogik.Bowire.Protocol.Amqp |
Exchange / routing key. |
amqp1 (1.0) |
Kuestenlogik.Bowire.Protocol.Amqp |
Address. |
ws |
Kuestenlogik.Bowire.Protocol.WebSocket |
Channel address as URL path. |
NATS follows once Kuestenlogik.Bowire.Protocol.Nats ships.
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