与 Spark Framework 一起使用时,如何配置 Jetty 以允许更大的表单

How do I configure Jetty to allow larger forms when used with Spark Framework

如何通过 Spark framework 配置 Jetty 选项?

我在提交大表单时遇到以下问题。 Jetty 的解决方案记录在 Form too Large Exception

但是 Jetty 对我使用 Spark Framework 是隐藏的,我该如何配置来解决这个问题。

    org.eclipse.jetty.http.BadMessageException: 400: Unable to parse form content
        at org.eclipse.jetty.server.Request.getParameters(Request.java:373)
        at org.eclipse.jetty.server.Request.getParameter(Request.java:1016)
        at javax.servlet.ServletRequestWrapper.getParameter(ServletRequestWrapper.java:194)
        at spark.Request.queryParams(Request.java:283)
        at spark.http.matching.RequestWrapper.queryParams(RequestWrapper.java:141)
        at com.jthink.songkong.server.callback.ServerEditSongs.startTask(ServerEditSongs.java:45)
        at com.jthink.songkong.server.CmdRemote.lambda$null(CmdRemote.java:171)
        at spark.RouteImpl.handle(RouteImpl.java:72)
        at spark.http.matching.Routes.execute(Routes.java:61)
        at spark.http.matching.MatcherFilter.doFilter(MatcherFilter.java:130)
        at spark.embeddedserver.jetty.JettyHandler.doHandle(JettyHandler.java:50)
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1568)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
        at org.eclipse.jetty.server.Server.handle(Server.java:564)
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:317)
        at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
        at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:110)
        at org.eclipse.jetty.io.ChannelEndPoint.run(ChannelEndPoint.java:124)
        at org.eclipse.jetty.util.thread.Invocable.invokePreferred(Invocable.java:128)
        at org.eclipse.jetty.util.thread.Invocable$InvocableExecutor.invoke(Invocable.java:222)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:294)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:199)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:673)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.run(QueuedThreadPool.java:59
1)
        at java.lang.Thread.run(Thread.java:745)
    Caused by: java.lang.IllegalStateException: Form too large: 273433 > 200000
        at org.eclipse.jetty.server.Request.extractFormParameters(Request.java:516)
        at org.eclipse.jetty.server.Request.extractContentParameters(Request.java:454)
        at org.eclipse.jetty.server.Request.getParameters(Request.java:369)
        ... 26 more

这是通过 org.eclipse.jetty.server.Server 属性控制的..

org.eclipse.jetty.server.Request.maxFormContentSize=<int> 以字节为单位的最大表单大小

org.eclipse.jetty.server.Request.maxFormKeys=<int> for max form keys(此处存在限制以对抗散列键冲突 DoS 技术)。

使用 Server.setAttribute(String name, Object value) 调用。

一段历史:

  • 我在 spark 的 git 回购协议上查了一下,发现这个问题是在 2015 年 8 月 3 日提出的,这里 issue 314

  • Perwendel(维护 Spark 的人)于 2016 年 10 月 11 日添加了 Much wanted 标签

  • 然后在 2016 年 11 月 3 日开始处理

  • 他合并了 Pull Request PR #813 以打开在 Spark embedded 中进行任何 Jetty 设置的可能性。

我查看了此 PR 中添加的修改,我认为您可以通过实现 JettyServerFactory 来配置一些东西,如果您覆盖 public Server create(...) 方法,您可以 return 你的自定义服务器:

public class Main {

  public static void main(String ...args) {
    CustomJettyServerFactory customJettyServerFactory = new CustomJettyServerFactory();
    EmbeddedServers.add(
        EmbeddedServers.Identifiers.JETTY, 
        new EmbeddedJettyFactory(customJettyServerFactory));
  }
}

class CustomJettyServerFactory implements JettyServerFactory {
  @Override
  public Server create(int maxThreads, int minThreads, int threadTimeoutMillis) {
    Server server = new Server();
    server.setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize", 1000000);
    return server;
  }

  @Override
  public Server create(ThreadPool threadPool) {
    return null;
  }
}

请试一试,看看是否可以完成这项工作,我没有任何设置可以尝试,但我认为这是配置 Jetty 服务器的正确路径。