关于重定向的奇怪码头警告 "java.lang.IllegalStateException: Committed",如何解决?

Strange jetty warning "java.lang.IllegalStateException: Committed" on redirecting, how to fix it?

我有一个自定义 Jetty 重定向处理程序:


  object RedirectHandler extends HandlerWrapper {

    override def handle(
        target: String,
        baseRequest: Request,
        request: HttpServletRequest,
        response: HttpServletResponse
    ): Unit = {

      require(!response.isCommitted)

      val redirectURIOpt = rewrite(request.getRequestURI)
      redirectURIOpt.foreach { v =>
        response.sendRedirect(v)
        require(response.isCommitted)
      }
    }

    def rewrite(target: String): Option[String] = {
      if (target.endsWith(".html")) None
      else {
        var _target = target.stripSuffix("/")
        if (_target.nonEmpty) {
          _target += ".html"
          Some(_target)
        } else {
          None
        }
      }
    }
  }

它配置为与普通 ResourceHandler 一起设置 Web 服务器:

...

    val server = new Server(10092)

    val resourceHandler = new ResourceHandler

    resourceHandler.setDirectoriesListed(true)
//    resource_handler.setWelcomeFiles(Array[String]("test-sites.html"))
    resourceHandler.setResourceBase(CommonConst.USER_DIR \ "test-sites")

    val handlers = new HandlerList
    handlers.setHandlers(Array(RedirectHandler, resourceHandler))
    server.setHandler(handlers)

每次触发重定向时,我都发现了一条奇怪的警告信息:

WARN HttpChannel: /test-sites/e-commerce/static
java.lang.IllegalStateException: Committed
    at org.sparkproject.jetty.server.HttpChannel.resetBuffer(HttpChannel.java:994)
    at org.sparkproject.jetty.server.HttpOutput.resetBuffer(HttpOutput.java:1459)
    at org.sparkproject.jetty.server.Response.resetBuffer(Response.java:1217)
    at org.sparkproject.jetty.server.Response.sendRedirect(Response.java:569)
    at org.sparkproject.jetty.server.Response.sendRedirect(Response.java:503)
    at org.sparkproject.jetty.server.Response.sendRedirect(Response.java:578)
    at org.sparkproject.jetty.server.ResourceService.sendWelcome(ResourceService.java:398)
    at org.sparkproject.jetty.server.ResourceService.doGet(ResourceService.java:257)
    at org.sparkproject.jetty.server.handler.ResourceHandler.handle(ResourceHandler.java:262)
    at org.sparkproject.jetty.server.handler.HandlerList.handle(HandlerList.java:59)
    at org.sparkproject.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.sparkproject.jetty.server.Server.handle(Server.java:516)
    at org.sparkproject.jetty.server.HttpChannel.lambda$handle(HttpChannel.java:388)
    at org.sparkproject.jetty.server.HttpChannel.dispatch(HttpChannel.java:633)
    at org.sparkproject.jetty.server.HttpChannel.handle(HttpChannel.java:380)
    at org.sparkproject.jetty.server.HttpConnection.onFillable(HttpConnection.java:277)
    at org.sparkproject.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
    at org.sparkproject.jetty.io.FillInterest.fillable(FillInterest.java:105)
    at org.sparkproject.jetty.io.ChannelEndPoint.run(ChannelEndPoint.java:104)
    at org.sparkproject.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883)
    at org.sparkproject.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034)
    at java.lang.Thread.run(Thread.java:748)

据此post:

jetty webSocket : java.lang.IllegalStateException: Committed

如果响应在 sendRedirect 之后被进一步篡改,就会触发该问题。但是,鉴于 resourceHandler 是一个非常成熟的组件,不太可能犯这种低级错误。

那么可能的原因是什么,更重要的是,如何通过将重定向响应声明为最终响应来修复它?

您错过了 baseRequest.setHandled(true) 告诉 Jetty 停止处理进一步的处理程序。当您的处理程序产生响应(或处理请求)时使用它。

后来的处理程序(ResourceHandler 根据您的堆栈跟踪)尝试写入响应并被击倒,因为响应已经提交。