Search code examples
clojureclojurescriptcompojurereagentsecretary

In ClojureScript, why can't I navigate to a URL entered by hand, but if I click a link it works?


(Note, I'm using Reagent, Secretary, and Compojure (among others))

I want to create a route /sectest/:id, and if I point my browser to that route, I get the following error:

Resource interpreted as Stylesheet but transferred with MIME type text/html: "http://localhost:3449/sectest/css/site.css". asdf:1 Refused to execute script from 'http://localhost:3449/sectest/js/app.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.

But if I click on a link in the browser that navigates to that route, it works fine...

Here's the pertinent code:

Client Side:

(secretary/defroute "/sectest/:id" [id]
  (do
    (js/console.log (str "Hi " id))
    (session/put! :current-page #'my-page)))

Server Side:

(defroutes routes
  (GET "*" [] loading-page) ;this anticipates client-side routing only
  (GET "/cards" [] cards-page)
  (resources "/")
  (not-found "Not Found"))

(def app (wrap-middleware #'routes))

So the following link takes me to my-page, and the console prints "Hi asdf" just fine:

[:div [:a {:href "/sectest/asdf"} "SECTEST"]]

But if I type in http://localhost:3449/sectest/asdf, I get an error, and I can't seem to trace it. I suspect it might have something to do with the code trying to find resources located at /sectest, (which it shouldn't), but I can't confirm this or figure out how to work with it... I am new to clojure, so forgive if I'm massively ignorant on some point, any thoughts?


Solution

  • Take a look at your server side routing, effectively you only have one route:

    (GET "*" [] loading-page)    
    

    As it handles everything all following routes will never trigger. Order matters:

    (defroutes routes
      (GET "/cards" [] cards-page)
      (resources "/")
      (GET "*" [] loading-page) ;this anticipates client-side routing only
    )
    

    The above should do the trick, I removed the 404 route, as this should be handled by the frontend routing.

    The reason it currently works when clicking on a page link in your SPA is that it will get handled by secretary. If you enter the url manually you are doing a page reload and the request is handled by compojure initially.

    Edit:

    After taking a closer look, relative links to your css/js files in your html template are most likely the culprit here:

    /sectest/js/app.js
    

    The compojure resources route won't match and the default catch all route loading-page is served as css/js file to your browser. Hence the error.

    For my dev env I also had to correct the :asset-path of my boot cljs task as the source mapping files suffered from the problem. Should be similiar with lein-figwheel.