feat: 完善统一端点响应与请求绑定框架
- 新增 IApiResponse 统一响应契约,覆盖普通响应和分页响应
- 扩展端点映射,支持 IApiResponse 和带请求 DTO 的 MapXxx 重载
- 增加 Body、Query、Route Values 到请求 DTO 的自动绑定
- 增加 PC 端路由模式匹配,支持 {id} 和 {id:int}
- API 与 PC 端点上下文补充路由参数传递
- 调整 OpenAPI 请求类型处理,避免 GET/DELETE 被标记为 JSON Body
- 鉴权端点迁移到强类型请求绑定和 IApiResponse 返回
- 增加统一端点文件流响应支持
This commit is contained in:
@@ -3,7 +3,6 @@ using Avalonia_Common.Core;
|
||||
using Avalonia_Services.Core;
|
||||
using Avalonia_Services.Services.AuthService;
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Avalonia_PC.Authentication
|
||||
@@ -14,16 +13,10 @@ namespace Avalonia_PC.Authentication
|
||||
/// </summary>
|
||||
public sealed class PcAuthEndpointService(PcGlobalTokenService tokenService) : IPcAuthEndpointService
|
||||
{
|
||||
private static readonly JsonSerializerOptions JsonOptions = new()
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
};
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<object?> AuthorizeAsync(ServiceEndpointContext ctx)
|
||||
public async Task<IApiResponse> AuthorizeAsync(PcAuthorizeRequest request, ServiceEndpointContext ctx)
|
||||
{
|
||||
var request = Deserialize<PcAuthorizeRequest>(ctx.Body);
|
||||
var token = await tokenService.AuthorizeAsync(request?.AuthorizationCode);
|
||||
var token = await tokenService.AuthorizeAsync(request.AuthorizationCode);
|
||||
if (token is null)
|
||||
{
|
||||
ctx.StatusCode = 401;
|
||||
@@ -34,10 +27,9 @@ namespace Avalonia_PC.Authentication
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<object?> RefreshAsync(ServiceEndpointContext ctx)
|
||||
public async Task<IApiResponse> RefreshAsync(PcRefreshRequest request, ServiceEndpointContext ctx)
|
||||
{
|
||||
var request = Deserialize<PcRefreshRequest>(ctx.Body);
|
||||
var token = request?.Token ?? ExtractBearerToken(ctx.GetHeader("Authorization"));
|
||||
var token = request.Token ?? ExtractBearerToken(ctx.GetHeader("Authorization"));
|
||||
var refreshed = await tokenService.RefreshAsync(token);
|
||||
if (refreshed is null)
|
||||
{
|
||||
@@ -49,25 +41,11 @@ namespace Avalonia_PC.Authentication
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<object?> LogoutAsync(ServiceEndpointContext ctx)
|
||||
public Task<IApiResponse> LogoutAsync(PcLogoutRequest request, ServiceEndpointContext ctx)
|
||||
{
|
||||
var request = Deserialize<PcLogoutRequest>(ctx.Body);
|
||||
var token = request?.Token ?? ExtractBearerToken(ctx.GetHeader("Authorization"));
|
||||
var token = request.Token ?? ExtractBearerToken(ctx.GetHeader("Authorization"));
|
||||
tokenService.Logout(token);
|
||||
return Task.FromResult<object?>(ResponseHelper.Succeed("退出成功"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将 JSON 请求体反序列化为指定类型。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">目标类型。</typeparam>
|
||||
/// <param name="body">JSON 请求体字符串,可为空。</param>
|
||||
/// <returns>反序列化后的对象;若 body 为空则返回默认值。</returns>
|
||||
private static T? Deserialize<T>(string? body)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(body)
|
||||
? default
|
||||
: JsonSerializer.Deserialize<T>(body, JsonOptions);
|
||||
return Task.FromResult<IApiResponse>(ResponseHelper.Succeed("退出成功"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user