Skip to content

Commit 733fb4b

Browse files
cristianonicolairsynek
authored andcommitted
fix: handle end slash into platform url
1 parent 184d0d9 commit 733fb4b

5 files changed

Lines changed: 56 additions & 3 deletions

File tree

service/tools/maven-plugin/src/main/java/ai/timefold/solver/tools/maven/AbstractPlatformModelMojo.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,26 @@ protected void validate() {
9696
Objects.requireNonNull(key, "Registration key is mandatory");
9797
}
9898

99+
/**
100+
* Resolves the configured platform URL, stripping any trailing slashes so it can be
101+
* safely concatenated with a path that starts with a slash (e.g. "/api/platform/v1/...").
102+
*/
103+
protected String getPlatformUrl() {
104+
String url = getPropertyOrParameter(PROP_PLATFORM_URL, this.platformUrl);
105+
if (url != null) {
106+
url = url.trim();
107+
int end = url.length();
108+
while (end > 0 && url.charAt(end - 1) == '/') {
109+
end--;
110+
}
111+
url = url.substring(0, end);
112+
}
113+
if (url == null || url.isEmpty()) {
114+
throw new IllegalStateException("Platform Url is mandatory");
115+
}
116+
return url;
117+
}
118+
99119
protected ObjectNode readModelDescriptor(Path modelDescriptorArchivePath) throws IOException {
100120
Path modelDescriptorPath = Paths.get(buildDirectory, "timefold", DESCRIPTOR_FILE_NAME);
101121

service/tools/maven-plugin/src/main/java/ai/timefold/solver/tools/maven/ConfigureMojo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ private PlatformIdentityInfo fetchPlatformConfiguration() {
152152
requestBuilder.header("Accept", "application/json");
153153

154154
requestBuilder.header("Authorization", "Bearer " + platformPAT);
155-
String platformUrl = getPropertyOrParameter(PROP_PLATFORM_URL, this.platformUrl);
155+
String platformUrl = getPlatformUrl();
156156
requestBuilder.uri(URI.create(platformUrl + "/api/platform/v1/aboutme?includeConfig=true"));
157157

158158
HttpRequest httpRequest = requestBuilder.build();

service/tools/maven-plugin/src/main/java/ai/timefold/solver/tools/maven/DeployModelMojo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public void execute() throws MojoExecutionException {
8888
}
8989

9090
try {
91-
String platformUrl = getPropertyOrParameter(PROP_PLATFORM_URL, this.platformUrl);
91+
String platformUrl = getPlatformUrl();
9292
String modelType = getPropertyOrParameter(PRIVATE_MODEL_TYPE, type);
9393
List<String> tenants = getTenants();
9494
if (modelType == null) {

service/tools/maven-plugin/src/main/java/ai/timefold/solver/tools/maven/UndeployModelMojo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public void execute() throws MojoExecutionException {
4343
}
4444

4545
try {
46-
String platformUrl = getPropertyOrParameter(PROP_PLATFORM_URL, this.platformUrl);
46+
String platformUrl = getPlatformUrl();
4747
String key = getPropertyOrParameter(PROP_MODEL_KEY, this.key);
4848
Path modelDescriptorArchivePath = Paths.get(buildDirectory, "model-descriptor.zip");
4949

service/tools/maven-plugin/src/test/java/ai/timefold/solver/tools/maven/ConfigureMojoTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,39 @@ public void testConfigureSuccessfully(ConfigureMojo mojo) throws Exception {
137137
.containsEntry("image.native-suffix", "");
138138
}
139139

140+
@Test
141+
@InjectMojo(goal = "configure", pom = "src/test/resources/project-to-test/pom.xml")
142+
public void testConfigureSuccessfullyWithTrailingSlashInPlatformUrl(ConfigureMojo mojo) throws Exception {
143+
144+
session.getRequest().setGoals(List.of("timefold:deploy"));
145+
146+
mojo.setAccessTokenProvider(new TestAccessTokenProvider("xxxx"));
147+
mojo.setLog(log);
148+
mojo.platformUrl = wm1.getRuntimeInfo().getHttpBaseUrl() + "/";
149+
mojo.execute();
150+
151+
wm1.verify(1, getRequestedFor(urlPathEqualTo("/api/platform/v1/aboutme")));
152+
153+
// assert that plugin executed and produced expected logs
154+
log.assertContains("Configured Timefold Platform integration", Level.INFO);
155+
}
156+
157+
@Test
158+
@InjectMojo(goal = "configure", pom = "src/test/resources/project-to-test/pom.xml")
159+
public void testConfigureFailsWithBlankPlatformUrl(ConfigureMojo mojo) throws Exception {
160+
161+
session.getRequest().setGoals(List.of("timefold:deploy"));
162+
163+
mojo.setAccessTokenProvider(new TestAccessTokenProvider("xxxx"));
164+
mojo.setLog(log);
165+
mojo.platformUrl = "///";
166+
167+
assertThatThrownBy(() -> mojo.execute()).isInstanceOf(IllegalStateException.class)
168+
.hasMessage("Platform Url is mandatory");
169+
170+
wm1.verify(0, getRequestedFor(urlPathEqualTo("/api/platform/v1/aboutme")));
171+
}
172+
140173
@Test
141174
@MojoParameter(name = "nativeSupported", value = "true")
142175
@InjectMojo(goal = "configure", pom = "src/test/resources/project-to-test/pom.xml")

0 commit comments

Comments
 (0)