5

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?

Chenmunka
  • 685
  • 4
  • 21
  • 25
leontalbot
  • 2,513
  • 1
  • 23
  • 32

1 Answers1

3

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.

DanLebrero
  • 8,545
  • 1
  • 29
  • 30
  • Thanks! Can't get the routing be specific to one subdomain though. This doesn't work `(GET "http://paris.classapp.com/" [] "Welcome to Paris site")` `(GET "http://newyork.classapp.com/" [] "Welcome to New York site")` Is it possible to change the content of the app according to a specific subdomain ? – leontalbot Aug 04 '14 at 15:16
  • 1
    Updated response with some details. – DanLebrero Aug 04 '14 at 17:51
  • The first solution you provide works with this small change: `(GET "/" {{host "host"} :headers} (str "Welcome to " host))` The second solution you provide would be the best, but it seems broken. I've tried `(when-let [route (get-in domain-routes-map [:headers "host"])]` but it doesn't seem to work! – leontalbot Aug 05 '14 at 11:51
  • 1
    Good catch. The get-in should be done in the request. I have updated the response. – DanLebrero Aug 05 '14 at 12:01
  • Brilliant answer, thanks so much! One last thing: defroutes doesn't accept arguments declaration, so you should remove the vector. – leontalbot Aug 05 '14 at 12:44