Description
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?
- Have you validated the input using an OpenAPI validator (example)?
- Have you tested with the latest master to confirm the issue still exists?
- Have you searched for related issues/PRs?
- What's the actual output vs expected output?
- [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
Generated client will correctly recognise a relative server such as: /mypath
and use this as the base path.
The relative server of just the root path /
is not recognized and so the client will instead default to localhost as the base path.
A single slash should be recognised as a valid relative path.
This behavior occurs with multiple generator targets (typescript-fetch and java were tested).
openapi-generator version
7.7.0
This is not a regression:
The relevant code URLPathUtils.isRelativeUrl
hasn't been touched in 3 years and a comment on the associated pull request pointed this out a year ago (#10057).
OpenAPI declaration file content
{
"openapi": "3.0.1",
"info": {
"title": "OpenAPI definition",
"version": "v0"
},
"servers": [
{
"url": "/",
"description": "Generated server url"
}
],
"paths": {},
"components": {}
}
Generation Details
Tested with both JDK 11 and JDK 17.
This was tested with both the typescript-fetch
generator and the java
generator.
CLI
java -jar openapi-generator-cli.jar generate -g typescript-fetch -i openapi.json -o my-generated-client
Alternatively, with Maven:
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>7.7.0</version>
<executions>
<execution>
<goals><goal>generate</goal></goals>
<configuration>
<generatorName>typescript-fetch</generatorName>
<inputSpec>${project.build.directory}/openapi.json</inputSpec>
<output>${project.build.directory}/ts-openapi</output>
</configuration>
</execution>
</executions>
</plugin>
Steps to reproduce
Using the provided JSON, the generated client (see above) should have the base URL be empty, rather than falling back to localhost.
The reason for empty, rather than a slash, is so that concatting with work like normal with the context path.
In the typescript-fetch client see runtime.ts
.
export const BASE_PATH = "http://localhost".replace(/\/+$/, "");
In the java client, see src/main/java/org/openapitools/client/ApiClient.java
.
private String basePath = "http://localhost";
Related issues/PRs
- Issue Fix relative url as basePath #10057 - the problem was mentioned, but only after that issue's fix had already been merged
- Issue [typescript-angular] allow empty string basePath #3489 - dealt with an empty path, it looks like a language/generator specific fix was done, rather than a general fix applying to all of them.
- Issue [BUG] Server URL '/' removed from inputs to generator #13494 - used a single slash, but it seems to be focused on trailing slashes.
Suggest a fix
Code investigation:
When no server is defined, then a server with "/" is used as the default (OpenAPIDeserializer.parseRoot
):`
ArrayNode array = getArray("servers", rootNode, false, location, result);
if (array != null && array.size() > 0) {
openAPI.setServers(getServersList(array, String.format("%s.%s", location, "servers"), result, path));
} else {
Server defaultServer = new Server();
defaultServer.setUrl("/");
List<Server> servers = new ArrayList<>();
servers.add(defaultServer);
openAPI.setServers(servers);
}
This then relates to the following in DefaultGenerator.configureGeneratorProperties
:
if (URLPathUtils.isRelativeUrl(openAPI.getServers())) {
basePath = removeTrailingSlash(basePathWithoutHost);
} else {
basePath = removeTrailingSlash(config.escapeText(URLPathUtils.getHost(openAPI, config.serverVariableOverrides())));
}
This means that when URLPathUtils.getHost
is called above, URLPathUtils.sanitizeUrl
changes the URL to localhost:
} else if (url.startsWith("/")) {
url = LOCAL_HOST + url;
once(LOGGER).info("'host' (OAS 2.0) or 'servers' (OAS 3.0) not defined in the spec. Default to [{}] for server URL [{}]", LOCAL_HOST, url);
}
Patch:
I have created a patch to support /
: https://github.com/scrhartley/openapi-generator/tree/root-relative-url
Why is this not a pull request?
Previously, several of the samples didn't specify an explicit server and so would default to /, which would then become localhost as explained above. By changing / to no longer default to localhost, this would affect readmes, api docs, generated client code and comments and generated spec files. In order to avoid this, I changed input spec files to explicitly use localhost so that the only generated client files that would change would be their generated spec files.
The problem with just changing the input specs to localhost is that some clients were already confused by /
being specified as the server , but then the basePath becoming localhost. This means that explicitly specifying localhost as the server may cause some clients which had previously been generating a blank base path, to now use localhost. To avoid these clients changing, I instead made their server be blank (a relative url with the trailing slash removed) since I only updated isRelativeUrl
to treat / as relative and hence blank server urls are still handled in the legacy manner.
I do not have the expertise to make existing clients handle /
as a server in a more graceful manner, nor am I sure if it would be better to just allow some clients' URL to change to localhost, nor whether "" should also be accepted as a relative URL.