【问题标题】:Scala Jetty webapp on Heroku 404Heroku 404 上的 Scala Jetty webapp
【发布时间】:2019-08-15 01:58:57
【问题描述】:

我正在使用 Scala Web 框架 (Udash) 进行测试,并尝试在 Heroku 中运行一个玩具示例。按照 Heroku 文档中的说明,我让它在本地运行没有问题:

sbt compile stage
heroku local web

但是,一旦部署,我输入的任何 URL 都会转到 404,甚至是应用程序的着陆页。这些是我正在使用的对象:

object Launcher extends CrossLogging {
  def main(args: Array[String]): Unit = {
    val port = Properties.envOrElse("PORT", "5000").toInt
    val server = new ApplicationServer(port, "frontend/target/UdashStatics/WebContent")
    server.start()
    logger.info(s"Application started...")
  }
}

class ApplicationServer(val port: Int, resourceBase: String) {
  private val server = new Server(port)
  private val contextHandler = new ServletContextHandler
  private val appHolder = createAppHolder()

  contextHandler.setSessionHandler(new SessionHandler)
  contextHandler.setGzipHandler(new GzipHandler)
  contextHandler.getSessionHandler.addEventListener(new org.atmosphere.cpr.SessionSupport())
  contextHandler.addServlet(appHolder, "/*")
  server.setHandler(contextHandler)

  def start(): Unit = server.start()
  def stop(): Unit = server.stop()

  private def createAppHolder() = {
    val appHolder = new ServletHolder(new DefaultServlet)
    appHolder.setAsyncSupported(true)
    appHolder.setInitParameter("resourceBase", resourceBase)
    appHolder
  }
}

我是否缺少任何 Heroku 配置/特征?

编辑

尝试应用建议的更改并最终得到以下 ApplicationContext:

class ApplicationServer(val port: Int, val resourceBase: String) {
  val server = new Server()
  val connector = new ServerConnector(server)
  connector.setPort(port)
  server.addConnector(connector)
  private val appHolder = createAppHolder()

  val context = new ServletContextHandler(ServletContextHandler.SESSIONS)

  context.setBaseResource(Resource.newResource(resourceBase))
  context.setContextPath("/")
  context.addServlet(appHolder, "/")
  server.setHandler(context)

  private def createAppHolder() = {
    val appHolder = new ServletHolder("default", classOf[DefaultServlet])
    appHolder.setInitParameter("dirAllowed", "true")
    appHolder.setInitParameter("resourceBase", resourceBase)
    appHolder
  }

  def start(): Unit = server.start()
  def stop(): Unit = server.stop()
}

但是,即使在部署到 Heroku 后,我仍然在登录页面上收到错误 404:

HTTP ERROR 404
Problem accessing /. Reason:
    Not Found

在本地运行应用程序时,我可以正确到达着陆页。

谢谢! 谢谢!

【问题讨论】:

  • 你的代码是可以的,只要我在resourceBase指向的目录下放一些东西通过浏览器获取即可。 (例如:我放了一个hello.html 和一个简单的<h1>hello world</h1>,然后通过http://localhost:8080/hello.html 访问它)

标签: scala heroku jetty udash


【解决方案1】:

调整一些可能对您有帮助的事情。

  1. resourceBase 作为DefaultServlet 上的初始参数用于alternate static file serving
  2. 请改用ServletContextHandler.setBaseResource(Resource)
  3. 使用Resource.newResource(String) 创建新的资源引用。这应该是文件系统上的绝对路径,或绝对 URI 引用。没有相对路径或 URI 片段。
  4. DefaultServlet 必须位于 "/"url-pattern 上,而不是 "/*"(这是 servlet 规范要求)
  5. DefaultServlet 必须命名,并且必须具有名称 "default"(这是 servlet 规范要求,例如参见第 1 点上的链接)
  6. ServletContextHandler.setContextPath("/") 设置为明确说明您要使用的基本上下文路径。

一些观察:

您的示例代码将仅提供resourceBase 之外的静态内容。

由于您没有配置welcomeFiles,因此默认情况下它将提供<resourceBase>/index.html(如果您没有指定要访问的特定静态资源)

您有一个 SessionListener 设置 (org.atmosphere.cpr.SessionSupport),但由于没有任何东西可以访问 Session,因此该代码几乎是无操作的。

您的示例代码库中没有来自自定义 Servlet 或过滤器的动态结果。

【讨论】:

  • 谢谢你的回答,我回家试试看,我会告诉你的
  • 你好@Joakim!尝试了您建议的更改但没有成功。我使用了您作为模板链接的另一个答案。我很抱歉,因为我对所有服务器的东西有点迷失(:但是,我认为我正确地应用了你的建议(我使用的新 applicationServer 在这里gist.github.com/pmbrull/64de6497d52463542cc2ca902a03ffb4)我非常感谢在我继续寻找的同时提供进一步的指导示例和文档。Tyvm!!
  • 您能否更新您的问题(编辑它)并包括您如何运行代码、您看到的结果与您期望的结果?
猜你喜欢
  • 2012-09-09
  • 2012-07-17
  • 2014-09-28
  • 2012-02-22
  • 1970-01-01
  • 1970-01-01
  • 2017-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多