C# Linux上ASP.Net核心Web API中未处理的异常

C# Linux上ASP.Net核心Web API中未处理的异常,c#,asp.net-core,kestrel-http-server,C#,Asp.net Core,Kestrel Http Server,我有一个ASP.NETCore3.1WebAPI,只有一个节点。(这本质上是一个代理端点,不必在这个链的最终端处理噩梦般的白名单。)我也控制的客户端都以编程方式向代理发送相同的请求。有时候,或者经常,Kestral服务器会在Linux服务器的系统日志中报告以下错误 Oct 2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: An unhandled exception has occurred while executing

我有一个ASP.NETCore3.1WebAPI,只有一个节点。(这本质上是一个代理端点,不必在这个链的最终端处理噩梦般的白名单。)我也控制的客户端都以编程方式向代理发送相同的请求。有时候,或者经常,Kestral服务器会在Linux服务器的系统日志中报告以下错误

Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:       An unhandled exception has occurred while executing the request.
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Unexpected end of request content.
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:    at Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException.Throw(RequestRejectionReason reason)
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1ContentLengthMessageBody.ReadAsyncInternal(CancellationToken cancellationToken)
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:    at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.ReadAsyncInternal(Memory`1 buffer, CancellationToken cancellationToken)
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:    at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:    at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:    at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:    at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:    at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMeta
data metadata, Object value)
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:    at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]: --- End of stack trace from previous location where exception was thrown ---
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:    at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boo
lean isCompleted)
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:    at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isComple
ted)
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:    at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:    at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Oct  2 19:06:52 CCBD-Status-API-East CCBD-Status-API[979]:    at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
Startup.cs配置方法

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseExceptionHandler(a => a.Run(async context =>
    {
        var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
        var exception = exceptionHandlerPathFeature.Error;

        var result = JsonConvert.SerializeObject(new {error = exception.Message});
        context.Response.ContentType = "application/json";
        await context.Response.WriteAsync(result);
    }));

    app.UseForwardedHeaders(new ForwardedHeadersOptions
    {
        ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
    });

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}
public void配置(IApplicationBuilder应用程序,IWebHostEnvironment环境)
{
app.UseExceptionHandler(a=>a.Run(异步上下文=>
{
var exceptionHandlerPathFeature=context.Features.Get();
var exception=exceptionHandlerPathFeature.Error;
var result=JsonConvert.SerializeObject(新的{error=exception.Message});
context.Response.ContentType=“应用程序/json”;
wait context.Response.WriteAsync(结果);
}));
app.UseForwardedHeaders(新ForwardedHeaders选项
{
ForwardedHeaders=ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
app.UseRouting();
app.UseEndpoints(端点=>
{
endpoints.MapControllers();
});
}
编辑:添加客户端代码

def check_stream(tc, app, feed, server):
    try:
        logger.info("Check Stream: {}".format(server))
        stream_url = ""
        if server == 'pri':
            stream_url = <Building URL>
        elif server == 'bak':
            stream_url = <Building URL>

        json_input = {"Url": stream_url, "Status": 0}
        logger.info(json_input)
        headers = {'Content-Type': 'application/json'}

        resp = requests.post(<Proxy URL>, data=json.dumps(json_input),
                             headers=headers)
        
        logger.info(resp.headers)
        logger.info("Response Text: {}".format(resp.text))
        results = json.loads(resp.text)
        code = results.get('status')

        return code
    except Exception as e:
        logger.error("Stream Check exception: {} {}".format(type(e).__name__, str(e.args)))
def check_流(tc、应用程序、提要、服务器):
尝试:
info(“检查流:{}”.format(服务器))
stream_url=“”
如果服务器==“pri”:
流地址=
elif服务器=='bak':
流地址=
json_输入={“Url”:流_Url,“状态”:0}
logger.info(json_输入)
headers={'Content-Type':'application/json'}
resp=requests.post(,data=json.dumps(json_输入),
页眉=页眉)
logger.info(相应的标题)
info(“响应文本:{}”.format(resp.Text))
结果=json.loads(resp.text)
代码=结果。获取('状态')
返回码
例外情况除外,如e:
logger.error(“流检查异常:{}{}”。格式(类型(e)。\uuuuuu name\uuuuu,str(e.args)))

我想出来了。我将节点转换为异步,它可以正常工作

public async Task<IActionResult> GetStreamStatusAsync([FromBody] StreamInfo input)
{
    try
    {
        if (!ModelState.IsValid) return BadRequest();
        NetworkCredential netCred = new NetworkCredential(_config.Value.User, _config.Value.Pass);
        var cred = new CredentialCache();
        cred.Add(new Uri(input.Url), "Digest", netCred);
        _logger.LogInformation($"Attempting to get status from: {input.Url}");
        var httpClient = new HttpClient(new HttpClientHandler {Credentials = cred, PreAuthenticate = true});
        var resp = await httpClient.GetAsync(new Uri(input.Url));
        _logger.LogInformation($"{input.Url} returned: {resp.StatusCode}");
        input.Status = (int) resp.StatusCode;

        return Ok(input);
    }
    catch (Exception e)
    {
        _logger.LogError(e.ToString());
        return BadRequest();
    }
}
公共异步任务GetStreamStatusAsync([FromBody]StreamInfo输入)
{
尝试
{
如果(!ModelState.IsValid)返回BadRequest();
NetworkCredential netCred=新的NetworkCredential(_config.Value.User,_config.Value.Pass);
var cred=新凭证缓存();
添加(新的Uri(input.Url),“摘要”,netCred);
_logger.LogInformation($“正在尝试从:{input.Url}获取状态”);
var httpClient=new httpClient(new HttpClientHandler{Credentials=cred,PreAuthenticate=true});
var resp=await-httpClient.GetAsync(新Uri(input.Url));
_logger.LogInformation($“{input.Url}返回:{resp.StatusCode}”);
input.Status=(int)resp.StatusCode;
返回Ok(输入);
}
捕获(例外e)
{
_logger.LogError(例如ToString());
返回请求();
}
}

堆栈跟踪显示http请求结束的时间比预期的要早-这强烈表明问题要么在于客户端如何发送请求,要么在于客户端和服务器之间的某个阶段。你有客户端代码吗?@JasonHolloway在edit中添加了客户端代码。这并没有什么错——在这一点上,我会尝试找出到底是什么让它进入服务器,这是非常可行的(通过谷歌搜索),特别是如果服务器在linux上。您应该能够使用
tcpdump
捕获所有传入消息,然后使用Wireshark之类的工具读取转储。基本上,我认为客户端和服务器之间的某些东西正在干扰请求-很抱歉,我无法提供更多帮助。此线程显示了您所面临的情况,即使细节不完全相同:我在最后注意到在服务器上打开跟踪级别日志的建议(请参阅指向底部的链接),也许这会显示一些东西我不知道你在做什么,我只是看到你异步地得到resp,然后像已经加载一样使用它,这可能不是真的。也许您应该等待
*Async
请求完成?在这一点上,您确定在处理来自流的数据时消息实际上已经完成了吗?在某些框架(node.js)上,您会得到消息的片段,在处理整个消息之前必须重新组合它们。不这样做会导致类似的异常。我只想到两件事。。。
def check_stream(tc, app, feed, server):
    try:
        logger.info("Check Stream: {}".format(server))
        stream_url = ""
        if server == 'pri':
            stream_url = <Building URL>
        elif server == 'bak':
            stream_url = <Building URL>

        json_input = {"Url": stream_url, "Status": 0}
        logger.info(json_input)
        headers = {'Content-Type': 'application/json'}

        resp = requests.post(<Proxy URL>, data=json.dumps(json_input),
                             headers=headers)
        
        logger.info(resp.headers)
        logger.info("Response Text: {}".format(resp.text))
        results = json.loads(resp.text)
        code = results.get('status')

        return code
    except Exception as e:
        logger.error("Stream Check exception: {} {}".format(type(e).__name__, str(e.args)))
public async Task<IActionResult> GetStreamStatusAsync([FromBody] StreamInfo input)
{
    try
    {
        if (!ModelState.IsValid) return BadRequest();
        NetworkCredential netCred = new NetworkCredential(_config.Value.User, _config.Value.Pass);
        var cred = new CredentialCache();
        cred.Add(new Uri(input.Url), "Digest", netCred);
        _logger.LogInformation($"Attempting to get status from: {input.Url}");
        var httpClient = new HttpClient(new HttpClientHandler {Credentials = cred, PreAuthenticate = true});
        var resp = await httpClient.GetAsync(new Uri(input.Url));
        _logger.LogInformation($"{input.Url} returned: {resp.StatusCode}");
        input.Status = (int) resp.StatusCode;

        return Ok(input);
    }
    catch (Exception e)
    {
        _logger.LogError(e.ToString());
        return BadRequest();
    }
}