Payload Testing
AWS ships a Lambda Test Tool for firing test payloads at a locally running Lambda; Swagger UI lets you construct and send test requests at an HTTP API. Benzene's equivalent is topic-centric: construct a payload for a topic, and send it into the running service through the same pipeline every transport uses — routing, validation, middleware, handler — regardless of whether that topic also has an HTTP mapping or is normally fed by SQS, SNS, EventBridge, Kafka, or Event Hubs.
Three pieces work together:
- Example payloads in the spec — the
benzenespec carries a generated, validation-awareexamplefor every topic and event (see Spec). - The message endpoint (
UseBenzeneMessageon any HTTP pipeline, this page) — accepts a POSTed BenzeneMessage envelope and dispatches it into the message pipeline. - The Spec UI — renders the examples and, when the service exposes a message endpoint, offers a Try it panel to edit and send payloads from the browser.
The message endpoint
UseBenzeneMessage (in Benzene.Http, namespace Benzene.Http.BenzeneMessage) is the HTTP
equivalent of the direct AWS Lambda invoke path — same name, same overload shapes. It works on
any Benzene HTTP transport (AWS Lambda API Gateway, Azure Functions, ASP.NET Core, self-host)
because it drives the transport-neutral request/response adapters directly.
using Benzene.Http.BenzeneMessage;
// Inline pipeline — serves POST /benzene-message
app.UseApiGateway(apiGateway => apiGateway
.UseBenzeneMessage(messageApp => messageApp
.UseMessageHandlers(router => router.UseFluentValidation()))
.UseMessageHandlers(router => router.UseFluentValidation())
);
// Or share one message pipeline across adapters (direct Lambda invoke + HTTP):
var benzeneMessagePipeline = aws.Create<BenzeneMessageContext>()
.UseMessageHandlers(router => router.UseFluentValidation());
aws.UseBenzeneMessage(benzeneMessagePipeline); // direct Lambda invoke
aws.UseApiGateway(apiGateway => apiGateway
.UseBenzeneMessage(benzeneMessagePipeline) // HTTP endpoint
.UseMessageHandlers());
The wire contract
POST a BenzeneMessage envelope; the body is the payload as a JSON string:
curl -X POST http://localhost:8080/benzene-message \
-H "content-type: application/json" \
-d '{ "topic": "order:create", "headers": {}, "body": "{\"customerId\":\"11111111-1111-1111-1111-111111111111\"}" }'
The response is the response envelope, with the HTTP status mapped from the envelope's status
(Ok → 200, ValidationError → 422, NotFound → 404, …):
{ "statusCode": "Ok", "headers": { }, "body": "{\"orderId\":\"...\"}" }
The envelope itself is always plain JSON (camelCase), independent of whatever payload formats the
app's own serializer negotiates. A malformed or topic-less envelope gets a BadRequest envelope
back with a 400.
Options
apiGateway.UseBenzeneMessage(new BenzeneMessageHttpOptions
{
Path = "/admin/benzene-message", // default: /benzene-message
TopicFilter = topic => topic.StartsWith("order:") // reject → NotFound envelope, 404
}, messageApp => messageApp.UseMessageHandlers());
Spec advertisement
Registering the endpoint also registers an IBenzeneMessageHttpEndpointInfo, and the benzene
spec advertises it as a top-level messageEndpoint field. Consumers — the Spec UI's Try it
panel in particular — feature-detect send capability on that field: no field, no send button.
Generating test payload files (AWS Lambda Test Tool)
For firing payloads from tooling rather than the browser, the benzene CLI can generate
per-topic test payload files from a service's spec — one JSON file per topic per transport
(<topic>-benzene-message.json, <topic>-sns.json, <topic>-sqs.json, and
<topic>-api-gateway.json for HTTP-mapped topics), ready to paste into the AWS Lambda Test Tool
or send with curl:
# from a running lambda
benzene lambda-test-tool -profile my-aws-profile -lambda-name my-service -directory ./test-payloads
# or from a spec JSON file on disk
benzene lambda-test-tool -file ./spec.json -directory ./test-payloads
The generation lives in Benzene.CodeGen.LambdaTestTool (LambdaTestFilesBuilder +
DefaultExampleBuilders), and the payload bodies come from the same spec-driven example
generator as everything else on this page.
⚠ Security
The endpoint dispatches every topic the pipeline routes, including topics that have no HTTP mapping and would otherwise only be reachable from a queue or an event bus. Treat it accordingly:
- It is opt-in only — nothing registers it implicitly.
- Intended for local development and protected/admin environments.
- Restrict what it can reach with
TopicFilter, and compose your authentication middleware before it in the pipeline. - Do not expose it unauthenticated in production.