【问题标题】:Can I force Azure API Management to return 400 instead of 404 when missing required field?缺少必填字段时,是否可以强制 Azure API 管理返回 400 而不是 404?
【发布时间】:2021-09-25 00:11:03
【问题描述】:

我们有一个应用程序需要提供一些字段。如果这些字段不存在,我们将返回 400 响应,解释正确的错误消息中缺少的内容。将 APIM 添加到混合中似乎会使它复杂化很多。由于 APIM 知道该字段是必需的,因此它看起来会缩短 curcuit 并返回 404 并带有通用消息,而不是我们自我解释的错误消息。

这是为 APIM 关闭此功能的一种方式吗?

【问题讨论】:

  • 按字段,你是指查询参数吗?
  • 是的。我们有一些必填字段。我确实理解 APIM 是按照其最佳意图做某事,但我宁愿在此处控制错误消息。
  • 如果查询参数中缺少字段,我认为它不会响应 404。当您请求不正确的 url 时,可能只是响应 404 错误。您能否提供您的后端网址示例以及您的 APIM api 示例?
  • 但这就是问题所在。由于我们有所需的查询参数,因此如果缺少所需的参数,apim 将使用 404 短路请求并返回 404,而不是让查询通过应用程序。所以也许这是错误的描述。
  • 我自己遇到了这个问题。我发现 APIM 正在将我所需的查询参数作为模板参数导入,这会导致在未提供查询时 URL 匹配失败。但是,可以在从 OpenAPI 规范导入端点后对其进行编辑。我能够删除模板参数并添加所需的查询参数,它按预期工作。在docs.microsoft.com/en-us/answers/questions/829259/… 看到我的问题

标签: azure azure-api-management


【解决方案1】:

我遇到了同样的问题,我最终改变了我的方法。我所做的是在应用程序端对其进行配置,并使用 FluentValidation 使查询字符串参数成为必需。所以,我的模型现在看起来像这样:

using FluentValidation;

public class UrlQueryParameters
{
    public string PropertyA { get; set; }
    public string PropertyB { get; set; }
}

public class UrlQueryParametersValidator : AbstractValidator<UrlQueryParameters>
{
    public UrlQueryParametersValidator()
    {
        RuleFor(o => o.PropertyA)
            .NotEmpty()
            .WithMessage("The 'PropertyA' parameter was missing or a value was not provided.");

        RuleFor(o => o.PropertyB)
            .NotEmpty()
            .WithMessage("The 'PropertyB' parameter was missing or a value was not provided.");
    }
}

前面的代码为PropertyAPropertyB 属性定义了一些带有自定义消息的验证规则。

现在,通过在Startup.cs 文件的ConfigureServices 方法中添加以下代码,启用 FluentValidation 作为我们应用程序的默认验证机制:

public void ConfigureServices(IServiceCollection services) {
    // Rest of the code omitted for brevity
    
    services
      .AddControllers()
      .AddFluentValidation(fv => 
      { 
          fv.DisableDataAnnotationsValidation = true;
          
          // The following line registers ALL public validators in the assembly containing UrlQueryParametersValidator
          // There is no need to register additional validators from this assembly.
          fv.RegisterValidatorsFromAssemblyContaining<UrlQueryParametersValidator>(lifetime: ServiceLifetime.Singleton);
      });
}

此时,您的 API 端点应验证请求中的所需参数,并且 APIM 不应在您尝试访问 /api/foo/{id} 时通过抛出 404 Not Found 来缩短请求。

之所以可行,是因为 Swashbuckle 不会自动从 FluentValidation 导入验证规则。这意味着,在 Swagger UI 中查看属性 PropertyAPropertyB 时,它们不会被标记为必需。这是这种方法的缺点,因为来自 Swagger UI 的必需查询字符串参数不会被标记为必需,这可能会让消费者感到困惑。但对我来说,向消费者返回带有有意义信息的正确 StatusCode 更为重要,这就是我暂时坚持这种解决方法的原因。您可以尝试使用 MicroElements.Swashbuckle.FluentValidation 在 Swagger UI 架构中根据需要至少设置/标记参数。但仅此而已。

我在这里写了一篇博客:Dirty Hack on Making the Required QueryString Params to Work in Azure APIM

【讨论】:

    【解决方案2】:

    在 API/产品/全局级别策略添加 on-error 部分,使用选择策略检查是否找到操作:

    <choose>
      <when condition="@(context.LastError.Source == "configuration" && context.LastError.Reason == "OperationNotFound")">
        <return-response>
          <set-status code="400" reason="Bad Request" />
        </return-response>
      </when>
    </choose>
    

    【讨论】:

    • 谢谢,但也许我应该详细说明我的意思。似乎 APIM 在调用后端之前“劫持”了请求并返回 404,因为它与操作不匹配。这不是我预期的行为。
    • 那么您应该将这些查询参数标记为不需要。然后 APIM 将匹配带有和不带有查询参数的操作。
    • 我认为这不是答案。我希望规范根据需要生成,以便您可以阅读开放 api 规范并查看您必须提供的内容。如果有人不遵循规范,我还想返回好的错误消息,而这不可能是 apim 的行为方式。
    猜你喜欢
    • 2013-04-03
    • 1970-01-01
    • 1970-01-01
    • 2015-03-15
    • 2020-12-12
    • 2016-06-09
    • 1970-01-01
    • 1970-01-01
    • 2021-10-03
    相关资源
    最近更新 更多