我尝试设置一个multipart/form-data
GET请求的内容类型,该请求缺少边界。我已经尝试过以下代码:
public class BoundaryMiddleware
{
private readonly RequestDelegate _next;
public BoundaryMiddleware(RequestDelegate next)
{
this._next = next;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Path.Value.Contains("api/webhook"))
{
if (context.Request.ContentType == "multipart/form-data")
{
context.Request.ContentType = $"multipart/form-data; boundary=\"{Guid.NewGuid()}\"";
}
}
await _next.Invoke(context);
}
}
启动文件:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory,
IConfiguration configuration)
{
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
loggerFactory.AddDebug();
}
app.UseMiddleware<BoundaryMiddleware>();
app.UseMvc();
}
}
但是,此代码引发以下异常:
System.IO.IOException: Unexpected end of Stream, the content may have already been read by another component.
at Microsoft.AspNetCore.WebUtilities.MultipartReaderStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
at Microsoft.AspNetCore.WebUtilities.StreamHelperExtensions.DrainAsync(Stream stream, ArrayPool`1 bytePool, Nullable`1 limit, CancellationToken cancellationToken)
at Microsoft.AspNetCore.WebUtilities.MultipartReader.ReadNextSectionAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Http.Features.FormFeature.InnerReadFormAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.ModelBinding.FormValueProviderFactory.AddValueProviderAsync(ValueProviderFactoryContext context)
at Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider.CreateAsync(ActionContext actionContext, IList`1 factories)
at Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider.CreateAsync(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
是否可以修改此内容?谢谢
编辑:这是传递给Web应用程序的请求:
GET /api/webhook HTTP/1.1
Host: localhost:5000
content-type: multipart/form-data
cache-control: no-cache
编辑2:如果我按原样发送请求,则会引发此异常:
System.IO.InvalidDataException: Missing content-type boundary.
at Microsoft.AspNetCore.Http.Features.FormFeature.GetBoundary(MediaTypeHeaderValue contentType, Int32 lengthLimit)
at Microsoft.AspNetCore.Http.Features.FormFeature.InnerReadFormAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.ModelBinding.FormValueProviderFactory.AddValueProviderAsync(ValueProviderFactoryContext context)
at Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider.CreateAsync(ActionContext actionContext, IList`1 factories)
at Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider.CreateAsync(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Internal.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
答案 0 :(得分:1)
.Net HTTP标头通常有点有趣,当尝试将原始http请求转换为HttpRequest
时,框架会做出各种假设,然后在Controller上调用动作时会进行进一步处理。
鉴于没有主体,因此拥有Content-Type标头或边界值几乎没有意义。您可能会发现完全删除标题更为有效。
public async Task Invoke(HttpContext context)
{
if (context.Request.Path.Value.Contains("api/webhook"))
{
if (context.Request.ContentType == "multipart/form-data")
context.Request.Headers.Remove("Content-Type");
}
await _next.Invoke(context);
}
答案 1 :(得分:0)
对于HTTP GET,内容类型HTTP标头根本不重要,内容类型HTTP标头是required,可以在具有正文的请求上设置(通常为PUT和POST)。
实际上,get可以与主体一起使用,如果您的API需要支持这种好运,请参阅here,但这并不是不可能!
否则,如果您的API使用者没有发送正文,请执行以下操作:
[AllowAnonymous]
[HttpGet]
[Route("api/webhook")]
public IActionResult GetWebhook()
{
// rock and roll
return Ok();
}
使用CURL测试(使用本地语言)
curl -X GET "https://localhost:44395/api/webhook" -H "content-type: multipart/form-data" --verbose
不需要该请求拦截器。