Kemal: is it possible to do the rails equivalent of constraints subdomain?

First off, I normally only think of posting here for things specific to strictly only Crystal itself and not projects that make use of Crystal (ala Kemal) - but also I have seen others ask Kemal specific questions here. My justification beyond that is perhaps the answer is more Crystal generic and not strictly relevant to Kemal.
Apologies if this is rude to ask here.

In Rails, I can do:

get "/whatever" do
   # my boring code
end

That allows me to run my boring code when someone goes to http://www.mysite.blah/whatever - very normal route.
Kemal does exactly the same - awesome, very easy, thank you.

In Rails, I can then say I want api.mysite.blah/whatever to return a JSON payload and www.mysite.blah/whatever to return the HTML payload via constraints and subdomain…

It is not obvious to me if it is possible to do that in Kemal or if there is any reason in Crystal that would prevent the equivalent functionality?

My web app can function just fine only doing it the basic way and if I really need a separate api-only domain just use a different process - but it would be convenient to handle it all via the routes. It is just not obvious to me how to do that in Kemal and I don’t see any examples close enough that make it clear to me.

And I specifically am interested in using Kemal and I don’t want a “heavier” framework like Rails - but I do like that one thing from Rails and would love to use it in Kemal/Crystal.

Any ideas or pointers?

Kemal leverages GitHub - luislavena/radix: Radix Tree implementation for Crystal for routing, which doesn’t have this capability out of the box. So by extension, to the best of my knowledge, this isn’t something Kemal supports either.

There is nothing in Crystal itself that is preventing this, it’s more so up to the library authors if they want to implement a solution for this use case.

If you’re not tightly coupled to the features Kemal offers, you could consider RoutingHandler - Routing from Athena’s routing component. Feature wise it basically only adds routing to HTTP::Server so less features than Kemal, but if all your need is a router then that could be a good option as it supports Subdomain Routing.

2 Likes

Well I guess I feel better that I wasn’t just being dense and missing it from the docs.

It appears that I could do the concept of “output different stuff conditionally on the domain” in a somewhat clumsier way in a given route with something like:

 get "/" do |env|
    if env.request.headers["Host"].includes?("//api.")
      "JSON"
    else
      "HTML"
    end
  end

In the end, it is a nice/fun to have thing and not critical to the overall thing I am trying to do.

Thank you for the quick and helpful response!

2 Likes