-
-
Notifications
You must be signed in to change notification settings - Fork 91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compile-time routes #38
Comments
Hi Stiff Thanks for your gist. It is similar to what I have implemented in another webframework : http://siliconframework.org/docs/apis.html but I dropped it for simplicity. It has one advantage that the current version:
The current url parameter reading are also typed checked but the types are provided when reading parameters:
However, if you do a typo in {{id}} or in s::id, the handler is invalid but still compiles. Your example has one disadvantage over the current version: it is not using named parameters, so if your handler takes 4 integers as parameters it won't be trivial to remember which one is what in the handler. Another disadvantage is the readability of the code. This makes defining a route a lot more complex than just writing a plain strings, while not really providing a big advantage: in the current version, if a very simple test would fail and report any mismatch between s::id and {{id}}. This would also require a lots of change in the core of the framework (including lots of templates, slowing down compilation): right now, all handlers have the same type. It we want to forward the static types of the route to the handler, we would have to switch to templated handlers, which would contaminate lots of the code. Silicon http://siliconframework.org was actually using this approach but was 5x slower to compile and it's codebase was more complex. So I when I rewrote it, I decided to strip down all the complex meta programming stuff to get something that compiles faster and with a code base accessible to more c++ devs. |
Sure each approach has it's own trade offs different from others, that's why I asked about the possibility of Lithium going in this direction. Silicon is different from my proposed approach in that Silicon invents it's own syntax, and first glance of a person who only knows C++ will definitely raise questions like what's POST, what's _about, To simplify writing routes it should be possible to get rid of Slug and use FixedString right away like Naming arguments is a bit more tricky, I totally agree that it's very helpful to have named arguments, but it's not clear if it should go into types. After all programmers are allowed to name instances of type as they like. Regarding compilation time, since it's done once, I prefer to let the computer do more work for me and check as much as possible. And to handle all this my initial though was to use std::visit of std::variant. Also having all routes in types opens possibilities to generate clients for same API, without writing it again by hand with typos and without compiler check. |
For named parameters, we can use symbols: I'm thinking about a way to integrate this to the framework as an additional way to declare routes. using singlePostRoute = Route<"blog", "posts", Capture<s::id, int>>;
api.get<singlePostRoute>([&](li::http_request& request, li::http_response& response) {
auto url_params = request.url_parameters<singlePostRoute>();
// do something with url_params.id
}); |
I think I would try this in my project :) I really like how parameters passed to handler function in Servant (like in toString example), for easier testing without any dependencies to http requests and responses. But separating responsibilities of performing the business logic and rendering response is probably quite a lot of changes. |
With recent additions in C++20 it is possible to write type-level compile-time routes that will accept only parameters of valid type, like this:
Here is the proof of concept: https://gist.github.com/stiff/27607ddeb4da590d915423ba6779f18e . Sorry for some obvious room for optimisation :)
Think it's also possible to parse incoming requests in similar manner, is there a chance that'll get into Lithium, so we could define all routes in one place and get compile-time validation that they all genereated and handled just as specified?
The text was updated successfully, but these errors were encountered: