Swagger at RBK.money – about our external APIs
If you want to do something useful and working, make it so that other people can use it fully, review it normally, and generally remember you with a kind word, and not the dark side of your vocabulary.
To do this, in addition to just doing your job well, writing the right code, not being afraid to use modern technologies and generally not being stupid, you need to pay attention to two things – the documentation and the API. Without them, it will be difficult for a person to understand what he is dealing with, how it works and what’s best not to be touched at all. Of course, you can google what this or that specification means, you can check in battle what and how (and then roll back to the previous working version as cheerfully), but it’s better when the person was given detailed documentation.
So that’s what I’m talking about today. In this post I will tell you why we use Swagger at RBK.money, how it helps us in our work and what jambs it has.
So, Swagger aka OpenAPI (https://swagger.io/) Swagger is good because it means a bunch of useful goodies at once, look here:
- typing of variables
- description of methods
- convenient link scheme
- not tied to any particular language
- and indeed a cool thing, everything that we need, it seems, is.
The scheme is described by a concise YAML or JSON file, it is easy to validate, and interfaces can be quickly generated for any language. Describing the interface on Swagger is also fast. Here, in principle, there are no special alternatives. Of course, you can recall xml, but to me personally it seems to be some uncomfortable antiquity purely from an aesthetic point of view. This actually seems important to me, because I’m trying to relate to the code as Tupolev’s companion for airplanes:
Only beautiful planes can fly well
Yes, here you can cheer about the accuracy of the quote, and indeed recall Marcel Dassault and his “un bel avion est un avion qui vole bien”, but we are not talking about that yet. I hope I conveyed the essence. So here. In my case, in Sublime Text, what we do should look beautiful. If this is a specification, then so is it. Alas, this thesis does not apply to xml.
And here is YAML – there is no garbage, there is only what you wrote.
The Swagger specification is also interesting in that description, definitions can be done normally. And so it turns out that the protocol itself is an interactive documentation. The arsenal is full of cool pieces that allow you to make a pretty decent thing out of YAML. All that I need for its normal support is to slightly edit the specs in YAML, and that’s all, I have ready-made documentation.
An example of interactive documentation built on a spec using ReDoc scripts is used by us on our developer portal: https://developer.rbk.money/api/.
More about the pros
The whole protocol is visible and described, you know what types are there, if you need to check what by the degree of security – you can safely go into the protocol implementation in the code and understand that (at least) all types that come to you have been validated. This is already cool, because it is a sufficient degree of protection – the set of input data to the control command is known, and it is easy to check the compliance of this set with the scheme. I will make a reservation right away that this does not give a full guarantee of security (a spoiler does not give anything at all), but it immediately blocks a huge bunch of potential holes.
A similar protocol is reviewing too quickly. Some definition is added to the new entity, for example, a chargeback. And you don’t have to cheerfully revise the footcloth for a few meters – you look that a new type has been added, you understand what it does, it makes it possible to automate tests and security. Because chargeback, in principle, is a very complex business process. And very heavy. But here it fit in 6 files and 224 lines. The beauty is that this is enough to completely understand what kind of data will go between microservices, all possible errors are described. In general, guys, this is really convenient.
Debiting is also a pleasure. Swagger was also chosen because it was possible to quickly log in from the browser, see requests and payloads. Yes, of course, you could go and make a web socket and drive a lot of data hard there, but I’m not a fan of this – it’s usually its own protocol, the wildest one, it’s also binary most often, and it’s normal to make it and not want to The process of taking a vacation (or sick leave) is quite difficult. Moreover, I have to secure everything wildly in such a scheme, but I want openness and transparency. So that you can quickly pull the curl-ohm from the console and see how things are going there in general.
There are enough data types with a margin, so far we haven’t had any situations so that we don’t have enough data types.
And one more thing. You assembled a distributed team, locked everything, someone writes a client, someone writes a server, you generally went to write UX / UI for the backend. The backend itself should be done for a long time, but we have a swagger spec, take it, generate a mock server for it, and that’s it. You can start writing the front-end before the back-end, in principle, finishes his coffee and turns on the computer to start working. And then you write a backend, change the endpoint and get a ready-made solution. That is, you can not only parallelize development, but also untie the dependencies of teams. This is a cool thing.
Cons, cons there?
And where without them, this is a great thing, but not a silver bullet so far.
Firstly, Swagger codegen in fact does not work. We had to cut it, so carried away that in the end we wrote our own. Now we can generate methods and classes. And so on paper everything was hurt, you take specs, generate a client, generate a server, enjoy life. In fact, you neither the client nor the server. Having heard a couple of desperate mats from developers on this topic, I decided to write my own.
Secondly, at the start we had a conflict of this kind. Inside the platform we have Thrift. At the same time, I’ll go outside with Swagger. Incidentally, I still can’t admit to myself that they did everything right, that it’s good that they didn’t take Swagger right away. And so it was twice as much work, protocol translators and other joys.
By the way, why Thrift – we had ready-made developments on rpc and client-server things that solved transport problems. We quickly screwed the implementation of Google Dapper there, the implementation of the idea that in a distributed microservice environment, you must be able to trace requests. That is, to understand what chain of microservices these very questions go to, and where they are stupid, if they are stupid. In one of the following posts about this will be in more detail. And it turned out that everything is inside, but outside it is necessary to do something different.
And also a changelog. There is a wildly weak automation of the changelog. You’re changing some methods to show that earlier in this method there was one thing – and now it’s different, and so, except for diffs in the repository, this is not. Therefore, the changelog must be written with your hands. And since you have to constantly do something with your hands, because it has not been possible to automate, this will not be done at all. And now it’s a little in the way of work, for example, I can’t explain to clients normally on the fingers what the difference is between API 2.0 and API 3.0 – there is no changelog.
And there are no examples. Usually they are, but here you have to write them yourself in the documentation generator. It is not so difficult, but – time.
In general, we are satisfied, but there are nuances – the documentation does not reflect some nested structures, now the 3rd specification, to which we can not migrate so far, and live on the second. But this is our technical debt. So – overcome.
And even if I didn’t like something more, there’s nowhere to dump. Suddenly, tell me in the comments something interesting on the topic. Of course, I won’t exchange Swagger for any separate crutch samopal, because something crutch and mine – it is in the end even worse than something average, but standard.
And that’s why.
In principle, I would be very happy if everyone who opens the API now would go in the direction of Swagger, look – this is a community, first of all. The community that will come will look at the standard, at the specification, and this will begin to develop. Where someone doesn’t like something, they’ll finish it and make it better. The standard here is always preferable.
Because the standard can be improved. And you can start doing something of your own in a separate corner, and then hammer on it, or even pull it in different directions all the time.
But again, if you know some useful alternative that is suitable for solving such problems – share in the comments, please.
You can take and evaluate here.
Remark after discussion in the comments. If you start from scratch, then you should immediately lay on the specification Open API Specification 3.0. There are radically more buns, we can say that this is almost a new standard, very different from version 2.