【问题标题】:Serve static resources using Clojure's Ring使用 Clojure 的 Ring 提供静态资源
【发布时间】:2019-12-13 12:32:00
【问题描述】:

我正在学习如何使用 Clojure 的 Ring 创建 Web 应用程序。我正在尝试提供一个静态 .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}))

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

谢谢。

【问题讨论】:

    标签: clojure compojure ring


    【解决方案1】:

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

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

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

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

    <html>
      <head>
        <link rel="stylesheet" href="css/style.css">
      </head>
      <!-- and son on... -->
    

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


    更新

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

    创建了一个新项目:

    lein new app hello-ring
    

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

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

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

    现在让我们编辑文件src/hello_ring/core.clj,它的内容应该是这样的:

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

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

    body {
        font-face: sans-serif;
        padding-left: 20px;
    }
    

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

    <html>
      <head>
        <title>It works!</title>
        <link rel="stylesheet" href="css/style.css" />
      </head>
      <body>
        <h1>it works!</h1>
      </body>
    </html>
    

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

    .
    ├── CHANGELOG.md
    ├── doc
    │   └── intro.md
    ├── LICENSE
    ├── project.clj
    ├── README.md
    ├── resources
    │   └── public
    │       ├── css
    │       │   └── style.css
    │       └── index.html
    ├── src
    │   └── hello_ring
    │       └── core.clj
    └── test
        └── hello_ring
            └── core_test.clj
    

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

    lein run
    

    输出将如下所示:

    $ lein run
    2019-08-05 23:46:14.919:INFO::main: Logging initialized @1221ms
    2019-08-05 23:46:16.281:INFO:oejs.Server:main: jetty-9.2.21.v20170120
    2019-08-05 23:46:16.303:INFO:oejs.ServerConnector:main: Started ServerConnector@2c846d55{HTTP/1.1}{0.0.0.0:3000}
    2019-08-05 23:46:16.303:INFO:oejs.Server:main: Started @2606ms
    

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

    我希望这会有所帮助。

    【讨论】:

    • 感谢您的回答。我试过这个:(defroutes approutes (GET "/" reqmap {:status 200 :body (slurp "resources/public/index.html")})) (def app (wrap-resource approutes "public")) (def server (run-jetty #'app {:join? false, :port 3000})) 并且能够在我的本地主机上看到index.html 加载......但是,它仍然没有拉动在其&lt;head&gt; 中声明的 .css 文件......这是预期行为的一部分吗?
    • 它应该适用于所有类型的静态资源。我猜问题出在某个地方的配置中。请检查我对答案的更新并检查您项目中的路径是否正确(可能您的 CSS 文件在另一个文件夹中或某处有错字)
    • 它适用于您编辑的代码。谢谢!。我会弄清楚我的代码中没有正确提取 css 的内容(它正在提取 html 文件,但不是 css)。再次,非常感谢!。
    猜你喜欢
    • 2015-02-05
    • 1970-01-01
    • 2022-10-20
    • 1970-01-01
    • 1970-01-01
    • 2016-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多