Codex 审计发现 124 个问题,修复 59 个 P0-P2 级别问题: P0 (CRITICAL): - TOCTOU 竞态: TransientRateStore/SseConcurrencyGuard 改用 wp_cache_add 原子锁 - REST 路由: __return_true → check_bearer_present 轻量鉴权 - Schema 验证: messages/tools/tool_choice 添加完整 validate_callback - SQL 列名不匹配: upsert 查询对齐 SchemaManager 定义 - SQL 表名插值: 统一使用 %i 占位符 P1 (HIGH): - IP hash 加盐 (HMAC) + IP 解析统一 (context 共享) - Header 注入防护 (X-Request-Id/响应头 \r\n 过滤) - 数值参数范围校验 (temperature/top_p/penalties/max_tokens) - insert_key 错误处理 + revoke_key 审计日志 - Pipeline finally 保护 + RateLimiter rollback 双 store - wp_unslash 补全 + strtotime 返回值检查 - RedisRateStore $rid 冒号验证 - UpstreamStreamClient catch \Throwable P2 (MEDIUM): - AuditLogRepository DRY (提取 build_where_clause) - Token 估算 CJK 优化 (mb_strlen) - ResponseTransformMiddleware null 检查 - 嵌入响应 usage 数据修复 - SchemaManager autoload 优化 25 files changed, ~530 insertions, ~190 deletions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
84 lines
1.9 KiB
PHP
84 lines
1.9 KiB
PHP
<?php
|
|
/**
|
|
* Response Transform Middleware
|
|
*
|
|
* Pipeline stage that transforms WPMind results into OpenAI-compatible responses.
|
|
*
|
|
* @package WPMind\Modules\ApiGateway\Pipeline
|
|
* @since 1.0.0
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace WPMind\Modules\ApiGateway\Pipeline;
|
|
|
|
use WPMind\Modules\ApiGateway\Transform\ResponseTransformer;
|
|
|
|
/**
|
|
* Class ResponseTransformMiddleware
|
|
*
|
|
* Reads the internal result from the context, transforms it
|
|
* into an OpenAI-compatible format, and sets the REST response.
|
|
*/
|
|
final class ResponseTransformMiddleware implements GatewayStageInterface {
|
|
|
|
private ResponseTransformer $transformer;
|
|
|
|
public function __construct() {
|
|
$this->transformer = new ResponseTransformer();
|
|
}
|
|
|
|
/**
|
|
* Process the gateway request context.
|
|
*
|
|
* @param GatewayRequestContext $context Shared request context.
|
|
*/
|
|
public function process( GatewayRequestContext $context ): void {
|
|
if ( $context->has_error() ) {
|
|
return;
|
|
}
|
|
|
|
$result = $context->get_internal_result();
|
|
|
|
if ( $result === null ) {
|
|
$context->set_error(
|
|
new \WP_Error(
|
|
'empty_upstream_result',
|
|
'No result from upstream provider.',
|
|
[ 'status' => 502 ]
|
|
)
|
|
);
|
|
return;
|
|
}
|
|
|
|
$payload = $context->get_internal_payload() ?? [];
|
|
$operation = $context->operation();
|
|
|
|
$original_model = $payload['original_model'] ?? $payload['model'] ?? '';
|
|
|
|
$data = match ( $operation ) {
|
|
'chat.completions' => $this->transformer->transform_chat(
|
|
$result,
|
|
$original_model,
|
|
$context->request_id()
|
|
),
|
|
'embeddings' => $this->transformer->transform_embedding(
|
|
$result,
|
|
$original_model,
|
|
$context->request_id()
|
|
),
|
|
'models' => $result,
|
|
'responses' => $this->transformer->transform_chat(
|
|
$result,
|
|
$original_model,
|
|
$context->request_id()
|
|
),
|
|
default => $result,
|
|
};
|
|
|
|
$response = new \WP_REST_Response( $data, 200 );
|
|
$response->header( 'Content-Type', 'application/json' );
|
|
|
|
$context->set_rest_response( $response );
|
|
}
|
|
}
|