Skip to content

Commit 4ab9f2c

Browse files
committed
fix(transport): complete endpoint policy contracts
1 parent 369e780 commit 4ab9f2c

2 files changed

Lines changed: 169 additions & 61 deletions

File tree

‎src/main/java/io/github/easy4j/hermes/api/HermesHttpClient.java‎

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ public CompletableFuture<ResponseResult> createResponseAsync(ResponseRequest req
289289
* @since 1.0.0
290290
*/
291291
public ResponseResult getResponse(String responseId) {
292-
return get("/v1/responses/" + responseId, ResponseResult.class);
292+
return get(PATH_RESPONSES + "/" + encodePathSegment(responseId), ResponseResult.class);
293293
}
294294

295295
/**
@@ -302,7 +302,7 @@ public ResponseResult getResponse(String responseId) {
302302
* @since 1.0.0
303303
*/
304304
public boolean deleteResponse(String responseId) {
305-
return deleteBoolean(PATH_RESPONSES + "/" + responseId);
305+
return deleteBoolean(PATH_RESPONSES + "/" + encodePathSegment(responseId));
306306
}
307307

308308
// ============================================================
@@ -329,11 +329,24 @@ public boolean deleteResponse(String responseId) {
329329
public CompletableFuture<ModelsResponse> listModelsAsync() { return getAsync(PATH_MODELS, ModelsResponse.class); }
330330

331331
private static String encodePathSegment(String value) {
332-
try {
333-
return java.net.URLEncoder.encode(value, "UTF-8");
334-
} catch (java.io.UnsupportedEncodingException e) {
335-
throw new IllegalStateException("UTF-8 is not supported", e);
332+
Objects.requireNonNull(value, "path segment");
333+
byte[] bytes = value.getBytes(java.nio.charset.StandardCharsets.UTF_8);
334+
char[] hex = "0123456789ABCDEF".toCharArray();
335+
StringBuilder encoded = new StringBuilder(bytes.length);
336+
for (byte raw : bytes) {
337+
int valueByte = raw & 0xFF;
338+
if ((valueByte >= 'a' && valueByte <= 'z')
339+
|| (valueByte >= 'A' && valueByte <= 'Z')
340+
|| (valueByte >= '0' && valueByte <= '9')
341+
|| valueByte == '-' || valueByte == '.' || valueByte == '_' || valueByte == '~') {
342+
encoded.append((char) valueByte);
343+
} else {
344+
encoded.append('%')
345+
.append(hex[(valueByte >>> 4) & 0x0F])
346+
.append(hex[valueByte & 0x0F]);
347+
}
336348
}
349+
return encoded.toString();
337350
}
338351

339352
/**
@@ -414,7 +427,7 @@ public RunStatus createRun(RunCreateRequest request) {
414427
* @return Agent Run 状态
415428
* @since 1.0.0
416429
*/
417-
public RunStatus getRun(String runId) { return get("/v1/runs/" + runId, RunStatus.class); }
430+
public RunStatus getRun(String runId) { return get(PATH_RUNS + "/" + encodePathSegment(runId), RunStatus.class); }
418431

419432
/**
420433
* <p>停止 Agent Run。</p>
@@ -438,7 +451,7 @@ public void stopRun(String runId) {
438451
* @since 1.0.0
439452
*/
440453
public CompletableFuture<Void> stopRunAsync(String runId) {
441-
Request request = authedRequest(url(PATH_RUNS + "/" + runId + "/stop"))
454+
Request request = authedRequest(url(PATH_RUNS + "/" + encodePathSegment(runId) + "/stop"))
442455
.post(RequestBody.create(new byte[0], null)).build();
443456
return executeResponseAsync(request, null).thenApply(response -> {
444457
if (!response.isSuccessful()) {
@@ -460,7 +473,7 @@ public CompletableFuture<Void> stopRunAsync(String runId) {
460473
*/
461474
@SuppressWarnings("unchecked")
462475
public Map<String, Object> approveRun(String runId, Map<String, Object> decision) {
463-
return postMap(PATH_RUNS + "/" + runId + "/approval", decision);
476+
return postMap(PATH_RUNS + "/" + encodePathSegment(runId) + "/approval", decision);
464477
}
465478

466479
// ============================================================
@@ -524,7 +537,7 @@ public List<Session> listSessions(Integer limit, Integer offset, String source,
524537
* @return 会话对象或会话列表
525538
* @since 1.0.0
526539
*/
527-
public Session getSession(String id) { return get(PATH_SESSIONS + "/" + id, Session.class); }
540+
public Session getSession(String id) { return get(PATH_SESSIONS + "/" + encodePathSegment(id), Session.class); }
528541

529542
/**
530543
* <p>查询会话消息。</p>
@@ -536,7 +549,7 @@ public List<Session> listSessions(Integer limit, Integer offset, String source,
536549
* @since 1.0.0
537550
*/
538551
public List<Map<String, Object>> getSessionMessages(String id) {
539-
return getList(PATH_SESSIONS + "/" + id + "/messages",
552+
return getList(PATH_SESSIONS + "/" + encodePathSegment(id) + "/messages",
540553
new TypeReference<List<Map<String, Object>>>() {});
541554
}
542555

@@ -553,7 +566,7 @@ public List<Map<String, Object>> getSessionMessages(String id) {
553566
public Session forkSession(String id, String title) {
554567
Map<String, Object> body = new LinkedHashMap<>();
555568
if (title != null) body.put("title", title);
556-
return post(PATH_SESSIONS + "/" + id + "/fork", body, Session.class);
569+
return post(PATH_SESSIONS + "/" + encodePathSegment(id) + "/fork", body, Session.class);
557570
}
558571

559572
/**
@@ -566,7 +579,7 @@ public Session forkSession(String id, String title) {
566579
* @since 1.0.0
567580
*/
568581
public boolean deleteSession(String id) {
569-
return deleteBoolean(PATH_SESSIONS + "/" + id);
582+
return deleteBoolean(PATH_SESSIONS + "/" + encodePathSegment(id));
570583
}
571584

572585
/**
@@ -580,7 +593,7 @@ public boolean deleteSession(String id) {
580593
* @since 1.0.0
581594
*/
582595
public Session updateSession(String id, Map<String, Object> patch) {
583-
Request request = authedRequest(url(PATH_SESSIONS + "/" + id))
596+
Request request = authedRequest(url(PATH_SESSIONS + "/" + encodePathSegment(id)))
584597
.patch(RequestBody.create(toJson(patch), JSON)).build();
585598
return execute(request, Session.class);
586599
}
@@ -596,7 +609,7 @@ public Session updateSession(String id, Map<String, Object> patch) {
596609
* @since 1.0.0
597610
*/
598611
public ChatResponse sessionChat(String id, String input) {
599-
return post(PATH_SESSIONS + "/" + id + "/chat", Collections.singletonMap("input", input), ChatResponse.class);
612+
return post(PATH_SESSIONS + "/" + encodePathSegment(id) + "/chat", Collections.singletonMap("input", input), ChatResponse.class);
600613
}
601614

602615
// ============================================================
@@ -639,7 +652,7 @@ public Map<String, Object> createJob(Map<String, Object> job) {
639652
*/
640653
@SuppressWarnings("unchecked")
641654
public Map<String, Object> getJob(String jobId) {
642-
Request request = authedRequest(url(PATH_JOBS + "/" + jobId)).get().build();
655+
Request request = authedRequest(url(PATH_JOBS + "/" + encodePathSegment(jobId))).get().build();
643656
return executeList(request, new TypeReference<Map<String, Object>>() {});
644657
}
645658

@@ -655,7 +668,7 @@ public Map<String, Object> getJob(String jobId) {
655668
*/
656669
@SuppressWarnings("unchecked")
657670
public Map<String, Object> updateJob(String jobId, Map<String, Object> patch) {
658-
Request request = authedRequest(url(PATH_JOBS + "/" + jobId))
671+
Request request = authedRequest(url(PATH_JOBS + "/" + encodePathSegment(jobId)))
659672
.patch(RequestBody.create(toJson(patch), JSON)).build();
660673
return executeList(request, new TypeReference<Map<String, Object>>() {});
661674
}
@@ -670,7 +683,7 @@ public Map<String, Object> updateJob(String jobId, Map<String, Object> patch) {
670683
* @since 1.0.0
671684
*/
672685
public boolean deleteJob(String jobId) {
673-
Request request = authedRequest(url(PATH_JOBS + "/" + jobId)).delete().build();
686+
Request request = authedRequest(url(PATH_JOBS + "/" + encodePathSegment(jobId))).delete().build();
674687
return awaitFuture(executeResponseAsync(request, null).thenApply(response -> {
675688
if (!response.isSuccessful() && response.getStatusCode() != 404) {
676689
log.warn("deleteJob {} failed: {}", jobId, response.getStatusCode());
@@ -689,7 +702,7 @@ public boolean deleteJob(String jobId) {
689702
* @since 1.0.0
690703
*/
691704
public Map<String, Object> pauseJob(String jobId) {
692-
return postMap("/api/jobs/" + jobId + "/pause", Collections.emptyMap());
705+
return postMap("/api/jobs/" + encodePathSegment(jobId) + "/pause", Collections.emptyMap());
693706
}
694707

695708
/**
@@ -702,7 +715,7 @@ public Map<String, Object> pauseJob(String jobId) {
702715
* @since 1.0.0
703716
*/
704717
public Map<String, Object> resumeJob(String jobId) {
705-
return postMap("/api/jobs/" + jobId + "/resume", Collections.emptyMap());
718+
return postMap("/api/jobs/" + encodePathSegment(jobId) + "/resume", Collections.emptyMap());
706719
}
707720

708721
/**
@@ -715,7 +728,7 @@ public Map<String, Object> resumeJob(String jobId) {
715728
* @since 1.0.0
716729
*/
717730
public Map<String, Object> runJobNow(String jobId) {
718-
return postMap("/api/jobs/" + jobId + "/run", Collections.emptyMap());
731+
return postMap("/api/jobs/" + encodePathSegment(jobId) + "/run", Collections.emptyMap());
719732
}
720733

721734
// ============================================================

0 commit comments

Comments
 (0)