【问题标题】:HTTP 413 error when using spring boot with Angular 4使用带有 Angular 4 的 Spring Boot 时出现 HTTP 413 错误
【发布时间】:2018-08-23 23:12:35
【问题描述】:

我的系统由一个 Angular 应用程序组成,该应用程序与 Spring Boot 应用程序中的 REST 端点 (POST) 进行通信。 Spring boot 配置为使用 jetty 作为嵌入式服务器。 Angular 应用程序具有调用 REST 端点并将 json 对象作为有效负载发送的 TypeScript 代码。 json 对象的大小会根据用户在浏览器中的选择从 1 MB 到 10 MB 不等。 我的 Spring Boot 应用程序在运行 Linux (CentOS) 的 Azure VM 中运行。 对于某些请求,我收到 HTTP 错误 413:请求大小太大。 我做了一些搜索,发现了 2 种机制来调整 spring boot 应用程序以克服这个限制。

选项 1 使用此属性更改 application.properties 中的请求大小限制 server.jetty.max-http-post-size=20971520 # HTTP post 或 put 内容的最大大小(以字节为单位)。

选项 2 使用主应用程序类中的一些 java 代码覆盖码头 maxFormContentSize

@Bean
public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
    JettyEmbeddedServletContainerFactory jettyContainer =
            new JettyEmbeddedServletContainerFactory();
    org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainer serverContainer = (org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainer)jettyContainer.getEmbeddedServletContainer();
    serverContainer.getServer().setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize", "20971520");
    return jettyContainer;
}

这些选项都不起作用,当某些请求很大时,我仍然会收到错误。

有没有更好的方法来解决这个问题?

注意:我只在运行 CentOS 的 Azure VM 环境中看到此错误。在我运行 Windows 10 的机器上,我没有看到这个错误

更新:我注意到当网络服务器重新启动时,第一个请求通过但后续请求失败。这表明服务器上有一些缓冲区或缓存没有及时清除。我的理解正确吗?

【问题讨论】:

  • 这些选项都不起作用,当某些请求很大时我仍然会收到错误。 - 您是否 100% 确定有效负载最多为 10MB 大?您将限制设置为 20MB,您是否 100% 确定您没有超过此限制?
  • 我使用 Chrome 浏览器调试器并将 json 有效负载复制到一个文本文件中。请求大小为 4 MB。
  • 您的 413 也可能来自滥用请求行或标题。确保您没有将该 JSON 对象作为 URI 上的查询字符串发送(例如),并且您的请求标头大小合理。如果 Jetty 回复 413,那么您的服务器日志应该会告诉您为什么会收到 413(或 431)。如果您没有看到这些日志,那么您可以确定它不是导致 413/431 结果的 Jetty 配置。
  • 标头大小在限制范围内。有没有办法检查请求有效负载的当前限制是多少?也许是 Spring Boot 中的一些 Java API?

标签: java http spring-boot centos jetty


【解决方案1】:

spring.http.multipart.max-file-size=200MB

spring.http.multipart.max-request-size=200MB

当您使用嵌入式 TOMCAT 运行时,这些设置将起作用。

【讨论】:

  • 但是这个问题被标记为jetty,并且OP说他正在使用码头。
  • 没错。此外,这些选项适用于内容类型为多部分的请求。我的内容类型是 json
【解决方案2】:

将这些添加到 application.properties 文件中,以防请求是多部分的,并根据您的需要调整它们:

multipart.maxFileSize=20Mb

multipart.maxRequestSize=20Mb

否则,看看这个:https://stackoverflow.com/a/3861510/945214 和这个:https://stackoverflow.com/a/36899004/945214

【讨论】:

  • 这个选项没有帮助。我仍然看到同样的错误
【解决方案3】:

在您的示例中,您在 bean 定义中实例化的 JettyEmbeddedServletContainer 从未使用过,您可以覆盖的 bean 是 JettyEmbeddedServletContainerFactory。看看EmbeddedServletContainerAutoConfiguration.EmbeddedJetty 魔法发生的地方。

要修改你想要的属性,你可以使用JettyServerCustomizer 接口:

@Bean
public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
    JettyEmbeddedServletContainerFactory factory = new JettyEmbeddedServletContainerFactory();
    factory.addServerCustomizers(server -> server.setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize", 20971520));
    return factor;
}

EmbeddedServletContainerCustomizer

@Component
public class FormSizeCustomizer implements EmbeddedServletContainerCustomizer {
    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        JettyEmbeddedServletContainerFactory factory = (JettyEmbeddedServletContainerFactory) container;
        factory.addServerCustomizers(server -> server.setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize",
                                                                   20971520));
    }
}

此限制仅适用于具有 application/x-www-form-urlencoded 内容类型的请求。要对 application/json 请求(或其他内容类型)强制设置最大大小,您需要自定义代码。您可以通过检查 Content-Length 标头或包装 ServletInputStream 并在消费分块请求时强制执行最大大小来做到这一点。

来源(Joakim 是 Jetty 开发人员):Jetty and max content size

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-10
    • 2021-04-18
    • 2021-05-31
    • 2018-05-27
    • 1970-01-01
    • 1970-01-01
    • 2021-03-01
    • 1970-01-01
    相关资源
    最近更新 更多