Task 6 – API endpoint with payload required (July Developer Challenge – “Reverse APIs”)

This is a task in the July Developer Challenge – “Reverse APIs”.

This task gets you to add another API endpoint to the plain “REST” service you have, but will be a little different in its definition, implementation, and how it’s called.

Background

HTTP-based API endpoints, whatever the protocol, can differ in various ways, such as:

  • how they’re called (which HTTP method)
  • whether they expect a payload (a body) in the HTTP request
  • what they do, what effect they have at the server side
  • what resource and representation they return (if any)

HTTP is an application protocol and there are already well understood semantic meanings for each of the methods (also known as “verbs”, where the URLs are the “nouns”). There are some protocols that abuse or ignore these semantics, particularly the set of heavyweight “Web Services” from a decade or so ago, known as “WS-Deathstar” (due to their weight and complexity), SOAP, and even today we have GraphQL that arguably abuses HTTP as a mere transport layer. Yes, “abuse” is a strong word, but, as my bio hints at, it’s an opinion I hold, and is one of many 🙂

bio.png

Anyway, in addition to those differences listed earlier, one must also consider the duumvirate (yes, I did just use that word) of:

  • idempotency
  • side effects

Idempotency (from the Latin, as is, of course, duumvirate) essentially means “having the same effect”. To quote the excellent MDN docs on Idempotency:

An HTTP method is idempotent if the intended effect on the server of making a single request is the same as the effect of making several identical requests.

Examples of HTTP methods that have this idempotency characteristic are: GET, HEAD, PUT and DELETE (yes!).

A side effect in this context means that in handling or otherwise fulfilling an HTTP request, state is changed on the server. HTTP methods that do not have side effects are known as safe. Examples of HTTP methods that do have side effects, i.e. that are not safe, are POST, PUT and DELETE. Examples of HTTP methods that are side effect free, i.e. safe, are GET, HEAD and OPTIONS.

Semantic meanings are important, as they form part of the “contract” of behaviour between clients and servers.

Why am I telling you all this? Because CDL, CAP’s definition language that you use to define your overall CDS model, has a couple of keywords that are important in this context.

Actions and functions

In Capire’s section on Providing Services, there’s a subsection on Actions & Functions that explain more. I recommend you go and read that section, then come back here.

Did you notice the explanation was in the context of OData? That’s because it’s where the specific definitions originate, but these definitions make sense even outside the context of OData, such as when serving via the “REST” protocol.

In summary, we can see that both actions and functions are for providing API endpoints that represent resources beyond the standard CRUD+Q requests, although:

  • Functions are for defining API endpoints that are safe, these endpoints are to be requested with HTTP GET, and any data should be supplied in the URL. There’s a related rule here that functions must be addressed (in the URL) with brackets, even if there’s no data to supply. Functions, on the whole, are for returning data.
  • Actions are for defining API endpoints that may have side effects, and these endpoints must be requested with HTTP POST; any data that is to be supplied must be as a payload to the POST request. In addition, actions may return nothing (just an HTTP status code and headers).

In addition (but not relevant for this task), both functions and actions can be bound or unbound. The idea of “unbound” is what we generally think of in terms of simple API endpoints. The “bound” concept is from OData, and is about calling an action or function relative to a specific entity. In such cases there’s an extra implicit “binding parameter” that the implementation receives in the request, as a connection to the instance of the entity to which the called function is bound.

The first task in the context of this current plain “REST” service was an unbound function (note the brackets, despite no parameters):

/rest/plain/theAnswer()
This task will require you to define and implement a simple unbound action, which means you must:
  • use the action keyword
  • call it using a request with the HTTP POST method
  • send the data in the payload of the request

You will also not need to use brackets at the end of the URL.

The requirements

Here are the specific requirements for this task.

In the plain service you have already, define an unbound action that expects a list of integers. The implementation of that unbound action must determine the highest of those numbers, and return it as a single integer.

Submitting to the TESTER

Now you’re ready to submit your CANDIDATE service, with this new API endpoint, to the TESTER!

Note that the TESTER will be calling your action via HTTP POST, and supplying the list of integers as an array, in a JSON representation, in other words, like this:

POST /rest/plain/highestValue HTTP/1.1
Host: localhost:8000
Content-Type: application/json
Content-Length: 19

[54, 203, -3, 0, 1]

The payload

The task identifier you need to supply in the payload of your submission is: plain-highestValue.

You’ll have already done this sort of thing previously so just head back there for the more detailed instructions if you need them, or to the the section titled “The Tester service, and making a test request” in the main challenge blog post.

You’ll need to submit a JSON payload like this:

{
  "communityid": "<your-community-id>",
  "serviceurl": "<the-URL-of-your-service>",
  "task": "plain-highestValue"
}
And, just as with the previous (and all further tasks):
  • the value for the communityid property should be your ID on this SAP Community platform (e.g. mine is “qmacro”)

  • the value for the serviceurl property should be the absolute URL (i.e. including the scheme), of your CANDIDATE service which contains the API endpoint (see ℹ️ A note on URLs and services).

That’s it!

Logging of test results

Remember that you can check on your progress, and the progress of your fellow participants – all requests are logged and are available in an entity set served by the TESTER service. The entity set URL is https://developer-challenge-2024-07.cfapps.eu10.hana.ondemand.com/tester/Testlog and being an OData V4 entity set, all the normal OData system query options are available to you for digging into that information.

Until the next task, have fun, and if you have any questions or comments, leave them below!

Scroll to Top