With a REST API, is there a convention for clients validate a request without committing any changes?
Not really, not in the way that you mean. REST doesn't care what spelling you are using for your identifiers; in REST, URI are opaque. The client just follows the links that are provided.
So you could send the validate the data to /c255ed19-d6b0-4666-b9cc-abc48d4246ae
and the actual "do it" request to fbb43bdf-0016-4aa1-9f55-28b884238d40
and as far as REST is concerned, those spellings are fine.
So changing the resource identifier to include an intent=validate
parameter in the URI is fine. If you instead decided to distinguish the intent by using a different spelling in the path segments, that's also fine. REST doesn't care; any meaning encoded into URI is done at the discretion of the server and for its own exclusive use.
Of course, if the spelling of the URI is opaque, then that spelling doesn't communicate any useful semantics. There must be an extra layer of indirection somewhere; in REST, that somewhere is a link -- the relation type is the out of band information that the client and server agree upon in advance. In an ideal case, the relation that you need is already standardized; you can check in the link relations registry to see if the information you need is there. If not, you can create a bespoke extention relation type, and assign it a meaning.
<link rel="http://example.org/relations/validateOrder" target="/c255ed19-d6b0-4666-b9cc-abc48d4246ae" />
<link rel="http://example.org/relations/placeOrder" target="/fbb43bdf-0016-4aa1-9f55-28b884238d40" />
You can mint your own identifiers to define these relations, or you can look for matches among the schemas that already exist
<link rel="http://schema.org/CheckAction" target="/c255ed19-d6b0-4666-b9cc-abc48d4246ae" />
<link rel="http://schema.org/OrderAction" target="/fbb43bdf-0016-4aa1-9f55-28b884238d40" />
In this case, i would add various kinds and combinations of rate-limiting, e.g.:
- maximum requests per interval allowed for the complete API
- maximum requests per interval for specific parts of the API, if you have certain calls that are 'expensive'
If you are able to identify non-authenticated calls, e.g. by IP-Adress or Cookies or something, you may be able to additionally limit that even more accurate. E.g.:
- maximum requests per client per interval for complete API
- maximum requests per client per interval for specifica parts of the API
Interval could be anything, e.g. hardcoded 5 seconds, in a fixed or a sliding time window.
In one project I implemented something like that using a combination of ip-adress and if available the user-id, and it worked very well - protecting the service from misuse/attacks of anonymous, identifiable and even properly authorized clients.
Iirc I used https://github.com/mokies/ratelimitj - the readme there also points to some background articles, e.g. https://blog.figma.com/an-alternative-approach-to-rate-limiting-f8a06cf7c94c
Best Answer
There are multiple ways which this question can be answered:
Aggregation of endpoints
API Gateways mostly aggregate other endpoints, not necessarily their results. That is, it is a single server which might mirror other endpoints with some additional functionality, like authentication, or routing.
The point is to centralize some services, hide the actual servers from the outside network, etc.
Aggregation of results
If you really want to have business logic on the Gateway, pulling different documents together to another document, or just altering requests or responses, you might be looking at an Enterprise Service Bus.
Whether aggregation is good
This is of course debatable, and up to individual opinions. One might argue, that there is a reason we got (mostly) away from SOA/ESB type solutions. This reason might be because individual responsibilities were not clear and would tend to collect on the ESB side, leaving the endpoints "dumb". Eventually resulting in the ESB knowing everything.
The "REST" approach is different. It builds on "smart" endpoints, knowing their part, and making sure no other components need to know any of the details. This idea in itself seems to be in conflict with making the Gateway know more about the responses.
Indeed, there are some architecture ideas, like Self-Contained Systems, that build on the idea, that any function your client would need should be covered completely by a given endpoint. It should not need synchronous communication with others to fulfill a request in its own area of responsibility. This also suggests that aggregating results might be counterproductive.
As always though, it all depends on the exact requirements.