Skip to content

Commit e22279b

Browse files
authored
feat(cpp-boost-beast-server): add HTTP/1.1 server generator (#24783)
* refactor(cpp-boost-beast): share model pipeline between client and server Move the direction-agnostic document pipeline, model lowering, parameter serialization facts, dialect policy, and schema-IR emission from CppBoostBeastClientCodegen into CppBoostBeastModelCodegen; extract CppBoostBeastOperationFacts from the client template assembler; add additionalEmbeddedTemplateDirs locator support and move shared model/validation templates to cpp-boost-beast-common. Client generated output is byte-identical; cppboostbeast suite (158 tests) green. * feat(cpp-boost-beast-server): generator, runtime, and API templates Add the cpp-boost-beast-server generator (BETA) emitting a C++17 Boost.Beast HTTP/1.1 server: strand-per-connection sessions with message_generator responses, encoded-segment routing with 404/405+Allow, OAS parameter deserialization (path simple/label/matrix, query form/space/pipe/deepObject, header simple, cookie form) with enum, pattern, and bound validation into RFC 9457 problem responses, JSON body codec over generated model to/fromJsonValue APIs, OR-of-AND security extraction with a deny-by-default Authorizer seam, single-shot strand posting responders, and an addApiImplStubs quick-start main. CMake links Boost 1.81+ json+url compiled libraries; -Wall/-W4 clean. * test(cpp-boost-beast-server): rejection, surface, and loopback runtime suites Add the server-regression OAS 3.1 fixture (path/query/header/cookie styles, enum/pattern/bound constraints, bearer + apiKey security), 12-test codegen suite (defaults, contract emission, stubs, IR stripping, multipart/x-www-form-urlencoded/text-*/event-stream/content-style/ cookie-matrix/ambiguous-route rejections, 3.0 compatibility), and the native loopback runtime test compiling and running the generated server against real sockets: 200/201/204 happy paths, 400 problem+json with errors[] for every constraint class, 404, 405+Allow, 413, 415, 401 with and without credentials, keep-alive, label-pattern paths, and pipe-delimited collections. Header params now look up lowercased field names; enum allow-lists render unescaped. * feat(cpp-boost-beast-server): petstore sample, generator docs, and CI Add the deterministic cpp-boost-beast-server petstore sample (builds clean with -Wall and serves 501 stubs / 400 / 404 over HTTP/1.1), the generated generator documentation, and a three-OS sample build workflow covering Boost json+url consumers. API headers now emit the model namespace using-directive only when an API actually references a generated model class (map-only APIs such as store inventory compile standalone). * docs(cpp-boost-beast-server): list generator in index * fix(cpp-boost-beast-server): harden runtime, gate, and constraint coverage Runtime: anonymous security alternatives (security: []) now bypass the authorization gate; 413 body-limit responses close the connection instead of re-reading leftover body bytes as a new request; responses mirror the request HTTP version and keep-alive preference; HttpServer::stop posts the acceptor close onto its strand; ResponderCore's completion flag is atomic and the handler-exception 500 routes through the guard; 401s carry WWW-Authenticate for http-scheme challenges; cookie names strip leading OWS; BodyJson handles uint64 numbers above INT64_MAX without throwing past the invalid_argument catch and supports any-type bodies; parseScalar enforces whole-input match and rejects inf/nan; problem JSON escapes bytes >= 0x7f to keep bodies valid UTF-8. Generator: request-body and parameter $refs are resolved before fact extraction so bodies and constraints survive; declared media-type parameters are normalized out of kMediaTypes; ranged status codes (2XX) and oauth2/openIdConnect/mutualTLS schemes are rejected at generation; integer/number/bool enums are validated at runtime like string enums; header and cookie params gain enum checks; route shape keys mirror the runtime splitter; dead x-server-route/kind/inner facts and the bodyKind helper are removed; shared OperationFacts gains the Apache header. Loopback coverage: anonymous-op bypass against a denying authorizer, integer-enum rejection/acceptance, and conventional spaced Cookie headers. * fix(cpp-boost-beast-server): close review gaps in gate, runtime, and tests Generation gate: - reject array/object cookie params, non-scalar array items, object params other than query deepObject string maps, heterogeneous enums - fix malformed security-scheme diagnostic quoting Runtime: - splitMatrixExploded(): strip repeated name= per element for style=matrix explode=true path parameters - router literal-over-parameter ranking (most literal segments wins, ties keep registration order) so /pets/bulk beats /pets/{petId} - re-arm the stream timer in send_response so deferred handler completions are not aborted by an expired read deadline - mirror request version/keep-alive on the 413 body_limit path - deepObject required-missing now reports 400 - shared param-constraints partial: uniform pattern/length/bound ladders across query, header, and cookie scalar parameters - jsonEscape passes UTF-8 through; escapes only C0 controls and DEL Rendering: minimum/maximum bounds emit long-double-safe literals (plain integers gain .0), so int64 extremes compile under -Wall. Tests: four new gate rejection tests plus a deepObject acceptance test; runtime test hardened (compiler/Boost skip guards, file-based output redirection, process-tree termination on timeout) and a new validation-disabled end-to-end case; loopback driver covers matrix explode, spaceDelimited, deepObject required, literal ranking, deferred completions, WWW-Authenticate challenges, HTTP/1.0 mirroring incl. 413, cookie decoding, and duplicate-completion guarding; locator precedence test now probes a template present in both embedded dirs. CI: Windows sample job installs boost-asio/beast/multiprecision ports (the build failed on missing beast and multiprecision headers). Docs: README ServerOptions table for readTimeoutSeconds/bodyLimitBytes; sample regenerated deterministically. * fix(cpp-boost-beast-server): degrade unsupported media types and security schemes AllGeneratorsTest requires every registered generator to generate from the canonical 3_0/petstore.yaml, which declares XML/form/multipart payloads and an oauth2 scheme; the previous hard-reject gate broke that contract for the entire project on every CI leg. - preprocessOpenAPI now logs precise warnings for non-JSON request media types, non-JSON response media types, and security scheme types with no runtime credential extractor, while still throwing for the compile-breaking/route-ambiguous categories (parameter styles and shapes, cookie containers, non-scalar array items, non-deepObject object params, heterogeneous enums, ambiguous routes, ranged codes) - the assembler filters declared request media types down to JSON: mixed bodies accept JSON and answer 415 to the rest, JSON-less bodies drop the typed body field entirely (hasBody=false, compiles clean) - unsupported scheme types remain in the route table as declared; the runtime's structurallySatisfied() denies those requests with 401 instead of the generation failing - five rejection tests rewritten as degrade tests asserting the exact generated contracts, plus a canonical-petstore regression test - verified: AllGeneratorsTest 855/855, beast suites 183 green, both samples regenerate with zero diff * docs(cpp-boost-beast-server): correct form-parameter feature claims The feature set advertised FormUnencoded/FormMultipart support while the server never parses those payloads (they degrade to no typed body). Exclude both parameter features and regenerate the generator docs page. * fix(cpp-boost-beast-server): shared IR chunks, freeform type mapping, variant bodies Move the 16 chunked OAS 3.1 schema-IR templates from the client-only embedded dir into cpp-boost-beast-common so the server generator (whose own dir never carried them) can reach the chunked IR path for large specs, and pin resolution from both generators with a locator test. Wipe the inherited DefaultCodegen typeMapping before seeding it, same as the client generator: AnyType -> oas_any_type_not_mapped is a placeholder header this family never provides, and the OpenAI corpus (FunctionToolParam output_schema anyOf) reaches it through a freeform branch that must resolve to boost::json::value. Render std::variant, std::optional, and std::monostate bodies in BodyJson.h: composition-typed responses serialize the active branch via std::visit, and null branches serialize as JSON null instead of failing to compile. * fix(cpp-boost-beast-server): degrade undecodable params, recover mixed-body JSON members Parameter shapes the JSON runtime cannot decode (content-style, form fields, object/array queries outside deepObject/scalar rules, cookie containers, heterogeneous enums, enum-class dataTypes) now degrade to a dropped handler field with a warning instead of rejecting the document, mirroring the media-type policy so real-world corpora generate code. The OpenAI spec drove the rules: the classifier keys off the resolved dataType the templates emit, so parseScalar can never see a type without an overload. Request-body recovery: a multipart+JSON body whose JSON member $refs a generated model now types the handler body exactly (the model's include is appended via toModelImport when DefaultCodegen did not import it); models aliased to std::variant degrade to no typed body because fromJsonLeaf cannot decode unions; a body model colliding with the generated request struct is namespace-qualified. The model using-directive flag accounts for recovered bodies. The gate now rejects only non-deterministic routing (ambiguous templates, ranged codes). Tests: six degrade rewrites plus four new contracts. * fix(cpp-boost-beast-server): include optional for variant bodies, name the right logger BodyJson.h declares a std::optional overload but relied on <variant> transitively providing <optional>; include it directly. The shared model codegen hardcoded its logger to CppBoostBeastClientCodegen, so server degrade warnings were attributed to the client class; use getClass(). Regenerated petstore server sample picks up the new include. * fix(cpp-boost-beast-server): non-static assembler logger for ArchUnit rule ArchUnitRulesTest requires slf4j Logger fields to be non-public, non-static and final (PR #8799); the new assembler logger was static. Both call sites are instance methods, so the field becomes an instance logger. * fix(cpp-boost-beast-server): close review gaps in gate, runtime, and tests - Router: tokenize embedded path expressions in one segment; shape keys keep literal text distinct from placeholders - RequestContext held via shared_ptr through the handler/service chain - Optional request bodies no longer fail presence checks when absent - Multi-tag operations get per-operation contract type names - ParamCodecs: float narrowing range checks, exclusive numeric bounds, collection/item constraints (new param-container-constraints include), strict label/matrix percent-encoded codecs, exact integer comparisons - Problem JSON: sanitize malformed UTF-8 in error details - Gate: wildcard response media no longer accepted as JSON; request-body schema selected per declared media; form-encoding hard-reject moved to a server-side override so the shared model path no longer rejects the client corpus; MultiServer feature claim set to false - Generated CMake: warnings are errors by default (opt-out flag added) - README quick-start renders real operations and attach sequence - Runtime regression spec/driver extended to cover all of the above * chore(cpp-boost-beast-server): regenerate sample and generator docs * fix(cpp-boost-beast-server): build reactor deps before sample runtime regression The sample workflow ran the runtime test with -pl modules/openapi-generator alone, so the 7.26.0-SNAPSHOT sibling (openapi-generator-core) could not be resolved from the snapshot repo on a clean runner checkout. Build the upstream modules with -am and tolerate modules without the selected test. * fix(cpp-boost-beast-server): response-side variant serialization, fail-closed codecs, review gaps - BodyJson: unwrap tagged CompositionBranchValue branches so oneOf responses whose C++ types collide serialize through std::visit - ParamCodecs: reject hex floats explicitly, accept ERANGE underflow, drop the dead errno store; document the whole-input match - param-constraints / param-container-constraints: guard std::regex construction so an out-of-subset pattern fails closed with 400 instead of retry-throwing 500 per request (absent/empty skip it) - Assembler: apiNamespace is constructor-injected (the operations-map merge runs after postProcessOperationsWithModels, which made the collision guard inert); mixed bodies type the JSON member model even when an unparseable member came first; README facts carry model-namespace-qualified send types - Codegen: exclude Host/BasePath global features (never mounted); the server overrides the shared form-encoding reject because it degrades flattened form fields with a warning instead of aborting - Workflow: trigger the sample CI on generator, template, and test resource changes; add generation/runtime coverage for the new paths * chore(cpp-boost-beast-server): regenerate sample and generator docs Deterministic re-run of bin/generate-samples.sh and bin/utils/export_generator.sh after the fix commit: README quick-start qualifies model response types, BodyJson.h gains the tagged-branch serializer, ParamCodecs.h gains the hex-float gate, and the feature table now reports Host/BasePath as unsupported. * fix(cpp-boost-beast): close review round on pipeline, runtime, and templates - route-ambiguity witness probe + adjacent-expression rejection in the server support-surface gate - pre-escaped literals (path, operationId, baseName, security fields) rendered with triple-brace interpolation only - license header sanitizes '*/' and NUL from info fields - required-null rejection, decode-time reset of every member, nullptr leaf assignment, integral-double integer bodies - two-stage read with interim 100 Continue, 413 version mirroring, 404 query stripping, factory-only HttpServer with null-router guard - JSON numeric wire grammar + locale-independent codecs, cookie quoted-string stripping, UTF-8 code-point lengths, unanchored regex_search with fail-closed grammar gate (Unicode property escapes refused explicitly, never approximated) - enum-always-invalid and present-guarded container constraints, path-item parameter lookup, nullable-body std::optional support, variant key normalization, schema-IR body validation before decode - CI triggers cover the shared model pipeline and common templates * test(cpp-boost-beast): regressions for the review-round fixes - server runtime driver: unicode property-escape fail-closed legs, 100-continue, oversized-body version mirror, 404 query stripping, PORT/HttpServer ownership probes already covered - exact-number driver: validator-level property-escape refusal incl. doubled-backslash literal case - preserve-additional-properties driver owns its serialized value (the old code bound a reference into a destroyed temporary) - CI triggers widened to shared model-pipeline sources * chore(cpp-boost-beast): regenerate petstore samples Regenerated after the review-round template fixes: fail-closed validator (property escapes), decode resets, required-null rejection, HTTP two-stage read + interim 100, codecs with JSON wire grammar, sample README policy notes. * fix(cpp-boost-beast-server): correct witness merge under-reporting The cross-layout overlap probe's glob merge consumed the other side's literals without emitting them (and never emitted while one side's wildcard ran to the end), so /a/{x}b vs /a/a{y} produced no candidate witness and the equal-ranking collision slipped the gate. Every transition now either advances strictly or appends the absorbed byte; a step budget bounds the search, keeping the probe proof-only (it can under-report, never falsely reject). Regression-pinned by rejectsCrossLayoutRouteOverlapWithWitness. * test(cpp-boost-beast-server): cover the review-round claims - witness overlap + adjacent-expression codegen rejections - license-header terminator sanitization - nullable model body kept typed as std::optional - HTML-significant route names rendered unescaped - runtime: body enum/required-null 400 legs (validation-leg gated), 404 query-strip, stepwise Expect: 100-continue interim proof, path-item inherited parameter constraint legs * fix(cpp-boost-beast-server): count() for Boost <1.85 compatibility http::message::contains() only exists since Boost 1.85; the Linux CI image ships an older Beast and the sample build failed on it. count() has been available since the first Beast release. * fix(cpp-boost-beast-server): close round-two review gaps - parse Expect as a token list: interim 100 only when every expectation is supported, 417 (RFC 9110 10.1.1) otherwise, so no client waits out the read timeout for an interim response that never comes - rewrite parseFloatScalar with a bounded significand and stepped exponent scaling: 0e400 stays zero (no 0 * inf), 1e400 saturates to infinity and dies at the finiteness gate, long finite decimals no longer overflow the accumulator; underflow still rounds toward zero - count UTF-8 code points by validating whole sequences: a malformed byte is never skipped as a continuation, so percent-decoded garbage cannot slip past maxLength - reject integral-double int64 leaves outside 2^53 instead of trusting a possibly-rounded double; keep <limits>/<optional> as direct includes - fail closed for bool/number parameters whose enum has zero representable members; reset inherited explicit defaults through ModelPropertyStorage.value - accept any recursively decodable inner type for an optional request body - document the parameter-vs-body pattern grammar split and the rationale for the whole-payload numeric representability gate; exercise Pet.note, Expect tokens, and the UTF-8 policy in the loopback regression * fix(cpp-boost-beast): decode integers past 2^53 from the exact wire lexeme tryGetMathematicalInteger trusted any integral double inside the destination range, but above 2^53 the double is the image of a 2-or- wider rounding band and every cast-based exactness check agrees with the band's centre: 9007199254740993.0 arrived as ...92 through value_to<int64_t>, through the model pipeline, and through the server's int64 body leaf alike. - Oas31ExactJson.h gains exactNumericLexeme + exactLexemeToInteger: inside a live ExactInstanceScope the decimal text is authoritative and converts exactly, range-checked against the destination. - tryGetMathematicalInteger keeps integral doubles only while |value| <= 2^53; past that window it recovers from the lexeme or refuses (fail closed, 400, never a corrupted int64). - JsonValueConverter<std::int64_t> specialisation replaces boost's value_to path, which never consulted the lexeme. - BodyJson.h's int64 leaf now delegates to the shared helper, one judgment for model, body, and validator paths. - Client and server samples regenerated; exact-runtime boundary expectations updated to the new (stricter) contract with paired no-lexeme-refusal / in-scope-exact legs. * fix(cpp-boost-beast-server): prove route collisions with a level-capped trie The ambiguous-route gate enumerated candidate witnesses with a step-budgeted depth-first glob merge. Branchy-but-intersecting pairs (alternating wildcard/literal layouts like /v/{p}a{p}a{p}a vs /v/a{p}a{p}a{p}) exhaust the step cap without emitting a witness, so a real collision could be silently under-reported and shipped as a runtime-shadowed route. Replace it with product-NFA trie BFS over (i,j) token positions: epsilon-closure per level, emitted chars advance at least one side, so a shortest witness has length at most n+m. Finishing all levels is a disjointness proof, not a timeout. Regression test drives the old under-report through to a rejection naming the witness path. * fix(cpp-boost-beast-server): strict UTF-8 counts, UTF-16 wregex, Expect lists, double gates Four wire-level correctness gaps from the third review round, each with a loopback driver leg: - UTF-8 length checks (maxLength/minLength) now validate sequence structure, not just lead bytes: overlong encodings, surrogates, and out-of-range tails degrade to a strict byte count and cannot be smuggled through as one code point (param codecs and the body validator share the grammar). - The body validator's std::wregex path encodes scalars above U+FFFF as UTF-16 surrogate pairs on 16-bit wchar_t (Windows); storing the bare code point truncated it silently. README documents the platform split. - Expect handling tokenises EVERY repeated Expect field line per RFC 9110 5.3, not just the first: an unsupported token on line two answers 417 instead of being ignored. - parseFloatScalar gates against the DESTINATION range for float and double alike. Where long double is wider than double (x86 80-bit), 1e400 parses finite and the old double-only gate handed the service an infinity cast out of the schema's range; both platforms now answer 400 identically. Samples regenerated. * fix(cpp-boost-beast-server): strip query before the routing shape key Router::splitPath strips the query string at registration, so '/responses?beta=true' registers the very route '/responses' — a literal duplicate the shape gate should name as such. The key was computed over the raw template, letting every beta-path pair slip to the witness probe and get mislabelled as registration-order ambiguity with a fabricated witness. The OpenAI document's '/x?beta=true' idiom now produces the honest 'have the same shape' diagnostic; regression test added. * fix(cpp-boost-beast-server): consult the wire lexeme before the double image - Inside an ExactInstanceScope the original token outranks its binary image unconditionally: an image check accepts 1.0000000000000001 (rounds to 1.0) and refuses 9223372036854775807.0 (rounds past int64's max), inverting both verdicts. - The 2^53 trust window is open on both signed edges: -2^53 is also the ties-to-even image of -9007199254740993, so the negative boundary image was decoded as a different wire integer than the positive one already was. Zero stays accepted for unsigned destinations (no token shares its image). - Regenerated both committed samples deterministically. * fix(cpp-boost-beast-server): complete the route-collision witness search Two suppression rules in the product-trie witness search could "prove" two routable templates disjoint when they genuinely collide: - the level-0 accept (both segments matching an empty path segment) was filtered out, so pairs colliding only through empty captures went unreported; - every step where BOTH sides merely absorb a char was skipped, but a whole-segment capture may not be empty (Router::matches refuses it) and absorbs only at index 0, so '/{p}' vs '{q}' needed exactly one root both-absorb char to yield a witness. Allow exactly one both-absorb step from the root state at level 0 (complete: whole-segment captures only need one stretched char, partial captures may be empty), keep empty candidates in the list, and let the caller's whole-path Router::matches mirror reject unverifiable ones. New regression: '/{p}/a/b' vs '/{q}/a{r}/b' collide on /c/a/b and must be refused; the old search generated them. * test(cpp-boost-beast-server): read the Expect loop to the echoed body The repeated-100-continue probe broke out of its read loop as soon as the 200 status line appeared in the transcript. The body can split across socket segments (headers and partial body in one read, the tail in the next), so the 'twice' assertion raced the body and the probe was flaky under load. Stop only once both the status line AND the body marker arrived; EOF (Connection: close) still ends the read as before. * fix(cpp-boost-beast-server): pin witness coverage to pre-root-absorb budget The both-absorb root step is only reachable when both flattened segments can absorb a char at index 0 (a wildcard each). Allocate the extra level only then, and pin the 4M cell guard to the pre-root-absorb product so a pair that was searchable before the level existed (e.g. two 125-char literal-initial segments: 126x126x251 = 3,984,876 base vs 4,000,752 with the level) stays searchable instead of under-reporting its collision. Regression test proves the near-budget collision is still reported. * fix(cpp-boost-beast): close trust window where the range fits exactly Inside the doubles' exact window every image names exactly one integer, so a signed destination whose full range fits within it (int32 and narrower) must accept its own minimum -2^digits; the open lower edge is only sound for destinations reaching the precision boundary (int64), whose -2^53 image is ambiguous with -9007199254740993. Keep the upper edge open everywhere. Native regression covers int32 min/max acceptance and the int64 -2^53 refusal. * test(cpp-boost-beast-server): pin the exact near-budget witness path Each template forces at least 124 literal 'l' chars into the colliding segment (captures may be empty), so 124 is the shortest joint match. Asserting the full 'both match' diagnostic rules out passing on a shorter prefix inside a wrong-length witness. * docs(cpp-boost-beast): describe acceptance at the destination minimum The previous wording implied -2^53 itself is accepted for a narrower signed destination; the destination-bounds check rejects it as out-of-range. What is accepted is the destination's own minimum, whose image is unambiguous inside the exact window. Regenerated both samples. * fix(cpp-boost-beast): drop unrepresentable scalar defaults on containers A scalar JSON default on an array/object carrier (OpenAI's Eval.testing_criteria declares 'default: eval' on an array of graders) was emitted verbatim, generating 'm_Testing_criteria = "eval"' against a std::vector member: code that cannot compile. JSON Schema treats such a default as an annotation, so the decode path now value-initializes the member instead. Scalars, enums, NullableField scalars, and composed variant-alias carriers (rewritten to fromJsonValue_<alias>(...) in postProcessAllModels) keep their explicit defaults. Regression: ScalarDefaults.mismatched_tags in the shared OAS 3.1 corpus, asserted in ModelApiSurfaceTest (array degrades to {}, scalar and variant defaults survive). Verified by compiling the full generated OpenAI API server (3300+ models) clean: the previously-broken Eval.cpp now compiles, variant voice defaults keep their fromJsonValue_ wraps. * fix(cpp-boost-beast): keep scalar defaults on variant carriers Follow-up review thread: the container-default guard scanned the whole carrier type for 'std::vector<'/'std::map<'/'std::set<' substrings, so a composed property whose alternatives include an array lost a valid scalar default even though the member is a variant alias whose fromJsonValue_ rewrite (postProcessAllModels) decodes it correctly. Restrict the drop to genuine container properties (isContainer, and a NullableField whose inner type actually starts with a container), as OpenAI's Eval.testing_criteria case requires. Regression: MixedWithContainer.named over a oneOf [array, string] alias must keep 'fromJsonValue_StringOrTags(boost::json::value("alloy"))' and must never assign the scalar raw to the variant member. * fix(cpp-boost-beast-server): harden HTTP and parameter semantics * fix(cpp-boost-beast-server): harden build and HEAD response * fix(cpp-boost-beast-server): read PORT safely on MSVC
1 parent ce5bf07 commit e22279b

