使用 Clojure 的 Ring 提供静态资源

Ari*_*iel 1 clojure compojure ring

我正在学习如何使用 Clojure 的 Ring 创建网络应用程序。我正在尝试提供一个静态.html<link>文件,该文件通过其头部的标签包含对 .css 文件的引用。.css 文件与我尝试提供的 index.html 文件位于同一目录中,但是,未加载 .css 文件(我收到错误,状态代码为 500,原因短语为:

响应图为零

这是我的代码如下:

(defroutes approutes
  (GET "/" reqmap
    (resource-response "index.html")))


(def server (run-jetty #'approutes {:join? false, :port 3000}))
Run Code Online (Sandbox Code Playgroud)

我在这里缺少什么?如何提供引用其他文件(.css、.js、.jpeg 等)的 html 文件?我有一些运气(虽然我不能完全解释为什么)wrap-resource在命名空间中使用 Ring 的中间件ring.middleware.resource,尽管该函数仅在请求映射匹配静态资源时使用(正如你所看到的,路由“/”与资源本身不匹配)。

谢谢。

Den*_*ida 5

您需要添加一点中间件,该中间件将负责从您可以选择的文件夹中提供静态文件,如下所示:

\n\n
;; Add to your (ns :requires at the top of the file)\n(:require [ring.middleware.resource :refer wrap-resource])\n\n;; more of your existing code here...\n\n(def app\n  (wrap-resource approutes "public")) ;; serve static files from "resources/public" in your project\n\n(def server (run-jetty #\'app {:join? false, :port 3000}))\n
Run Code Online (Sandbox Code Playgroud)\n\n

这应该足以让您继续前进,因此如果您启动服务器,您应该能够打开http://localhost:3000/style.css等地址中的文件,这些文件应该在public/resources/style.css您的项目中找到。任何其他静态文件都应该可以工作。Github 的 Ring wiki 中有一个指南,解释了您可以使用的两个类似的功能(中间件)。

\n\n

接下来,在您的index.html文件中,您应该能够引用其他文件,例如 CSS 文件,如下所示:

\n\n
<html>\n  <head>\n    <link rel="stylesheet" href="css/style.css">\n  </head>\n  <!-- and son on... -->\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我不久前写的一个示例项目,它确实显示了相同的想法: https: //github.com/dfuenzalida/antizer-demo

\n\n
\n\n

更新

\n\n

我已经从头开始快速运行,这应该可以帮助您找到问题所在。

\n\n

创建了一个新项目:

\n\n
lein new app hello-ring\n
Run Code Online (Sandbox Code Playgroud)\n\n

实际上,这个名称有点误导,因为我们将同时使用 Ring 和 Compojure。

\n\n

我们将project.clj使用以下内容更新该文件:

\n\n
lein new app hello-ring\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在让我们编辑该文件src/hello_ring/core.clj,其内容应如下所示:

\n\n
(defproject hello-ring "0.1.0-SNAPSHOT"\n  :description "FIXME: write description"\n  :url "http://example.com/FIXME"\n  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"\n            :url "https://www.eclipse.org/legal/epl-2.0/"}\n  :dependencies [[org.clojure/clojure "1.10.0"]\n                 [compojure "1.6.1"]\n                 [ring/ring-core "1.6.3"]\n                 [ring/ring-jetty-adapter "1.6.3"]]\n  :main ^:skip-aot hello-ring.core\n  :target-path "target/%s"\n  :profiles {:uberjar {:aot :all}})\n
Run Code Online (Sandbox Code Playgroud)\n\n

最后让我们创建一些静态资源。创建文件夹结构resources/public/css并在文件中resources/public/css/style.css输入以下内容:

\n\n
(ns hello-ring.core\n  (:require [ring.adapter.jetty :refer [run-jetty]]\n            [ring.middleware.resource :refer [wrap-resource]]\n            [ring.util.response :refer [resource-response]]\n            [compojure.core :refer [defroutes GET]])\n  (:gen-class))\n\n(defroutes approutes\n  (GET "/" []\n       (resource-response "public/index.html")))\n\n(def app\n  (-> approutes\n      (wrap-resource "public"))) ;; files from resources/public are served\n\n(defn server []\n  (run-jetty app {:join? false, :port 3000}))\n\n(defn -main [& args]\n  (server))\n
Run Code Online (Sandbox Code Playgroud)\n\n

...以及一个基本的 HTML 文件,其中resources/public/index.html包含以下内容:

\n\n
body {\n    font-face: sans-serif;\n    padding-left: 20px;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

... 就是这样。HTML 文件将尝试加载 CSS 文件。保存所有内容并检查它是否与以下文件夹结构匹配:

\n\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 CHANGELOG.md\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 doc\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 intro.md\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 LICENSE\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 project.clj\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 README.md\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 resources\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 public\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 css\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 style.css\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 index.html\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 src\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 hello_ring\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 core.clj\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 test\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 hello_ring\n        \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 core_test.clj\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在您应该可以使用以下命令从命令行启动该服务:

\n\n
lein run\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出将如下所示:

\n\n
$ lein run\n2019-08-05 23:46:14.919:INFO::main: Logging initialized @1221ms\n2019-08-05 23:46:16.281:INFO:oejs.Server:main: jetty-9.2.21.v20170120\n2019-08-05 23:46:16.303:INFO:oejs.ServerConnector:main: Started ServerConnector@2c846d55{HTTP/1.1}{0.0.0.0:3000}\n2019-08-05 23:46:16.303:INFO:oejs.Server:main: Started @2606ms\n
Run Code Online (Sandbox Code Playgroud)\n\n

连接到http://0.0.0.0:3000/中的服务器...您应该在浏览器中看到您的页面,并显示It Works! 消息和基本的 CSS 重置。在控制台中,您最有可能看到一些异常,因为浏览器尝试/favicon.ico从您的服务器加载文件,但该文件不存在(您现在可以将其创建为空文件)。

\n\n

我希望这有帮助。

\n