使用嵌入式 Jetty 通过内容协商提供静态文件

Serving static files with content negotiation using embedded Jetty

我有一个应用程序使用嵌入式 Jetty 来服务于网站的前端和 API。

它是用 Scala 编写的,但这并不是真正相关的。我设置所有内容的文件如下所示:

val servlet = new ServletHolder(Servlet)

val frontend = new ServletHolder(new DefaultServlet())
frontend.setInitParameter("resourceBase", "frontend")

val handler = new ServletContextHandler()
handler.addServlet(servlet, "/api/*")
handler.addServlet(frontend, "/*")

val server = new Server(8080)
server.setHandler(handler)
server.start()

但是,从 / 提供的静态内容要求我为我的静态内容使用文件扩展名 - 我想使用 content negotiation,这样就不需要这些了。这可能吗?

如果您想使用内容协商,则您没有提供静态文件。

内容协商是 HTTP 的一个基本概念,它实际上是针对您正在请求的(挥手)"resource" 提供的内容。

提供静态文件是 "resource" 的一种特殊形式,其中 mime 类型/内容类型根据其文件扩展名已知。

DefaultServlet(在您的示例中执行静态文件服务)在此专业化之上还有 1 个功能,但不是针对内容类型,而是针对内容编码(您可以预压缩您的静态文件通过创建位于原始文件旁边的 <filename>.gz 文件来获取资源,如果请求客户端表示他们可以接受 gzip,则将提供此 <filename>.gz 而不是未压缩的 <filename> 版本。

为了实现这个目标,您需要编写一些以对您有意义的方式为静态文件提供服务的内容。

如果你想自己做,你需要什么。

  • url 模式 /*
  • 上的新 servlet
  • 新的 servlet .init() 创建了一个内存数据结构,其中包含您拥有的所有已知静态文件,以及它们的扩展名和 mime 类型。
  • 新 servlet 的 .doGet() 将根据此内存中查找查看是否有可接受的资源来处理任何传入请求。从此内存中查找提供您想要的实际内容。
  • 不要忘记支持 ETag、远程请求、服务器响应缓存、HTTP 缓存和 Gzip。