當前有這樣一個場景,需要對外提供接口,而這個接口裏面可以不寫做具體的邏輯,轉手調用別的接口,並將請求該接口的 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 的事情就順理成章了。另外主張對外接口與業務分離開來這樣可以最大限度減少對外接口的變動。