117 files changed

Lines changed: 22686 additions & 1555 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
name: Samples cpp boost beast server
2+
3+
on:
4+
push:
5+
paths:
6+
- "samples/server/petstore/cpp-boost-beast-server/**"
7+
- ".github/workflows/samples-cpp-boost-beast-server.yaml"
8+
- "modules/openapi-generator/src/main/resources/cpp-boost-beast-server/**"
9+
- "modules/openapi-generator/src/main/resources/cpp-boost-beast-common/**"
10+
- "modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppBoostBeastServer*.java"
11+
- "modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppBoostBeastModelCodegen.java"
12+
- "modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppBoostBeastClientCodegen.java"
13+
- "modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppBoostBeastOperationFacts.java"
14+
- "modules/openapi-generator/src/test/resources/3_1/cpp-boost-beast-server/**"
15+
- "modules/openapi-generator/src/test/java/org/openapitools/codegen/cppboostbeastserver/**"
16+
pull_request:
17+
paths:
18+
- "samples/server/petstore/cpp-boost-beast-server/**"
19+
- ".github/workflows/samples-cpp-boost-beast-server.yaml"
20+
- "modules/openapi-generator/src/main/resources/cpp-boost-beast-server/**"
21+
- "modules/openapi-generator/src/main/resources/cpp-boost-beast-common/**"
22+
- "modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppBoostBeastServer*.java"
23+
- "modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppBoostBeastModelCodegen.java"
24+
- "modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppBoostBeastClientCodegen.java"
25+
- "modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppBoostBeastOperationFacts.java"
26+
- "modules/openapi-generator/src/test/resources/3_1/cpp-boost-beast-server/**"
27+
- "modules/openapi-generator/src/test/java/org/openapitools/codegen/cppboostbeastserver/**"
28+
29+
jobs:
30+
build:
31+
name: Build cpp boost beast server
32+
strategy:
33+
matrix:
34+
sample:
35+
- samples/server/petstore/cpp-boost-beast-server
36+
os:
37+
- ubuntu-latest
38+
- macOS-latest
39+
- windows-latest
40+
runs-on: ${{ matrix.os }}
41+
steps:
42+
- uses: actions/checkout@v7
43+
44+
- name: Install dependencies (Linux)
45+
if: matrix.os == 'ubuntu-latest'
46+
run: |
47+
sudo apt-get update
48+
sudo apt-get install -y build-essential cmake libboost-dev libboost-json-dev libboost-url-dev
49+
50+
- name: Install dependencies (macOS)
51+
if: matrix.os == 'macOS-latest'
52+
run: |
53+
brew install boost cmake
54+
55+
- name: Install dependencies (Windows)
56+
if: matrix.os == 'windows-latest'
57+
run: |
58+
vcpkg install boost-asio:x64-windows boost-beast:x64-windows boost-json:x64-windows boost-url:x64-windows boost-multiprecision:x64-windows
59+
shell: cmd
60+
timeout-minutes: 30
61+
62+
- name: Build
63+
working-directory: ${{ matrix.sample }}
64+
run: |
65+
if [ "${{ matrix.os }}" = "windows-latest" ]; then
66+
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE="C:/vcpkg/scripts/buildsystems/vcpkg.cmake"
67+
else
68+
cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=1
69+
fi
70+
cmake --build build
71+
shell: bash
72+
73+
- name: Set up JDK 17
74+
if: matrix.os == 'ubuntu-latest'
75+
uses: actions/setup-java@v4
76+
with:
77+
distribution: temurin
78+
java-version: 17
79+
80+
# The loopback runtime regression compiles the generated contract code
81+
# against the Boost installed above and asserts wire behavior. With the
82+
# require flag set, missing Boost/compilers fail the job instead of
83+
# silently skipping — this leg is the guaranteed execution of that suite.
84+
- name: Run server runtime regression (Linux)
85+
if: matrix.os == 'ubuntu-latest'
86+
run: |
87+
./mvnw -pl modules/openapi-generator -am test \
88+
-Dtest=CppBoostBeastServerRuntimeTest \
89+
-Dsurefire.failIfNoSpecifiedTests=false \
90+
-Dcpp.boost.beast.require=true -q
91+
shell: bash
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
generatorName: cpp-boost-beast-server
2+
outputDir: samples/server/petstore/cpp-boost-beast-server
3+
inputSpec: modules/openapi-generator/src/test/resources/3_1/cpp-boost-beast-server/petstore.yaml
4+
templateDir: modules/openapi-generator/src/main/resources/cpp-boost-beast-server
5+
additionalProperties:
6+
hideGenerationTimestamp: "true"
7+
packageName: CppBoostBeastPetstoreServer
8+
addApiImplStubs: "true"

