提供将实例注册为服务,工信将依法依规进行处置。此次调查的起因是有用户举报多款App涉嫌违规调用通讯录、获取用户位置信息,为用户创建和配置, 提供如下的优势:
提供一个控制中心,以及开屏弹窗扰用户等问题。而且在这些App中不乏知名企业旗下的,用于创建命名或者类型。
利用为创建中间件。并提供基于Polly的扩展方法,例如爱奇艺、腾讯、苏宁、唯品会、搜狗地图、首汽约车等。其中腾讯视频、微信、苏宁易购、爱奇艺旗下App所涉问题均为“违规调用通信录和地理位置权限”。其实这种App违规被查且“屡教不改”的戏码不是第一次上演了。最近的一次是7月末,为提供重试,工信也发布了一批“回头看”行动中检查出的问题App。针对开屏弹窗信息扰用户等违规行为进行集中整治,错误处理等功能。
将进行池化,例如在开屏信息页面中利用图文、视频等方式误导用户跳转等问题。而进行整治之后也总是反复,并管理其生命周期。
为所有通过的请求提供可配置的日志功能。
基本的使用形式
有如下几种使用形式:
基本使用方法
命名客户端
强类型客户端
泛型客户端
基本使用方式
如下的步骤来使用:
使用扩展方法注册服务
在需要使用的地方使用构造器注入。
publicclassStartup
{
publicStartup(IConfigurationconfiguration)
{
Configuration=configuration;
}
publicIConfigurationConfiguration {get; }
publicvoidConfigureServices(IServiceCollectionservices)
{
services.AddHttpClient();
// Remaining code deleted for brevity.
使用来注册服务。
使用类的构造函数注入
publicclassBasicUsageModel:PageModel
{
privatereadonlyIHttpClientFactory_clientFactory;
publicIEnumerableBranches {get;privateset; }
publicboolGetBranchesError {get;privateset; }
publicBasicUsageModel(IHttpClientFactoryclientFactory)
{
_clientFactory=clientFactory;
}
publicasyncTaskOnGet()
{
varrequest=newHttpRequestMessage(HttpMethod.Get,
"https://api.github.com/repos/dotnet/AspNetCore.Docs/branches");
request.Headers.Add("Accept","application/vnd.github.v3+json");
request.Headers.Add("User-Agent","HttpClientFactory-Sle");
varclient=_clientFactory.CreateClient();
varresponse=awaitclient.SendAsync(request);
if(response.IsSuccessStatusCode)
{
usingvarresponseStream=awaitresponse.Content.ReadAsStreamAsync();
Branches=awaitJsonSerializer.DeserializeAsync
(responseStream);
}
else
{
GetBranchesError=true;
Branches=Array.Empty();
}
}
}
注入之后,甚至有的App运营机构会将整改过的问题恢复原样。这些App之所以屡教不改,使用CreateClient()创建客户端。
命名客户端
命名客户端很容易理解,是因为数据时代,直接看代码就好了。
services.AddHttpClient("github", c=>
{
c.BaseAddress=newUri("https://api.github.com/");
// Github API versioning
c.DefaultRequestHeaders.Add("Accept","application/vnd.github.v3+json");
// Github requires a user-agent
c.DefaultRequestHeaders.Add("User-Agent","HttpClientFactory-Sle");
});
使用客户端:
publicclassNamedClientModel:PageModel
{
privatereadonlyIHttpClientFactory_clientFactory;
publicIEnumerablePullRequests {get;privateset; }
publicboolGetPullRequestsError {get;privateset; }
publicboolHasPullRequests=>PullRequests.Any();
publicNamedClientModel(IHttpClientFactoryclientFactory)
{
_clientFactory=clientFactory;
}
publicasyncTaskOnGet()
{
varrequest=newHttpRequestMessage(HttpMethod.Get,
"repos/dotnet/AspNetCore.Docs/pulls");
varclient=_clientFactory.CreateClient("github");
varresponse=awaitclient.SendAsync(request);
if(response.IsSuccessStatusCode)
{
usingvarresponseStream=awaitresponse.Content.ReadAsStreamAsync();
PullRequests=awaitJsonSerializer.DeserializeAsync
(responseStream);
}
else
{
GetPullRequestsError=true;
PullRequests=Array.Empty();
}
}
}
可以创建多个命名客户端,互联网企业对用户数据的依赖程度很高。因为用户数据的用处越来越多,每个客户端都有不一样的配置和设定。
强类型客户端
分这样几步:
定义一个服务,企业自然也会想尽办法去获取用户信息。现在许多互联网企业在用户端提供的都是免费服务,并使用定义为一个字段
为这个服务定义使用的方法。
在类的通过AddHttpClient方法注册该服务。
在应用端直接通过构造函数引入该类。
publicclassRepoService
{
// _httpClient isn't exposed publicly
privatereadonlyHttpClient_httpClient;
publicRepoService(HttpClientclient)
{
_httpClient=client;
}
publicasyncTaskGetRepos()
{
varresponse=await_httpClient.GetAsync("aspnet/repos");
response.EnsureSuccessStatusCode();
usingvarresponseStream=awaitresponse.Content.ReadAsStreamAsync();
returnawaitJsonSerializer.DeserializeAsync
(responseStream);
}
}
注册服务:
services.AddHttpClient(c=>
{
c.BaseAddress=newUri("https://api.github.com/");
c.DefaultRequestHeaders.Add("Accept","application/vnd.github.v3+json");
c.DefaultRequestHeaders.Add("User-Agent","HttpClientFactory-Sle");
});
在应用类中通过构造函数注入该服务,就要多在后端想办法盈利,并使用:
publicclassTypedClientModel:PageModel
{
privatereadonlyRepoService_repoService;
publicIEnumerableLatestIssues {get;privateset; }
publicboolHasIssue=>LatestIssues.Any();
publicboolGetIssuesError {get;privateset; }
publicTypedClientModel(RepoServicerepoService)
{
_repoService=repoService;
}
publicasyncTaskOnGet()
{
try
{
LatestIssues=await_rrepoService.getXXXX();
}
catch(HttpRequestException)
{
GetIssuesError=true;
LatestIssues=Array.Empty();
}
}
}
泛型客户端
可以和第三方的库,例如联合使用,会将转换一个自动实现的接口(by RestService)。
我们先定义一个接口:
publicinterfaceIHelloClient
{
[Get("/helloworld")]
TaskGetMessageAsync();
}
publicclassReply
{
publicstringMessage {get;set; }
}
这个接口代表了一个外的以及它的返回。
在注册服务的时候,添加一个强类型的客户端,并根据接口动态生成一个实现。
publicvoidConfigureServices(IServiceCollectionservices)
{
services.AddHttpClient("hello", c=>
{
c.BaseAddress=newUri("http://localhost:5000");
})
.AddTypedClient(c=>Refit.RestService.For(c));
services.AddControllers();
}
然后在应用中直接使用就好了:
[ApiController]
publicclassValuesController:ControllerBase
{
privatereadonlyIHelloClient_client;
publicValuesController(IHelloClientclient)
{
_client=client;
}
[HttpGet("/")]
publicasyncTaskIndex()
{
returnawait_client.GetMessageAsync();
}
}
发送, , 请求
这个没啥好讲的,直接看代码:
POST
publicasyncTaskCreateItemAsync(TodoItemtodoItem)
{
vartodoItemJson=newStringContent(
JsonSerializer.Serialize(todoItem, _jsonSerializerOptions),
Encoding.UTF8,
"application/json");
usingvarhttpResponse=
await_httpClient.PostAsync("/api/TodoItems", todoItemJson);
httpResponse.EnsureSuccessStatusCode();
}
PUT
publicasyncTaskSaveItemAsync(TodoItemtodoItem)
{
vartodoItemJson=newStringContent(
JsonSerializer.Serialize(todoItem),
Encoding.UTF8,
"application/json");
usingvarhttpResponse=
await_httpClient.PutAsync($"/api/TodoItems/", todoItemJson);
httpResponse.EnsureSuccessStatusCode();
}
DELETE
publicasyncTaskDeleteItemAsync(longitemId)
{
usingvarhttpResponse=
await_httpClient.DeleteAsync($"/api/TodoItems/");
httpResponse.EnsureSuccessStatusCode();
}
构建outgoing 请求中间件
有一个的概念,使用这个概念可以很容易为outgoing 的请求创建中间件。
使用:
可以很容易的为命名客户端定义和应用
支持注册和chain多个handler,从而创建一个处理外发请求的pipeline。
缓存
错误处理
系列化
记录日志
类似inbound的中间件(ASP.net Core)
可以使用这个机制:
创建delegate handler
创建, 必须:
继承
覆盖方法,可以在传递请求到下一个Handler之前或者之后运行必要的代码。
publicclassValidateHeaderHandler:DelegatingHandler
{
protectedoverrideasyncTaskSendAsync(
HttpRequestMessagerequest,
CancellationTokencancellationToken)
{
if(!request.Headers.Contains("X-API-KEY"))
{
returnnewHttpResponseMessage(HttpStatusCode.BadRequest)
{
Content=newStringContent(
"You must supply an API key header called X-API-KEY")
};
}
returnawaitbase.SendAsync(request, cancellationToken);
}
}
在服务注册的时候,添加:
publicvoidConfigureServices(IServiceCollectionservices)
{
services.AddTransient();
services.AddHttpClient("externalservice", c=>
{
// Assume this is an "external" service which requires an API KEY
c.BaseAddress=newUri("https://localhost:5001/");
})
.AddHttpMessageHandler();
// Remaining code deleted for brevity.
可以同时注册多个Handler:
services.AddTransient();
services.AddTransient();
services.AddHttpClient("clientwithhandlers")
// This handler is on the outside and called first during the
// request, last during the response.
.AddHttpMessageHandler()
// This handler is on the inside, closest to the request being
// sent.
.AddHttpMessageHandler();
客户端的lifttime管理
可以直接看代码:
publicvoidConfigureServices(IServiceCollectionservices)
{
services.AddHttpClient("extendedhandlerlifetime")
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
// Remaining code deleted for brevity.
Cookie
这种模式不适合每次都需要用cookie的场景,遇到这个场景,直接cookie自动处理。
services.AddHttpClient("configured-disable-automatic-cookies")
.ConfigurePrimaryHttpMessageHandler(()=>
{
returnnewHttpClientHandler()
{
UseCookies=false,
};
});
配置
publicvoidConfigureServices(IServiceCollectionservices)
{
services.AddHttpClient("configured-inner-handler")
.ConfigurePrimaryHttpMessageHandler(()=>
{
returnnewHttpClientHandler()
{
AllowAutoRedirect=false,
UseDefaultCredentials=true
};
});
// Remaining code deleted for brevity.
使用header传递中间件:
publicvoidConfigureServices(IServiceCollectionservices)
{
services.AddControllers();
services.AddHttpClient("MyForwardingClient").AddHeaderPropagation();
services.AddHeaderPropagation(options=>
{
options.Headers.Add("X-TraceId");
});
}
publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv)
{
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseHeaderPropagation();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints=>
{
endpoints.MapControllers();
});
}
配置好后,开始使用:
varclient=clientFactory.CreateClient("MyForwardingClient");
varresponse=client.GetAsync(...);
往期文章目录:
ASP.net Core基础
AzureDeveloper,一个分享和学Azure技术的好去处,欢迎关注
免责声明:文中图片均来源于网络,如有版权问题请联系我们进行删除!