|
|
@@ -218,6 +218,85 @@ public class ForwardRobotService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 转发:测试舌象图片校验(multipart/form-data)
|
|
|
+ * 目标接口:POST /api/v1/diagnosis/testtongue/check-image
|
|
|
+ */
|
|
|
+ public ResponseEntity<String> forwardTesttongueCheckImage(MultipartFile file, String authorization) {
|
|
|
+ String url = joinUrl(targetBaseUrl, "/api/v1/diagnosis/testtongue/check-image");
|
|
|
+
|
|
|
+ try {
|
|
|
+ long start = System.currentTimeMillis();
|
|
|
+ long fileSize = (file != null ? file.getSize() : 0L);
|
|
|
+ String ct = (file != null ? file.getContentType() : null);
|
|
|
+ log.info("转发 testtongue check-image 开始,url={}, fileSize={} bytes, contentType={}", url, fileSize, ct);
|
|
|
+
|
|
|
+ final String boundary = "----EmoonForwardBoundary" + System.currentTimeMillis();
|
|
|
+ final byte[] CRLF = "\r\n".getBytes(StandardCharsets.UTF_8);
|
|
|
+
|
|
|
+ String filename = (file != null && file.getOriginalFilename() != null) ? file.getOriginalFilename() : "file";
|
|
|
+ String fileContentType = (file != null && file.getContentType() != null && !file.getContentType().isBlank())
|
|
|
+ ? file.getContentType()
|
|
|
+ : MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
|
|
+ byte[] fileBytes = (file != null) ? file.getBytes() : new byte[0];
|
|
|
+
|
|
|
+ ByteArrayOutputStream bos = new ByteArrayOutputStream(fileBytes.length + 2048);
|
|
|
+
|
|
|
+ // file field
|
|
|
+ bos.write(("--" + boundary).getBytes(StandardCharsets.UTF_8));
|
|
|
+ bos.write(CRLF);
|
|
|
+ bos.write(("Content-Disposition: form-data; name=\"file\"; filename=\"" + filename + "\"").getBytes(StandardCharsets.UTF_8));
|
|
|
+ bos.write(CRLF);
|
|
|
+ bos.write(("Content-Type: " + fileContentType).getBytes(StandardCharsets.UTF_8));
|
|
|
+ bos.write(CRLF);
|
|
|
+ bos.write(CRLF);
|
|
|
+ bos.write(fileBytes);
|
|
|
+ bos.write(CRLF);
|
|
|
+
|
|
|
+ // end
|
|
|
+ bos.write(("--" + boundary + "--").getBytes(StandardCharsets.UTF_8));
|
|
|
+ bos.write(CRLF);
|
|
|
+
|
|
|
+ byte[] multipartBody = bos.toByteArray();
|
|
|
+
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.setContentType(MediaType.parseMediaType("multipart/form-data; boundary=" + boundary));
|
|
|
+ headers.setContentLength(multipartBody.length);
|
|
|
+ headers.setAccept(java.util.List.of(MediaType.ALL));
|
|
|
+ if (userAgent != null && !userAgent.isBlank()) {
|
|
|
+ headers.set(HttpHeaders.USER_AGENT, userAgent.trim());
|
|
|
+ }
|
|
|
+ if (targetHostHeader != null && !targetHostHeader.isBlank()) {
|
|
|
+ headers.set(HttpHeaders.HOST, targetHostHeader.trim());
|
|
|
+ }
|
|
|
+ if (forceConnectionClose) {
|
|
|
+ headers.setConnection("close");
|
|
|
+ }
|
|
|
+ if (authorization != null && !authorization.isBlank()) {
|
|
|
+ headers.set(HttpHeaders.AUTHORIZATION, authorization.trim());
|
|
|
+ }
|
|
|
+
|
|
|
+ HttpEntity<byte[]> req = new HttpEntity<>(multipartBody, headers);
|
|
|
+ ResponseEntity<String> resp;
|
|
|
+ try {
|
|
|
+ resp = buildRestTemplate().exchange(url, HttpMethod.POST, req, String.class);
|
|
|
+ } catch (ResourceAccessException e) {
|
|
|
+ log.warn("转发 testtongue check-image JDK HttpClient 失败,尝试降级为 HttpURLConnection 重试,url={}, reason={}",
|
|
|
+ url, e.getMessage());
|
|
|
+ resp = buildSimpleRestTemplate().exchange(url, HttpMethod.POST, req, String.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("转发 testtongue check-image 完成,url={}, status={}, costMs={}", url,
|
|
|
+ resp != null ? resp.getStatusCode() : null, (System.currentTimeMillis() - start));
|
|
|
+ return toJsonResponse(resp);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("转发 testtongue check-image 失败,url={}", url, e);
|
|
|
+ return ResponseEntity.status(HttpStatus.BAD_GATEWAY)
|
|
|
+ .contentType(MediaType.APPLICATION_JSON)
|
|
|
+ .body(JSONUtil.toJsonStr(R.fail("转发失败:" + e.getMessage())));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public ResponseEntity<String> forwardDetail(String patientId,
|
|
|
String projectId,
|
|
|
Long timestamp,
|
|
|
@@ -281,6 +360,27 @@ public class ForwardRobotService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 通用:转发 GET(用于 /mask-config 等简单查询接口)
|
|
|
+ */
|
|
|
+ public ResponseEntity<String> forwardGet(String path) {
|
|
|
+ String url = joinUrl(targetBaseUrl, path);
|
|
|
+ try {
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.setAccept(java.util.List.of(MediaType.APPLICATION_JSON, MediaType.ALL));
|
|
|
+ if (targetHostHeader != null && !targetHostHeader.isBlank()) {
|
|
|
+ headers.set(HttpHeaders.HOST, targetHostHeader.trim());
|
|
|
+ }
|
|
|
+ ResponseEntity<String> resp = buildRestTemplate().exchange(url, HttpMethod.GET, new HttpEntity<>(headers), String.class);
|
|
|
+ return toJsonResponse(resp);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("转发 GET 失败(机器人端),url={}", url, e);
|
|
|
+ return ResponseEntity.status(HttpStatus.BAD_GATEWAY)
|
|
|
+ .contentType(MediaType.APPLICATION_JSON)
|
|
|
+ .body(JSONUtil.toJsonStr(R.fail("转发失败:" + e.getMessage())));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 通用:转发 JSON POST(用于 /llm-call、/generate-sign 等)
|
|
|
*/
|