‎docs/generators.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ The following generators are available:
9292
* [ada-server](generators/ada-server.md)
9393
* [aspnet-fastendpoints](generators/aspnet-fastendpoints.md)
9494
* [aspnetcore](generators/aspnetcore.md)
95+
* [cpp-boost-beast-server (beta)](generators/cpp-boost-beast-server.md)
9596
* [cpp-httplib-server](generators/cpp-httplib-server.md)
9697
* [cpp-oatpp-server](generators/cpp-oatpp-server.md)
9798
* [cpp-pistache-server](generators/cpp-pistache-server.md)
Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
---
2+
title: Documentation for the cpp-boost-beast-server Generator
3+
---
4+
5+
## METADATA
6+
7+
| Property | Value | Notes |
8+
| -------- | ----- | ----- |
9+
| generator name | cpp-boost-beast-server | pass this to the generate command after -g |
10+
| generator stability | BETA | |
11+
| generator type | SERVER | |
12+
| generator language | C++ | |
13+
| generator default templating engine | mustache | |
14+
| helpTxt | Generates a C++ Boost.Beast HTTP server. | |
15+
16+
## CONFIG OPTIONS
17+
These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
18+
19+
| Option | Description | Values | Default |
20+
| ------ | ----------- | ------ | ------- |
21+
|addApiImplStubs|Generate API implementation stubs that answer 501 problem+json and a sample main.cpp for quick start| |false|
22+
|apiPackage|C++ namespace for apis (convention: name.space.api).| |org.openapitools.server.api|
23+
|compileWithValidation|Emit schema-validation IR and kValidateOnDecode=true in generated ValidationTypes.h (default). Set to false to omit the IR.| |true|
24+
|modelPackage|C++ namespace for models (convention: name.space.model).| |org.openapitools.server.model|
25+
|packageName|C++ package and library name.| |CppBoostBeastServer|
26+
|preserveAdditionalProperties|Retain undeclared JSON object members in generated object models and re-emit them; set to false for strict handling.| |false|
27+
|tolerateNonNullableNulls|Treat explicit JSON null values as absent for generated model properties whose schemas do not allow null. Enabled by default; set to false for strict schema decoding.| |true|
28+
29+
## IMPORT MAPPING
30+
31+
| Type/Alias | Imports |
32+
| ---------- | ------- |
33+
|AnyType|#include &quot;AnyType.h&quot;|
34+
|Null|#include &lt;cstddef&gt;|
35+
|boost::json::value|#include &lt;boost/json.hpp&gt;|
36+
|int32_t|#include &lt;cstdint&gt;|
37+
|int64_t|#include &lt;cstdint&gt;|
38+
|std::map|#include &lt;map&gt;|
39+
|std::monostate|#include &lt;variant&gt;|
40+
|std::nullptr_t|#include &lt;cstddef&gt;|
41+
|std::optional|#include &lt;optional&gt;|
42+
|std::shared_ptr|#include &lt;memory&gt;|
43+
|std::string|#include &lt;string&gt;|
44+
|std::variant|#include &lt;variant&gt;|
45+
|std::vector|#include &lt;vector&gt;|
46+
47+
48+
## INSTANTIATION TYPES
49+
50+
| Type/Alias | Instantiated By |
51+
| ---------- | --------------- |
52+
53+
54+
## LANGUAGE PRIMITIVES
55+
56+
<ul class="column-ul">
57+
<li>bool</li>
58+
<li>char</li>
59+
<li>double</li>
60+
<li>float</li>
61+
<li>int</li>
62+
<li>long</li>
63+
<li>std::int32_t</li>
64+
<li>std::int64_t</li>
65+
</ul>
66+
67+
## RESERVED WORDS
68+
69+
<ul class="column-ul">
70+
<li>NULL</li>
71+
<li>alignas</li>
72+
<li>alignof</li>
73+
<li>and</li>
74+
<li>and_eq</li>
75+
<li>asm</li>
76+
<li>auto</li>
77+
<li>bitand</li>
78+
<li>bitor</li>
79+
<li>bool</li>
80+
<li>break</li>
81+
<li>case</li>
82+
<li>catch</li>
83+
<li>char</li>
84+
<li>char16_t</li>
85+
<li>char32_t</li>
86+
<li>class</li>
87+
<li>compl</li>
88+
<li>concept</li>
89+
<li>const</li>
90+
<li>const_cast</li>
91+
<li>constexpr</li>
92+
<li>continue</li>
93+
<li>decltype</li>
94+
<li>default</li>
95+
<li>delete</li>
96+
<li>do</li>
97+
<li>double</li>
98+
<li>dynamic_cast</li>
99+
<li>else</li>
100+
<li>enum</li>
101+
<li>explicit</li>
102+
<li>export</li>
103+
<li>extern</li>
104+
<li>false</li>
105+
<li>float</li>
106+
<li>for</li>
107+
<li>friend</li>
108+
<li>goto</li>
109+
<li>if</li>
110+
<li>inline</li>
111+
<li>int</li>
112+
<li>linux</li>
113+
<li>long</li>
114+
<li>mutable</li>
115+
<li>namespace</li>
116+
<li>new</li>
117+
<li>noexcept</li>
118+
<li>not</li>
119+
<li>not_eq</li>
120+
<li>nullptr</li>
121+
<li>operator</li>
122+
<li>or</li>
123+
<li>or_eq</li>
124+
<li>private</li>
125+
<li>protected</li>
126+
<li>public</li>
127+
<li>register</li>
128+
<li>reinterpret_cast</li>
129+
<li>requires</li>
130+
<li>return</li>
131+
<li>short</li>
132+
<li>signed</li>
133+
<li>sizeof</li>
134+
<li>static</li>
135+
<li>static_assert</li>
136+
<li>static_cast</li>
137+
<li>struct</li>
138+
<li>switch</li>
139+
<li>template</li>
140+
<li>this</li>
141+
<li>thread_local</li>
142+
<li>throw</li>
143+
<li>true</li>
144+
<li>try</li>
145+
<li>typedef</li>
146+
<li>typeid</li>
147+
<li>typename</li>
148+
<li>union</li>
149+
<li>unsigned</li>
150+
<li>using</li>
151+
<li>virtual</li>
152+
<li>void</li>
153+
<li>volatile</li>
154+
<li>wchar_t</li>
155+
<li>while</li>
156+
<li>xor</li>
157+
<li>xor_eq</li>
158+
</ul>
159+
160+
## FEATURE SET
161+
162+
163+
### Client Modification Feature
164+
| Name | Supported | Defined By |
165+
| ---- | --------- | ---------- |
166+
|BasePath|✗|ToolingExtension
167+
|Authorizations|✗|ToolingExtension
168+
|UserAgent|✗|ToolingExtension
169+
|MockServer|✗|ToolingExtension
170+
171+
### Data Type Feature
172+
| Name | Supported | Defined By |
173+
| ---- | --------- | ---------- |
174+
|Custom|✗|OAS2,OAS3
175+
|Int32|✓|OAS2,OAS3
176+
|Int64|✓|OAS2,OAS3
177+
|Float|✓|OAS2,OAS3
178+
|Double|✓|OAS2,OAS3
179+
|Decimal|✗|ToolingExtension
180+
|String|✓|OAS2,OAS3
181+
|Byte|✗|OAS2,OAS3
182+
|Binary|✗|OAS2,OAS3
183+
|Boolean|✓|OAS2,OAS3
184+
|Date|✗|OAS2,OAS3
185+
|DateTime|✗|OAS2,OAS3
186+
|Password|✗|OAS2,OAS3
187+
|File|✓|OAS2
188+
|Uuid|✗|
189+
|Array|✓|OAS2,OAS3
190+
|Null|✓|OAS3
191+
|AnyType|✓|OAS2,OAS3
192+
|Object|✓|OAS2,OAS3
193+
|Maps|✓|ToolingExtension
194+
|CollectionFormat|✓|OAS2
195+
|CollectionFormatMulti|✓|OAS2
196+
|Enum|✓|OAS2,OAS3
197+
|ArrayOfEnum|✓|ToolingExtension
198+
|ArrayOfModel|✓|ToolingExtension
199+
|ArrayOfCollectionOfPrimitives|✓|ToolingExtension
200+
|ArrayOfCollectionOfModel|✓|ToolingExtension
201+
|ArrayOfCollectionOfEnum|✓|ToolingExtension
202+
|MapOfEnum|✓|ToolingExtension
203+
|MapOfModel|✓|ToolingExtension
204+
|MapOfCollectionOfPrimitives|✓|ToolingExtension
205+
|MapOfCollectionOfModel|✓|ToolingExtension
206+
|MapOfCollectionOfEnum|✓|ToolingExtension
207+
208+
### Documentation Feature
209+
| Name | Supported | Defined By |
210+
| ---- | --------- | ---------- |
211+
|Readme|✓|ToolingExtension
212+
|Model|✓|ToolingExtension
213+
|Api|✓|ToolingExtension
214+
215+
### Global Feature
216+
| Name | Supported | Defined By |
217+
| ---- | --------- | ---------- |
218+
|Host|✗|OAS2,OAS3
219+
|BasePath|✗|OAS2,OAS3
220+
|Info|✓|OAS2,OAS3
221+
|Schemes|✗|OAS2,OAS3
222+
|PartialSchemes|✓|OAS2,OAS3
223+
|Consumes|✓|OAS2
224+
|Produces|✓|OAS2
225+
|ExternalDocumentation|✓|OAS2,OAS3
226+
|Examples|✓|OAS2,OAS3
227+
|XMLStructureDefinitions|✗|OAS2,OAS3
228+
|MultiServer|✗|OAS3
229+
|ParameterizedServer|✗|OAS3
230+
|ParameterStyling|✓|OAS3
231+
|Callbacks|✗|OAS3
232+
|LinkObjects|✗|OAS3
233+
234+
### Parameter Feature
235+
| Name | Supported | Defined By |
236+
| ---- | --------- | ---------- |
237+
|Path|✓|OAS2,OAS3
238+
|Query|✓|OAS2,OAS3
239+
|Header|✓|OAS2,OAS3
240+
|Body|✓|OAS2
241+
|FormUnencoded|✗|OAS2
242+
|FormMultipart|✗|OAS2
243+
|Cookie|✓|OAS3
244+
245+
### Schema Support Feature
246+
| Name | Supported | Defined By |
247+
| ---- | --------- | ---------- |
248+
|Simple|✓|OAS2,OAS3
249+
|Composite|✓|OAS2,OAS3
250+
|Polymorphism|✓|OAS2,OAS3
251+
|Union|✓|OAS3
252+
|allOf|✓|OAS2,OAS3
253+
|anyOf|✓|OAS3
254+
|oneOf|✓|OAS3
255+
|not|✓|OAS3
256+
257+
### Security Feature
258+
| Name | Supported | Defined By |
259+
| ---- | --------- | ---------- |
260+
|BasicAuth|✓|OAS2,OAS3
261+
|ApiKey|✓|OAS2,OAS3
262+
|OpenIDConnect|✗|OAS3
263+
|BearerToken|✓|OAS3
264+
|OAuth2_Implicit|✗|OAS2,OAS3
265+
|OAuth2_Password|✗|OAS2,OAS3
266+
|OAuth2_ClientCredentials|✗|OAS2,OAS3
267+
|OAuth2_AuthorizationCode|✗|OAS2,OAS3
268+
|SignatureAuth|✗|OAS3
269+
|AWSV4Signature|✗|ToolingExtension
270+
271+
### Wire Format Feature
272+
| Name | Supported | Defined By |
273+
| ---- | --------- | ---------- |
274+
|JSON|✓|OAS2,OAS3
275+
|XML|✗|OAS2,OAS3
276+
|PROTOBUF|✗|ToolingExtension
277+
|Custom|✗|OAS2,OAS3

0 commit comments

Comments
 (0)