📜 ⬆️ ⬇️

Duma about the web-API. part two

Approaching the second: The right way

If suddenly you missed the first approach, you can find it here . And in this approximation, I would like to talk separately about the approaches to building unique paths to the resources and methods of your web API and about the architectural features of the application that affect the appearance of this path and its components.

What is worth thinking while standing on the shore


Versionality


Sooner or later, any operating system begins to evolve: evolve, become more complex, scale, and modernize. For REST API developers, this is fraught primarily with the need to launch new versions of the API while the old ones are running. Here I’m not talking anymore about architectural changes under the hood of your system, but about the fact that the data format itself and the set of operations with them are changing. In any case, versioning should be provided both in the initial organization of the source code, and in principle the construction of the URL. As for the URL, there are two of the most popular ways to specify the version of the API that the request is addressed to. Prefixing the path example-api.com/v1/ and breeding versions at the subdomain level v1.example-api.com . You can use any of them, depending on the need and need.

Component autonomy


Web API complex systems that support multiple user roles, often requires separation into parts, each of which serves its own range of tasks. In fact, each part can be an independent application, work on different physical machines and platforms. In the context of the API description, it doesn’t matter to us how the server processes the request and what forces and technologies are involved in this. For an API client, the system is encapsulated. However, different parts of the system may have completely different functionality, for example, the administrative and user parts. And the methodology of working with the same seemingly same resources may differ significantly. Therefore, such parts must be separated at the level of the admin.v1.example-api.com domain or the path prefix example-api.com/v1/admin . This requirement is not mandatory, and much depends on the complexity of the system and its purpose.

Data exchange format


In my opinion, the most convenient and functional data exchange format is JSON , but no one forbids the use of XML , YAML or any other format that allows storing serialized objects without losing the data type (we are for typing). If you prefer, you can make the API support multiple input / output formats. It is enough to use the HTTP request header to specify the desired Accept response format and Content-Type to specify the format of the data transmitted in the request. Another popular way is to add an extension to a resource URL, for example, GET /users.xml , but this method seems less flexible and beautiful, if only because it makes the URL heavier and true for GET requests rather than for all possible operations.
')

Localization and multilingualism


In practice, multilingual API is most often reduced to translating service messages and error messages into the required language for direct display to the end user. Multilingual content also has a place to be, but the storage and distribution of content in different languages, in my opinion, should be distinguished more clearly, for example, if you have the same article in different languages, then in fact these are two different entities grouped by a sign of unity of content. To identify the expected language, you can use different methods. The simplest is the standard HTTP header Accept-Language . I have seen other ways, such as adding the GET parameter language = ”en”, using the path prefix example-api.com/en/ or even at the domain name en.example-api.com . It seems to me that the choice of how to specify the locale depends on the specific application and the tasks facing it.

Internal routing


So, we got to the root node of our API (or one of its components). All further routes will pass directly inside your server application, in accordance with the set of resources it supports.

Ways to collections


To specify the path to the collection, we simply use the name of the corresponding entity, for example, if it is a list of users, then the path will be that of / users . Two methods are applicable to the collection as such: GET (getting a limited list of entities) and POST (creating a new item). In requests for lists, we can use many additional GET parameters used for paginal output, sorting, filtering, searching, etc, but they should be optional, i.e. These parameters should not be passed as part of the path!

Elements of the collection


To refer to a specific element of the collection, we use its unique identifier / users / 25 in the route. This is a unique way to it. The GET (object acquisition), PUT / PATCH (change) and DELETE (delete) methods are applicable for working with an object.

Unique objects


In many services, there are objects unique to the current user, for example, the profile of the current user / profile , or personal settings / settings . Of course, on the one hand, these are elements of one of the collections, but they are the starting point in the use of our Web API by the client application, and also allow a much wider range of operations on data. In this case, the collection that stores user settings may not be available at all for security and privacy reasons.

Properties of objects and collections


In order to get to any of the properties of an object directly, it is enough to add the name of the property to the path to the object, for example, to get the user name / users / 25 / name. The GET (get value) and PUT / PATCH (change value) methods are applicable to the property. The DELETE method is not applicable, since A property is a structural part of an object, as a formalized data unit.

In the previous part, we talked about the fact that collections, like objects, can have their own properties. In my memory, only the count property came in handy, but your application can be more complex and specific. The paths to the properties of collections are built on the same principle as the properties of their elements: / users / count. For properties of collections, only the GET (property retrieval) method is applicable, since The collection is only an interface for accessing the list.

Collections of related objects


One of the types of properties of objects can be related objects or collections of related objects. Such entities, as a rule, are not an object's own property, but merely references to its connections with other entities. For example, a list of roles that have been assigned to / users / 25 / roles . As for working with nested objects and collections, we will talk in detail in one of the following parts, and at this stage it suffices that we have the opportunity to refer to them directly, as to any other property of the object.

Object and Collection Functions


To build the path to the call interface of the collection or object, we use the same approach as for accessing the property. For example, for the / users / 25 / sendPasswordReminder object or the / users / disableOld collection . For function calls, we always use the POST method. Why? Let me remind you that in the classic REST there is no special verb for calling functions, so we will have to use one of the existing ones. In my opinion, the POST method is most suitable for this, since it allows you to transfer the necessary arguments to the server, is not idempotent (returning the same result with multiple conversions) and is most abstract in semantics.

I hope that everything is more or less fit into the system :) In the next part we will talk more about requests and responses, their formats, status codes.

Source: https://habr.com/ru/post/313532/


All Articles