clojurering

How do i server static html file with ring handler in clojure?


I am trying to server html over a ring based api server path . however everytime i hit the endpoint , i am getting this wierd error

java.lang.IllegalArgumentException: No implementation of method: :write-body-to-stream of protocol: #'ring.core.protocols/StreamableResponseBody found for class: clojure.lang.PersistentArrayMap
    at clojure.core$_cache_protocol_fn.invokeStatic(core_deftype.clj:583) ~[clojure-1.10.1.jar:?]
    at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:575) ~[clojure-1.10.1.jar:?]
    at ring.core.protocols$eval18503$fn__18504$G__18494__18513.invoke(protocols.clj:8) ~[?:?]
    at ring.util.servlet$update_servlet_response.invokeStatic(servlet.clj:106) ~[?:?]
    at ring.util.servlet$update_servlet_response.invoke(servlet.clj:91) ~[?:?]
    at ring.util.servlet$update_servlet_response.invokeStatic(servlet.clj:95) ~[?:?]
    at ring.util.servlet$update_servlet_response.invoke(servlet.clj:91) ~[?:?]
    at ring.adapter.jetty$proxy_handler$fn__18623.invoke(jetty.clj:27) ~[?:?]

Here is what my api is returning.

{:status 200
:body   (resource-response "index.html" {:root "public"})}

Whereas if i hit the index.html path directly it is accessible at this route

http://localhost:8080/index.html

Solution

  • You get the error No implementation of method: :write-body-to-stream of protocol: #'ring.core.protocols/StreamableResponseBody found for class: clojure.lang.PersistentArrayMap because as a body you return a PersistentArrayMap instead of something that can be encoded as the body of a Ring HTTP response.

    resource-response already returns a full response map (a PersistentArrayMap):

    (resource-response "index.html")
    ;; => {:status 200,
    ;;     :headers
    ;;     {"Content-Length" "0", "Last-Modified" "Mon, 16 Nov 2020 14:22:48 GMT"},
    ;;     :body
    ;;     #object[java.io.File 0x239d3777 "/index.html"]}
    
    

    so no need to wrap it in {:status 200, :body ...} since it becomes {:status 200 :body {:status 200, ...}} which lead to that error. To fix it your API can directly return:

    (resource-response "index.html" {:root "public"})