Applications use application programming interfaces (APIs) to communicate. To do so, one program can learn the variables and data structures used by another program, making logic choices based on those values, changing the values of those variables, creating new variables, and deleting variables. APIs allow programs running on different computers to work cooperatively, exchanging data to achieve some goal. In an API software world, some applications create an API, with many other applications using (consuming) the API. Software developers add APIs to their software so other application software can make use of the first application’s features.
When writing an application, the developer will write some code, but often the developer may do a lot of work by looking for APIs that can provide the data and functions, reducing the amount of new code that must be written. As a result, much of modern software development centers on understanding and learning new APIs, along with the available libraries (prebuilt software that can be used to accomplish tasks rather than writing the equivalent from scratch).
REST-Based (RESTful) APIs
REST APIs follow a set of foundational rules about what makes a REST API and what does not. First, from a literal perspective, REST APIs include the six attributes. Those six attributes are:
- Client/server architecture
- Stateless operation
- Clear statement of cacheable/uncacheable
- Uniform interface
Like many applications, REST applications use a client/server architectural model. First, an application developer creates a REST API, and that application, when executing, acts as a REST server. Any other application can make a REST API call (the REST client) by executing some code that causes a request to flow from the client to the server.
- The REST client on the left executes a REST API call, which generates a message sent to the REST server.
- The REST server on the right has API code that considers the request and decides how to reply.
- The REST server sends back the reply message with the appropriate data variables in the reply message.
The stateless attribute of REST APIs means that REST does not record and use information about one API exchange for the purpose of how subsequent API exchanges are processed. In other words, each API request and reply does not use any other past history considered when processing the request. For comparison, the TCP protocol uses a statefull approach, whereas UDP uses stateless operation. A TCP connection requires the endpoints to initialize variables on each end, with those variables updating over time, and with those variables being used for subsequent TCP messages. For instance, TCP uses sequence numbers and acknowledgment numbers to manage the flow of data in a TCP connection.
Cacheable (or Not)
To appreciate what is meant by cacheable, consider what happens when you browse a website. When your browser loads a new web page, the page itself contains a variety of objects (text, images, videos, audio). Some objects seldom change, so it would be better to download the object once and not download it again; in that case, the server marks that object as cacheable. For instance, a logo or other image shown on many pages of a website would almost never change and would likely be cacheable. However, the product list returned in your most recent search of the website would not be cacheable because the server would want to update and supply a new list each time you request the page.
REST APIs require that any resource requested via an API call have a clear method by which to mark the resource as cacheable or not. The goals remain the same: improve performance by retrieving resources less often (cacheable). Note that cacheable resources are marked with a timeframe so that the client knows when to ask for a new copy of the resource again.
REST APIs and HTTP
APIs exist to allow two programs to exchange data. Some APIs may be designed as an interface between programs running on the same computer, so the communication between programs happens within a single operating system. Many APIs need to be available to programs that run on other computers, so the API must define the type of networking protocols supported by the API—and many REST-based APIs use the HTTP protocol. The creators of REST-based APIs often choose HTTP because HTTP’s logic matches some of the concepts defined more generally for REST APIs. HTTP uses the same principles as REST: it operates with a client/server model; it uses a stateless operational model; and it includes headers that clearly mark objects as cacheable or not cacheable. It also includes verbs—words that dictate the desired action for a pair HTTP Request and Reply—which matches how applications like to work.
Software CRUD Actions and HTTP Verbs
The software industry uses a memorable acronym—CRUD—for the four primary actions performed by an application. Those actions are:
- Create: Allows the client to create some new instances of variables and data structures at the server and initialize their values as kept at the server
- Read: Allows the client to retrieve (read) the current value of variables that exist at the server, storing a copy of the variables, structures, and values at the client
- Update: Allows the client to change (update) the value of variables that exist at the server
- Delete: Allows the client to delete from the server different instances of data variables
For instance, if using the northbound REST API of a DNA controller, you might want to create something new, like a new security policy. From a programming perspective, the security policy exists as a related set of configuration settings on the DNA controller, internally represented by variables. To do that, a REST client application would use a create action, using the DNA Center RESTful API, that created variables on the DNA Controller via the DNA Center REST API. The concept of creating new configuration at the controller is performed via the API using a create action per the CRUD generic acronym.
HTTP uses verbs that mirror CRUD actions. HTTP defines the concept of an HTTP request and reply, with the client sending a request and with the server answering back with a reply. Each request/reply lists an action verb in the HTTP request header, which defines the HTTP action. The HTTP messages also include a URI, which identifies the resource being manipulated for this request. As always, the HTTP message is carried in IP and TCP, with headers and data.
HTTP works well with REST in part because HTTP has verbs that match the common program actions in the CRUD paradigm. Table lists the HTTP verbs and CRUD terms for easy reference and study.
|Action||CRUD Term||REST (HTTP) verb|
|Create new data structures and variables||Create||POST|
|Read (retrieve) variable names, structures, and values||Read||GET|
|Update or replace values of some variable||Update||PATCH, PUT|
|Delete some variables and data structures||Delete||DELETE|
Using URIs with HTTP to Specify the Resource
In addition to using HTTP verbs to perform the CRUD functions for an application, REST uses URIs to identify what resource the HTTP request acts on. For REST APIs, the resource can be any one of the many resources defined by the API. Each resource contains a set of related variables, defined by the API and identified by a URI. For instance, imagine a user creates a REST-based API. When she does so, she creates a set of resources that she wants to make available via the API, and she also assigns a unique URI to each resource. In other words, the API creator creates a URI and a matching set of variables, and defines the actions that can be performed against those variables (read, update, and so on).
The API creator also creates API documentation that lists the resources and the URI that identifies each resource, among other details. The programmer for a REST client application can read the API documentation, build a REST API request, and ask for the specific resource.
Above figure shows the URIs as generic values; however, today’s network engineers need to be able to read API documentation, see URIs in that documentation, and understand the meaning of each part of the URI. Below figure shows a URI specific to the Cisco DNA Center northbound REST API as an example of some of the components of the URI.
The figure shows these important values and concepts:
- HTTPS: The letters before the :// identify the protocol used—in this case, HTTP Secure (which uses HTTP with SSL encryption).
- Hostname or IP Address: This value sits between the // and first /, and identifies the host; if using a hostname, the REST client must perform name resolution to learn the IP address of the REST server.
- Path (Resource): This value sits after the first / and finishes either at the end of the URI or before any additional fields (like a parameter query field). HTTP calls this field the path, but for use with REST, the field uniquely identifies the resource as defined by the API.
The Need for a Data Model with APIs
First, for the nonworking example, consider the flow and numbered steps in figure. A REST client sits on the left. The REST client asks for a resource, and the server needs to reply. In REST, a resource is a set of variables as defined by the API, so the REST server needs to return a set of variables to the REST client on the left. The steps in the figure run as follows:
- The REST server (a JAVA application) takes a copy of the stored variables in RAM (step 1) in response to the REST request.
- The REST API code creates the REST reply and sends it over the network, placing an exact replica of what the REST server had in RAM to represent the variables in that resource.
- The REST client (a Python application) receives the REST reply message, storing the exact same bits and bytes into its RAM, in an attempt to have a copy of the variables, data, and data structures on the server.
The process shown in figure does not work (and is not attempted) because the REST client programs may not store variables in the same ways. First, programs written in different languages use different conventions to store their variables internally because there is no standard for internal variable storage across languages. In fact, programs written in the same language but with different versions of that language may not store all their variables with the same internal conventions. To overcome these issues, applications need a standard method to represent variables for transmission and storage of those variables outside the program. Data serialization languages provide that function.
Below figure shows the correct process flow in comparison to figure with the data serialization process included:
- The server collects the internally represented data and gives it to the API code.
- The API converts the internal representation to a data model representing those variables (with JSON shown in the figure).\
- The server sends the data model in JSON format via messages across the network.
- The REST client takes the received data and converts the JSON-formatted data into variables in the native format of the client application.
At the end of the process, the REST client application now has equivalent variables to the ones it requested from the server in the API call. Note that the final step—to convert from the data serialization language to the native format—can be as little as a single line of code! Finally, note that while data serialization languages like JSON enable applications to exchange variables over a network, applications can also store data in JSON format.
Each data serialization language enables API servers to return data so that the API client can replicate the same variable names as well as data structures as found on the API server. To describe the data structures, the data serialization languages include special characters and conventions that communicate ideas about list variables, dictionary variables, and other more complex data structures.