perwendel / spark

A simple expressive web framework for java. Spark has a kotlin DSL https://github.com/perwendel/spark-kotlin
Apache License 2.0
9.64k stars 1.56k forks source link

change maxFormContentSize through sparkjava #1070

Open jiadongzh opened 5 years ago

jiadongzh commented 5 years ago

I'm using SparkJava 2.6.0. I'm getting "Form too large" exception which is thrown by Jetty. I don't know how to change the maxFormContentSize through sparkjava. In sparkjava 2.6.0 doc, it mentions that jetty is fully configable, but does not provide any config example.

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$62(CmdRemote.java:171) at spark.RouteImpl$1.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$2.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$2.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

Is there any way to alter maxFormContentSize? Thank you very much!

leeharland commented 5 years ago

I also need to set this and have used code (i think I must have got this from the sparkjava website sorry for no credit) to do this BUT when i updated to latest version i noticed that jetty has changed and this method is no longer viable. Rather than have to do complex jumps to get at the underlying jetty like the person at [1] has done, if we could just do Spark.setMaxUploadSize(x) that would save a lot of messing about and negate the need in my code to know anything about jetty

Thanks!

  EmbeddedServers.add(EmbeddedServers.Identifiers.JETTY,
          new EmbeddedJettyFactory((i, js, k) -> {
            server = new Server();

            /**
             * Set upload maxes
             */
            server.setAttribute(
                "org.eclipse.jetty.server.Request.maxFormContentSize",
                9999999999 // or whatever
            );
            return server;
          }));

[1] https://github.com/freeacs/freeacs/blob/master/tr069/src/main/java/com/github/freeacs/App.java

jiadongzh commented 5 years ago

I just upgraded to sparkjava 2.8.0 to use the code:

public static void main(String[] args) { // sparkjava configuration Spark.threadPool(SparkJavaConfig.MAX_THREADS, SparkJavaConfig.MIN_THREADS, SparkJavaConfig.TIME_OUT_MILLIS); Config config = ConfigFactory.load(); int maxHttpPostSize = getInt(config, "server.jetty.max-http-post-size"); int maxFormKeys = getInt(config, "server.jetty.max-form-keys"); EmbeddedServers.add( EmbeddedServers.Identifiers.JETTY, new JettyFactory(true, maxHttpPostSize , maxFormKeys));

    // paths groups
    try {
        Spark.path(Constant.SLASH+RequestAttr.NLP, () -> {

            // hello world!
            Spark.path("/hello", () -> {
                Spark.post("/:name", (request, response) -> {
                    return "Hello: " + request.params(":name");
                });
            });

            // segment
            Spark.path(Constant.SLASH+RequestAttr.SEGMENT, () -> {
                seg.seg();
            });

            // ner
            Spark.path(Constant.SLASH+RequestAttr.NER, () -> {
                ner.segAndNer();
            });
        });
    } catch (Exception e) {
        LogPrinter.print(logger, e);
    }
}

It does not work. When content size > 200,000:

500 Internal Error

sparkjava is so not popular. No one knows how do do.

toyg commented 5 years ago

Have a look at a complete example here: https://github.com/toyg/spark-custom-jetty .

In your case, it looks like you need to set the parameters on the Jetty Handler with handler.setMaxFormContentSize(int maxSize); in https://github.com/toyg/spark-custom-jetty/blob/master/src/main/java/com/autoepm/sparktips/customjetty/MyCustomEmbeddedServerFactory.java

The problem is not due to Spark as much as to how Jetty is structured internally, with server, handlers, and sockets. The actual APi is https://www.eclipse.org/jetty/javadoc/9.4.14.v20181114/org/eclipse/jetty/server/handler/ContextHandler.html#setMaxFormContentSize-int-

zhangskills commented 3 years ago

version: 2.9.3

use custom jettyServer

EmbeddedServers.add(EmbeddedServers.Identifiers.JETTY, new EmbeddedJettyFactory(new JettyServerFactory() {

    @Override
    public Server create(int maxThreads, int minThreads, int threadTimeoutMillis) {
        Server server;

        if (maxThreads > 0) {
            int max = maxThreads;
            int min = (minThreads > 0) ? minThreads : 8;
            int idleTimeout = (threadTimeoutMillis > 0) ? threadTimeoutMillis : 60000;

            server = new Server(new QueuedThreadPool(max, min, idleTimeout));
        } else {
            server = new Server();
        }
        // or whatever
        server.setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize", -1);

        return server;
    }

    @Override
    public Server create(ThreadPool threadPool) {
        return threadPool != null ? new Server(threadPool) : new Server();
    }
}));