Volo.Abp 整合 WebApiClient 从请求中获取 Headers 信息
当前有这样一个场景,需要对外提供接口,而这个接口里面可以不写做具体的逻辑,转手调用别的接口,并将请求该接口的 Headers 与数据一起转发,流程如图:
如图所示 API Service 接收统一接收请求,但并不处理请求,仅仅只做转发。最终处理请求的是 Other Service。接下来是通过 WebApiClient 快速定义转发接口:
namespace ARchGL.Platform.UserRequest
{
#if DEBUG
[Timeout(3000)]
#else
[Timeout(10000)]
#endif
[TraceFilter(OutputTarget = OutputTarget.Console)]
public interface IForwardInfoApi : IHttpApi
{
/// <summary>
/// 上传环境监测工作数据
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("/api/open/iot/v3/env/runtime")]
Task<AjaxResponse<string>> UpdateEnvironment([JsonContent]ForwardInput input);
}
}
接口定义后用起来就和我们自己写的业务逻辑差不多,在需用用到的地方注入即可。下面我们就将这个接口提供给外部调用。
public class ForwardAppService : PlatformAppServiceBase
{
private readonly IForwardInfoApi _forwardInfoApi;
public JianweiAppService(IHostingEnvironment env, IForwardInfoApi forwardInfoApi)
{
_forwardInfoApi = forwardInfoApi;
}
/// <summary>创建项目人员信息</summary>
[DontWrapResult]
public async Task<object> UpdateEnvironment(ForwardInput input)
{
return await _forwardInfoApi.UpdateEnvironment(input);
}
}
至此,我们就将 UpdateEnvironment 接口提供给外部调用了,并且将接口返回信息原封不动的返回给调用方,对于用户来说甚至感受不到接口变化,和直接调用 Other Service 是”一样的“。
注意 UpdateEnvironment 方法使用了 [DontWrapResult] 注解,前面有一篇文章对于用法有提到,点我去了解。
public class ThirdPartyChongqingHttpRegistrarHeaderAttribute : ApiActionFilterAttribute
{
private readonly IConfigurationRoot _appConfiguration;
public ThirdPartyChongqingHttpRegistrarHeaderAttribute(IConfigurationRoot appConfiguration)
{
_appConfiguration = appConfiguration;
}
public override async Task OnBeginRequestAsync(ApiActionContext context)
{
//从请求中获取 Header 并注入 WebApiClient Header 中传递
var request = context.GetService<IHttpContextAccessor>().HttpContext.Request;
if (request != null)
{
var headers = request.Headers;
if (headers != null)
{
var keyId = headers["keyId"].FirstOrDefault();
var code = headers["rCode"].FirstOrDefault();
context.RequestMessage.Headers.Add("keyId", keyId);
context.RequestMessage.Headers.Add("ts", headers["ts"].FirstOrDefault());
context.RequestMessage.Headers.Add("rCode", code);
context.RequestMessage.Headers.Add("signature", headers["signature"].FirstOrDefault());
}
}
await base.OnBeginRequestAsync(context);
}
上面是最终的代码,这里稍微讲下遇到的问题。主要是如何在 OnBeginRequestAsync 中如何实例化的问题。在老版本 ABP 中可以使用 IoCManager 类实例化。在 Volo 中改为 GetService 方式。在任何地方,只要有 GetService 方法就能注入。代码如下:
context.GetService<IHttpContextAccessor>().HttpContext.Request;
通过 GetService 注入 IHttpContextAccessor 就可以取到 Request ,接下来取 Headers 的事情就顺理成章了。另外主张对外接口与业务分离开来这样可以最大限度减少对外接口的变动。