Fork me on GitHub
#pedestal
<
2021-10-01
>
simongray11:10:04

How to do I make a catch-all/not-found route? I.e. one that doesn’t cancel out the other routes. When I was using Compojure it was as simple as "*" while making sure that the route was the last to be defined. Then the SPA gets served in the same HTML/JS blob and the frontend routing in the single-page app would basically take over.

simongray11:10:58

With Pedestal it seems like you need separation into separate paths, e.g. /app and /api for this work…? And if you want both /app and /app/* to work you will need to make two separate routes. Is that the case?

simongray11:10:54

I basically need all of this to get it to work and it’s still less elegant than Compojure since it forces me to use “/app” as a the root rather than “/”:

["/" :get redirect :route-name ::root]
["/app" :get single-page-app :route-name ::app]
["/app/*" :get single-page-app :route-name ::app-path]

emccue13:10:07

There isn't a way with pedestal's routing - but what you can do is use interceptors for this

emccue13:10:33

;; ----------------------------------------------------------------------------
(def serve-spa-on-404
  "Intercepts any unhandled get requests and serves the SPA."
  {:leave
   (fn [context]
     (if (and (not (http/response? (:response context)))
              (= :get (:request-method (:request context))))
       (assoc
         context
         :response
         {:status 200
          :headers {"Content-Type" "text/html"}
          :body
          (page/html5
            {:lang "en"}
            [:html
             [:head
              [:meta {:charset "UTF-8"}]
              [:style "body { padding: 0; margin: 0; }"]]
             [:body
              [:div {:id "mount"}]
              [:script {:type "text/javascript"} (-> (io/resource "public/app.js") ;; TODO: Cache
                                                     (slurp))]
              [:script {:type "text/javascript"}
               "var app = Elm.Main.init({node: document.getElementById('mount')});"]]])})
       context))})

emccue13:10:06

if you went through the interceptor chain and didn't produce a response

emccue13:10:12

and its a get request\

emccue13:10:23

then you serve your JS

simongray14:10:26

Ah, interesting approach @emccue. Thanks for including the code 🙂