实现SuperAgent特殊入口结果处理
This commit is contained in:
@@ -4,10 +4,12 @@ import cn.nianxx.thhotel.integrations.ai.superagent.common.request.SuperAgentTas
|
||||
import cn.nianxx.thhotel.integrations.ai.superagent.service.SuperAgentTaskResultSecurityService;
|
||||
import cn.nianxx.thhotel.integrations.ai.superagent.service.impl.SuperAgentTaskResultException;
|
||||
import cn.nianxx.thhotel.integrations.ai.superagent.service.impl.SuperAgentTaskResultProperties;
|
||||
import cn.nianxx.thhotel.integrations.messaging.agentbus.adapter.AgentBusProperties;
|
||||
import cn.nianxx.thhotel.workflows.reservation.common.result.SuperAgentTaskResultResponse;
|
||||
import cn.nianxx.thhotel.workflows.reservation.service.ReservationAiTaskIntakeService;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.InvalidMediaTypeException;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@@ -27,6 +29,7 @@ public class SuperAgentTaskResultController {
|
||||
|
||||
private final SuperAgentTaskResultSecurityService securityService;
|
||||
private final SuperAgentTaskResultProperties properties;
|
||||
private final AgentBusProperties agentBusProperties;
|
||||
private final ReservationAiTaskIntakeService intakeService;
|
||||
|
||||
/**
|
||||
@@ -35,18 +38,21 @@ public class SuperAgentTaskResultController {
|
||||
public SuperAgentTaskResultController(
|
||||
SuperAgentTaskResultSecurityService securityService,
|
||||
SuperAgentTaskResultProperties properties,
|
||||
AgentBusProperties agentBusProperties,
|
||||
ReservationAiTaskIntakeService intakeService) {
|
||||
this.securityService = securityService;
|
||||
this.properties = properties;
|
||||
this.agentBusProperties = agentBusProperties;
|
||||
this.intakeService = intakeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收 SuperAgent AI 任务结果,先限制请求体大小,再完成 HMAC 鉴权,最后委托业务服务创建 CP1-3 数据。
|
||||
* 接收 SuperAgent AI 任务结果,支持 JSON 和 S000/S999 文本结果;HMAC 始终基于原始请求体校验。
|
||||
*/
|
||||
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<SuperAgentTaskResultResponse> accept(
|
||||
@RequestBody(required = false) String rawBody,
|
||||
@RequestHeader(name = "Content-Type", required = false) String contentType,
|
||||
@RequestHeader(name = "X-TH-Hotel-SuperAgent-Client-Id", required = false) String clientId,
|
||||
@RequestHeader(name = "X-TH-Hotel-SuperAgent-Timestamp", required = false) String timestamp,
|
||||
@RequestHeader(name = "X-TH-Hotel-SuperAgent-Nonce", required = false) String nonce,
|
||||
@@ -54,6 +60,7 @@ public class SuperAgentTaskResultController {
|
||||
@RequestHeader(name = "X-TH-Hotel-Request-Id", required = false) String requestId) {
|
||||
String requestBody = rawBody == null ? "" : rawBody;
|
||||
rejectBodyWhenTooLarge(requestBody);
|
||||
rejectUnsupportedContentType(contentType);
|
||||
securityService.verify(new SuperAgentTaskResultSecurityRequest(
|
||||
"POST",
|
||||
REQUEST_PATH,
|
||||
@@ -63,11 +70,45 @@ public class SuperAgentTaskResultController {
|
||||
signature,
|
||||
requestBody
|
||||
));
|
||||
SuperAgentTaskResultResponse response = intakeService.accept(requestBody, clientId, requestId);
|
||||
SuperAgentTaskResultResponse response = intakeService.accept(
|
||||
requestBody,
|
||||
clientId,
|
||||
requestId,
|
||||
agentBusProperties.getCapture().getDefaultHotelId());
|
||||
HttpStatus status = response.idempotentReplay() ? HttpStatus.OK : HttpStatus.CREATED;
|
||||
return ResponseEntity.status(status).body(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅允许 JSON 结构化任务或 text/plain 入口结果文本,避免其他媒体类型误入业务解析。
|
||||
*/
|
||||
private void rejectUnsupportedContentType(String contentType) {
|
||||
String rawContentType = contentType == null ? "" : contentType.trim();
|
||||
if (rawContentType.isEmpty()) {
|
||||
throw unsupportedContentType();
|
||||
}
|
||||
MediaType mediaType;
|
||||
try {
|
||||
mediaType = MediaType.parseMediaType(rawContentType);
|
||||
} catch (InvalidMediaTypeException exception) {
|
||||
throw unsupportedContentType();
|
||||
}
|
||||
if (!MediaType.APPLICATION_JSON.isCompatibleWith(mediaType)
|
||||
&& !MediaType.TEXT_PLAIN.isCompatibleWith(mediaType)) {
|
||||
throw unsupportedContentType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造统一的 Content-Type 不支持错误,避免把外部原始 Header 写入响应。
|
||||
*/
|
||||
private SuperAgentTaskResultException unsupportedContentType() {
|
||||
return new SuperAgentTaskResultException(
|
||||
HttpStatus.UNSUPPORTED_MEDIA_TYPE,
|
||||
"REQUEST_CONTENT_TYPE_UNSUPPORTED",
|
||||
"Content-Type 仅支持 application/json 或 text/plain。");
|
||||
}
|
||||
|
||||
/**
|
||||
* 在解析 JSON 和校验 Header 之前限制请求体大小,避免超限请求进入后续处理。
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user