Search code examples
herokuclojuresubdomainring

Handle subdomains for a Clojure classified web app hosted on Heroku


I have a classified clojure web app I want to host on Heroku. The domain is registered at Godaddy.

What would be the most effective and efficient way to have multiple subdomains:

  • newyork.classapp.com
  • montreal.classapp.com
  • paris.classapp.com
  • ...

Users, all logic, should be shared across subdomains, so I'd love to have only one code base.

It would be easy to redirect subdomains to first level folder like this: paris.classapp.com -> classapp.com/paris/

But I want users to keep seeing the subdomain while browsing the site, like this: paris.classapp.com/cars/blue-car-to-sell

As opposed to this:classapp.com/paris/cars/blue-car-to-sell

What should I do?


Solution

  • Heroku support wildcard subdomains: https://devcenter.heroku.com/articles/custom-domains#wildcard-domains.

    You will have in the host header the original domain, which you can use with something like (completely untested):

    (GET "/" {{host "host"} :headers} (str "Welcomed to " host))
    

    You could also create your own routing MW (completely untested):

    (defn domain-routing [domain-routes-map]
       (fn [req]
           (when-let [route (get domain-routes-map (get-in req [:headers "host"]))]
               (route req))))
    

    And use it with something like:

     (defroutes paris  
        (GET "/" [] "I am in Paris"))
     (defroutes new-new-york
        (GET "/" [] "I am in New New York"))
    
     (def my-domain-specific-routes 
        (domain-routing {"paris.example.com" paris "newnewyork.example.com" new-new-york}))
    

    And yet another option is to create a "mod-rewrite" MW that modifies the uri before getting to the Compojure routes:

     (defn subdomain-mw [handler]
        (fn [req]
            (let [new-path (str (subdomain-from-host (get-in req [:headers "host"])
                                "/"
                                (:uri req))]
                 (handler (assoc req :uri new-path))))  
    
      (defroutes my-routes  
          (GET "/:subdomain/" [subdomain] (str "Welcomed to " subdomain))
    

    Pick the one that suits your requirements.