Skip to content

Failing test: OAS 3.1 internal $ref inlined when spec loaded by file:// URL (resolveFully=false) — #1922#2342

Draft
pavelkryl wants to merge 1 commit into
swagger-api:masterfrom
pavelkryl:issue-1922-internal-ref-file-url
Draft

Failing test: OAS 3.1 internal $ref inlined when spec loaded by file:// URL (resolveFully=false) — #1922#2342
pavelkryl wants to merge 1 commit into
swagger-api:masterfrom
pavelkryl:issue-1922-internal-ref-file-url

Conversation

@pavelkryl

Copy link
Copy Markdown

What / why

Adds a failing regression test for #1922 in the parser's own harness.

For an OAS 3.1 document that contains only internal (#/components/...) references, parsing with resolve=true and resolveFully=false should leave those $refs intact. Today the result depends on how the root document was loaded:

load by FeeListResponse.fees.items.$ref
filesystem path #/components/schemas/FeeValues (preserved ✅)
file:// URL null — schema inlined, $ref lost ❌

reproduce (also dependency-free, runnable against any openapi-generator-cli jar which bundles this parser):

ParseOptions o = new ParseOptions();
o.setResolve(true);
o.setResolveFully(false);            // explicitly: do NOT inline
new OpenAPIV3Parser().readLocation(PATH, null, o);      // $ref preserved
new OpenAPIV3Parser().readLocation(FILE_URI, null, o);  // $ref inlined (bug)

This is OAS 3.1-only (the equivalent 3.0 spec preserves the $ref under both path and URL load) and reproduces on every release from 2.1.22 through 2.1.43 (latest).

Test results (this PR)

internalRefPreservedWhenLoadedByPath     PASS   (baseline)
internalRefPreservedWhenLoadedByFileUrl  FAIL   expected [#/components/schemas/FeeValues] but found [null]
pathAndFileUrlAgree                      FAIL   expected [#/components/schemas/FeeValues] but found [null]

The two failing assertions are the bug. Draft because the test is intended to fail until the parser is fixed.

Why it matters downstream

openapi-generator's CodegenConfigurator calls readLocation(...) with resolve=true, resolveFully=false and relies on internal $refs being preserved (it runs its own InlineModelResolver). Callers that pass the spec as a URL — the Maven/Gradle plugins, and quarkus-openapi-generator (configurator.setInputSpec(specFilePath.toUri().toString())) — get the refs back inlined, so every reused component is duplicated per use-site (<Parent><Prop>Inner, <Parent><Prop> for nullable anyOf, <Operation>Request for request bodies) and the canonical component is emitted but orphaned.

Root-cause localization (for a fix)

For OAS 3.1, OpenAPIV3Parser.resolve(...) runs the dereferencer whenever isResolve() || isResolveFully(). In OpenAPIDereferencer31.dereference(...) the root document is registered in the in-memory reference set as "local" only when rootUri is blank; with a non-blank file:// rootUri it is not, so in ReferenceVisitor.resolveSchemaRef(...) an internal #/... pointer is resolved against the file:// base URI and the document is re-read/dereferenced (inlined). A fix likely lives here: internal (ReferenceUtils.isLocalRef) pointers into the root document should be handled consistently regardless of whether the root was loaded by path or by file:// URL (i.e. not inlined under resolveFully=false). Related: #2201, #1166.

I'm happy to iterate on the actual fix with maintainer guidance on the intended resolve vs resolveFully contract for internal refs.

🤖 Generated with Claude Code

…ef lost on file:// URL load

For an OAS 3.1 doc with only internal ("#/components/...") references parsed with
resolve=true and resolveFully=false, the internal $refs must be preserved regardless
of whether the root document is loaded by filesystem path or by file:// URL.

Today they diverge: loaded by path the $ref is preserved; loaded by file:// URL the
3.1 dereferencer inlines the referenced schema and the $ref is lost. Downstream code
generators (openapi-generator, quarkus-openapi-generator) that hand the spec to the
parser as a URL therefore duplicate every reused component per use-site and leave the
canonical component generated-but-orphaned.

The new test passes for path load (baseline) and fails for file:// URL load,
demonstrating the bug in the parser's own harness. Related: swagger-api#2201, swagger-api#1166.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant