我正在使用 .NET Core 2.1 和 Web API ,该API托管在 Azure 上作为应用程序服务。
UserService :<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0" />
服务1 :<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.2" />
服务1 基本上是通过同步http调用来调用 UserService 。
对于我的HttpClient
,我实现了一个非常简单的包装器类,您可以在这里看到它(仅是相关的GET实现):
public async Task<T> GetAsync<T>(string relativeUri, string accessToken)
{
var result = default(T);
try
{
var httpRequestMessage = CreateHttpRequestMessage(HttpMethod.Get, relativeUri, accessToken);
// SendAsync is supposed to be thread safe
var response = await _httpClient.SendAsync(httpRequestMessage);
response.EnsureSuccessStatusCode();
// TODO : Only for debugging purposes
var content = await response.Content.ReadAsStringAsync();
_customHttpClientLogger.LogInformation(content);
using (var stream = await response.Content.ReadAsStreamAsync())
{
using (var reader = new JsonTextReader(new StreamReader(stream)))
{
result = _jsonSerializer.Deserialize<T>(reader);
_customHttpClientLogger.LogInformation("HTTP GET to {url} was successful.", relativeUri);
}
}
return result;
}
catch (Exception ex)
{
_customHttpClientLogger.LogError(ex, "HTTP GET to {url} received an error.", relativeUri);
throw;
}
}
private HttpRequestMessage CreateHttpRequestMessage(HttpMethod httpMethod, string relativeUri, string accessToken, string authenticationSchema = BEARER)
{
var request = new HttpRequestMessage()
{
RequestUri = new Uri(relativeUri, UriKind.Relative),
Method = httpMethod,
};
// Has to be added on a per-request basis, otherwise it would be shared with other requests.
request.Headers.Add("Authorization", $"{authenticationSchema} {accessToken}");
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Accept-Encoding", "gzip");
return request;
}
services.AddHttpClient<UserServiceHttpClient>()
.ConfigureHttpMessageHandlerBuilder(c => new HttpClientHandler()
{
UseProxy = false,
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
})
.AddHttpMessageHandler<CorrelationIdDelegatingHandler>();
[HttpGet("api/user")]
[MapToApiVersion("1.0")]
[Produces("application/json")]
[SwaggerResponse((int)HttpStatusCode.OK, Type = typeof(List<User>), Description = "A list of user entities.")]
[SwaggerResponse((int)HttpStatusCode.InternalServerError, Description = "An error occured.")]
public async Task<IActionResult> GetAllAsync()
{
try
{
var users = await _userService.GetAllAsync();
return Ok(users);
}
catch (Exception ex)
{
_userControllerLogger.LogError(ex.InnerException ?? ex,
"An error occcured in the method {method}() in the class '{class}'.", nameof(GetAllAsync), nameof(UserController));
}
return StatusCode(StatusCodes.Status500InternalServerError);
}
这里的所有内容在我的 localhost 环境中都可以很好地运行,并且请求由 Service 1 处理。不幸的是,一旦我将其托管在Azure上,对api /api/user
的调用就会返回类似以下内容的HttpContent
。
var content = await response.Content.ReadAsStringAsync();
_customHttpClientLogger.LogInformation(content);
? ?I?%&/m?{J?J??t??
$?@ ????????? iG#)?* ?? eVe] f @ ???? {??? {???;?N'???? \ fdl ?? J ??!???????〜|?“ ???? * f =?}?n ?? E ??? z ?? <[6?u ????? O?j?U?v: / ?? v?v ??????????? [???????? EV ?? Y?7?G ???} ?? 9}?i?:?[?? ??? q ?? ??X?T3??????E{MIg??h?????O??_]L????>Z??yQ?g??^dm???IQ]??j
gi?
有趣的是,如果我直接通过 Postman 调用 UserService (/api/user
),那么我确实会收到适当的json
响应。我还确保使用与代码中完全相同的HttpHeaders
。
本地主机:
天蓝色:
无论采用哪种执行路径(也是无效的执行路径),都会始终调用用户服务,并返回成功响应。我可以通过远程调试来验证用户服务始终返回OK()
响应。
我真的很努力地找出编码部分可能出了错。
Azure 中的 UserService 似乎可以正常工作,但是一旦我从 Service 1 调用它,它似乎就不再起作用
是不是某些HttpMessageHandler
或Middleware
干扰了请求?
听起来很奇怪,此问题仅在 Azure 中托管时出现。
是否有任何Azure特定的出站规则或拦截器会篡改我的请求?
以下是我用于服务1 的 NuGet软件包:
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.6.0" />
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="2.3.0" />
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="1.1.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.1.1" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.1" />
<PackageReference Include="Serilog" Version="2.7.1" />
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.1.2" />
<PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.0" />
<PackageReference Include="Serilog.Sinks.Seq" Version="4.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.1" PrivateAssets="All" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.1" PrivateAssets="All" />
我将非常感谢能为我指明正确方向的一切。
谢谢!