четверг, 13 августа 2020 г.

[prog.c++] My view of the near (and not so) future of the RESTinio project

Now, after the official release of RESTinio-0.6.9, it's a good time to share some thoughts about the near (and not only near) future of the RESTinio project.

It is worth noting that the text below is only my point of view. This point of view can change over time.

This text is split into two parts. The first part tells about rather practical things that I want to see in the upcoming releases of RESTinio. The second part is more philosophical and intended for the discussion about the role of RESTinio in the modern C++ landscape.

Part One. What I want to have in RESTinio 0.6 and what could be seen in 0.7?

Compatibility is a very good thing, but RESTinio-0.7 is somewhere on the horizon

I don't like to break compatibility between versions. It's because most of my career I work on projects with long lifetimes. And I know that it's not easy to update an old codebase if a new version of a library used breaks compatibility.

That is why we're trying to develop new functionality of RESTinio in the same branch: there were several releases inside 0.4 branch and there are several releases inside 0.6 branch. We're trying not to break compatibility between versions inside one branch. Because of that in most cases upgrades from, for example, 0.6.5 to 0.6.6 is going smoothly.

But sometimes we make mistakes. And sometimes we get asked about the features that can't be implemented in the current branch. In those cases we break compatibility.

There are some flaws in the current design of RESTinio because of those we can't implement some important features we want to have. Like support for incoming requests with very long bodies (without collecting the whole body in the memory). Or support for http/2 or/and http/3.

Because of that, there is a desire to start the development of 0.7 branch in the future. RESTinio-0.7 can break compatibility with 0.6. But it's unknown how seriously. It's also unknown when the development of 0.7 started and how long it can take.

There also are several features I want to have in the RESTinio that can be implemented in 0.6 branch without breaking compatibility (I hope). And I plan to begin work on them as soon as there will be a time for that.

connection_limiter

connection_limiter is an optional helper that can apply several limits to a RESTinio server.

The first limit is for the total number of active connections accepted by the server. For example, if a user sets that limit to 1000 then RESTinio won't call accept() if there are 1000 active connections. RESTinio will return to calling accept() when the number of active connections drops below that limit.

The second limit is for the total number of active connections from the same IP address. For example, if a user sets that limit to 20 then RESTinio will drop all new incoming connections from an IP address if there are already 20 active connections from that IP. The server can drop new incoming connections silently or can send back a negative response like "429 Too Many Requests".

ip_black_list and ip_white_list

ip_black_list is an optional object that drops all incoming connections made from specified IP addresses. A user can add/remove IP addresses to ip_black_list dynamically. An IP address is held in the ip_black_list for a specified amount of time. After expiration of that time the IP address is automatically removed from black list.

An ip_black_list can be used for making a simple defense for services that look directly to the Internet.

ip_white_list is an optional object that drops all incoming connections unless they are made from one of allowed IP. A user can add/remove IP addresses to ip_white_list dynamically. An IP address is held in the ip_white_list until it will be explicitly removed.

An ip_white_list can be used for making admin entry-points for software with Web-based admin interfaces. In those cases, access to the admin interface will be allowed only from a small set of known IP addresses.

Limits for max sizes of elements of HTTP message

I think RESTinio should check the maximum sizes of several elements of a HTTP message:

  • length of URI (aka request-target);
  • length of the name of HTTP field;
  • length of the value of HTTP field;
  • total size of all HTTP fields.

The current versions of RESTinio do not control those values. And because all those values are collected in the memory until the HTTP message will be parsed there is a possibility to make troubles for a RESTinio's server by sending incoming requests with very long HTTP fields.

What is the main goal of RESTinio-0.7?

The main goal for the 0.7 branch with high probability of breaking compatibility is to fix some flaws in the initial design of RESTinio:

  • loading of the whole HTTP message into the memory before the call to a request handler;
  • support for only HTTP/1.1 protocol.

Those were not flaws at the beginning of RESTinio's lifetime because we created RESTinio for our specific needs of that time. But time goes and RESTinio is now used in different scenarios by different people. So I think RESTinio should get fixes for those flaws to have a bright future.

I don't know yet how RESTinio can be extended for support of very long HTTP-messages and http/2 or http/3. But, I am afraid it may require to change RESTinio's interface. If so, then the switch from RESTinio-0.6 to RESTinio-0.7 will require some rewriting of the user's code.

When will RESTinio-0.7 get its shape?

It's hard to predict.

The main factor is that RESTinio doesn't bring us money by itself. So we have to do orders most of them do not relate to RESTinio. Because of that, we have time to develop RESTinio only in pauses between commercial software development, or if we use RESTinio in the commercial project and there is a necessity to add something to RESTinio.

Another factor is the presence of features that can be implemented in 0.6 branch without breaking the compatibility. And those can be useful right now, in any project that doesn't require the support of http/(2,3).

And yet another factor is the presence of other OpenSource projects (notable SObjectizer) that also require our attention. So we have to split our free time+resources between several OpenSource projects.

So I think that work on RESTinio-0.7 can be started not earlier than mid-autumn of 2020.

Part Two. The place of RESTinio in the landscape of modern C++ libraries?

More than three years ago we tried to create a modern C++ library that greatly simplified asynchronous processing of incoming HTTP requests. And I believe that RESTinio had one of the best and easy to use API at that time.

There were not so many analogs of RESTinio in 2017. At least we knew a few of them. For example, we knew about Beast, C++ REST SDK, CROW, Pistache, Proxygen, RestBed. But there also were Silicon (http_backend), Simple-Web-Server, served, drogon, and Oat++ we weren't aware of.

So now I have a very different view of the landscape of modern C++ libraries from that category.

It seems that there are very low-level tools like Boost.Beast and very high-level libraries like Oat++. And RESTinio is somewhere in between. It means that if a user wants a very simple to use tool for handling incoming HTTP requests then there is Oat++. And RESTinio isn't the best player in that category.

Because of that, the main philosophical question for me is: "Should we go in the direction of simplifying the API of RESTinio?"

Now I think we shouldn't.

I think RESTinio should have an easy to use (and hard to misuse) interface, but shouldn't hide important details from a user. So I see RESTinio as a tool that is much more high level than Boost.Beast, but lower level than Oat++.

And yet another direction that wasn't seen at the beginning of RESTinio development in 2017: some of RESTinio functionality can be used separately. For example, in one of the projects we have used the http_header_fields_t class and some helpers for parsing HTTP fields even without the usage of RESTinio's server. This direction should also be taken into the account (but it won't be the primary one).

Instead of the conclusion

I want to say thanks to all who choose RESTinio. Your support is very important for us and is one of the main drivers for the further development of RESTinio.

I have also to say that we are open and if you want to see something in the RESTinio you can tell about that by opening an issue on GitHub or in Google-group. I can't promise that all wishes will be fulfilled, but we'll try :)

Комментариев нет: