christosgkoros opened a new pull request, #25390: URL: https://github.com/apache/camel/pull/25390
## What this adds A new `camel-rest-postman` component that configures REST producers and contract-first REST consumers from a [Postman Collection](https://learning.postman.com/docs/collections/collections-overview/) instead of an OpenAPI specification. It is the Postman counterpart of `camel-rest-openapi`: it performs no HTTP itself and delegates to a component implementing `RestProducerFactory`. The motivation is that a large number of teams keep a Postman Collection as the only machine-readable description of their API, and today Camel has no way to consume that. The collection is loaded either from a Collection v2.1 JSON document (`classpath:`, `file:`, `http:`) or, by its uid, from the Postman cloud. ## Usage ```java // invoke one request from("direct:start") .to("rest-postman:petstore.json#getPetById"); // run every request of a folder, or of the whole collection, like Postman's collection runner from("timer:smoke?period=60000") .to("rest-postman:petstore.json#pets"); // serve the collection's requests, dispatching each to direct:<requestId> from("rest-postman:petstore.json") .to("direct:dummy"); ``` Multi-request runs return a `List<PostmanRunResult>` (status, body, headers, per-request failure), with `runFailFast` controlling whether the first failure aborts the run. ## Design notes **Addressing requests.** Postman items have a human name rather than an operation id, so the name is slugified (`Get Pet By Id` → `getPetById`), folder-qualified (`pets/getPetById`) when a name is not unique. `item.id` is accepted too, but note it is *optional* in the v2.1 schema and Postman's exporter strips it, so exported collections are normally addressed by slug and cloud-fetched ones by id. Both work. **Two credentials, deliberately named apart.** `postmanApiKey` authenticates against Postman in order to download a collection; it is never sent to the API the collection describes. The collection's own `auth` block authenticates against that API and is governed by `collectionAuth`, which defaults to `ignore` (with a startup warning naming the type found) because those values are usually unresolved `{{placeholders}}`, and silently attaching a credential found in a config file to outbound requests is surprising. An e2e test asserts the separation. **Security.** Redirects from `postmanApiUrl` are rejected rather than followed, since following one would replay the API key to the redirect target; `postmanApiUrl` must be HTTPS except for loopback; reads are bounded (8 MiB, 5000 items, 64 folder levels); `apiContextPath` serves the collection with every `auth` block and every `type: secret` variable removed, unconditionally. Postman `event` scripts are never parsed or executed. **No new third-party dependency.** The collection is parsed with `camel-util-json`, already on the classpath via `camel-support`. ## Testing - 167 tests in `camel-rest-postman` - 8 contract-first consumer tests in `camel-platform-http-vertx`, following the precedent that `rest-openapi`'s consumer tests live there because `PlatformHttpComponent` is the only `RestOpenApiConsumerFactory` implementation - `mvn clean install -Psourcecheck` passes on both modified modules ## Two things I would especially like review on 1. **Reusing the `RestOpenApiConsumerFactory` SPI** for a non-OpenAPI component. Its contract is entirely generic and `PlatformHttpComponent` is its only implementation; the alternative is a new SPI in `core/camel-api` plus a change to `camel-platform-http`. I took the smaller change deliberately, but the name is a wart and I am happy to switch if preferred. 2. **`collectionAuth` defaulting to `ignore`** rather than `header`, per the reasoning above. ## Known gap For a path the collection *does* describe, a wrong-method request currently gets a 405 from the vert.x router before this component's processor runs, and the router leaves `Allow` empty. `rest-openapi` populates `Allow` in the equivalent case, so the difference is mine; the processor's own 404/405 handling (with `Allow`) still applies to paths the router has no route for. I would appreciate a pointer here if the cause is obvious to someone who knows `platform-http` well. ## Notes No JIRA issue was created, as the contributing guide makes the reference conditional. Happy to open one if preferred. I have not yet raised this on `dev@`; I am opening the PR so there is something concrete to discuss and will start that thread. --- _This contribution was AI-assisted: written with [Claude Code](https://github.com/anthropics/claude-code) (Claude Opus) on behalf of @christosgkoros, who reviewed the design decisions. Commits carry a `Co-Authored-By` trailer._ -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
