You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

100 lines
25 KiB

import { addBanner, addArticle, addTitle, addHeader, addParagraph, addClassParagraph, addCaption, addSubHeader, addOrderedList, addUnorderedList, addBlockquote, addQuote, addInset, addInsetList, addInsetCodeListing, addInsetBulletList, addImageWithCaption, addButtonGroup, addSidebar, addSyntax, menu, global_menu } from '/scripts/import.js';
import { local_menu } from '/scripts/webdev.js';
const heading = document.querySelector(".heading");
const global = document.querySelector(".global_menu");
const local = document.querySelector(".local_menu");
const sidebar = document.querySelector(".sidebar");
const main = document.querySelector(".main_content");
heading.append(addTitle("Learning REST APIs"));
heading.append(addParagraph("Morten Rand-Hendriksen - LinkedIn Learning - February 2018"));
heading.append(addParagraph("Chapter 2 - Request"));
main.append(addHeader("The RESTful Librarian"));
main.append(addParagraph("A good analogy for thinking about how a REST API works in context is to think of a librarian. In this scenario, the REST API plays the role of the librarian, the customer is the client sending requests to the API and the library itself, the books, are the data that the API is going to serve up."));
main.append(addParagraph("When a request is sent to the API, the 'librarian' collates the data and decides how it is to be returned to the client so the API is acting as an intermediary and interacts with both the client and the data in the API."));
main.append(addParagraph("The client might submit a GET request which is a way of saying please send me some data and it might provide some additional headers to let the API know the format (such as JSON or HTML) that it wants the data to appear in. The API will generate the response and send it to the client with a response code - hopefully something like 200 to indicate that everything is okay or it may send a 404 response if the requested resource can't be found. There may also be other things sent with the response including metadata like a resource id, links to available actions and so on. It is the often the responsibility of the client to parse the data into something meaningful at the client end."));
main.append(addParagraph("The client might also submit a PUT request possibly indiciating that it wants to change some data on the server side such as updating a password or it may just be the case that the client is sending some data to the client in order to modify the response and that might be some search terms, for instance, if the client is sending in a search request. If the client wants to update some data on the server side, the API may need to convert that data into a format acceptable to the server, it will then update the data and sends an updated representation of the data back to the client. Again, it will also send back some additional data including a response code to let the client know if the request succeeded."));
main.append(addHeader("What is a REST API?"));
main.append(addParagraph("The first step in understanding REST APIs is to understand what these terms mean, so let's start by defining them."));
main.append(addParagraph("REST stands for REpresentational State Transfer and you are probably familiar with the acronym API which stands for Application Programming Interface, so if we put both of these together we can say that a REST API is a"));
main.append(addSyntax("REpresentational State Transfer Application Programming Interface"));
main.append(addParagraph("So that makes things clearer, right? No? Not to worry, hopefully things will become clearer as we progress. I think that the key to understanding this is to understand what is meant by a representational state. We mentioned the fact that the REST API will often return a representation of the modified data in response to a put request so that might help to clarify things. Let's break it down into its three parts."));
main.append(addSubHeader("REpresentational"));
main.append(addParagraph("One of the responsibilities of the REST API is to provide a representation of the data in some form of another so that might be a web page, some JSON or XML containing search results and so on. It doesn't really matter what the actual data is."));
main.append(addSubHeader("State"));
main.append(addParagraph("State means the same thing here as it would if we were describing the current state of an object in a programming language like Java so here, we are thinking specifically of the data being returned so that includes what text is contained in a web page, what fields and associated values are being returned in search results and so on."));
main.append(addSubHeader("Transfer"));
main.append(addParagraph("This is the easy one, really. This signifies that the API is transferring the requested data back to the client as well as transferring the clients data (in some cases) to the server for, as an example, a PUT request."));
main.append(addParagraph("Consider a humble web page as an example where we are not using a REST API, but all of these things are nevertheless happening. Try clicking <a href='/index.html' target='_blank'>here</a> which will open the home page for this site in a new tab. Switch over to the tab and navigate to a different page. You might, for example, click on the Web Development button and then the Introducing Postman button to call up that particular page on this site. The home page is shown in figure 1."));
main.append(addImageWithCaption("images/example.png", "Figure 1 - The home page for this website."));
main.append(addParagraph("This page (for now, at least) is built in a traditional way with HTML and CSS. It doesn't use any JavaScript but the way in which I create these pages has evolved as I learn more Web Development skills. If you click through to the course notes for Introducing Postman, you will see a page with more textual content as shown in figure 2, you can also open that page in a new tab by clicking <a href='/webdevelopment/introducingpostman/introduction.html' target='_blank'>here</a>."));
main.append(addImageWithCaption("images/example1.png", "Figure 2 - The web page for my notes on the Introducing Postman course."));
main.append(addParagraph("Agian, this may change in the futire but for now this page is built in a different way to the home page. It is an HTML document, of course, and it uses CSS in more or less the same way that the home page does. However, where the HTML document for the home page is made up of a number of HTML elements such as paragrpahs, images, headers and so on, the HTML document for this page is empty in the sense that there is nothing except an empty main element in the body of the document. The code for this is shown in figure 3."));
main.append(addInsetCodeListing(["<!doctype html>", "<html>", "<head>", "<meta charset=\"utf-8\">", "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">", "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">", "<title>My Learning Website</title>", "<link href=\"/styles/styles.css\" rel=\"stylesheet\" type=\"text/css\">", "<link href=\"/webdevelopment/styles/styles.css\" rel=\"stylesheet\" type=\"text/css\">", "<script type=\"module\" src=\"./introduction.js\" defer></script>", "<script type=\"module\" src=\"/scripts/main.js\" defer></script>", "<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->", "<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->", "<!--[if lt IE 9]>", " <script src=\"https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js\"></script>", " <script src=\"https://oss.maxcdn.com/respond/1.4.2/respond.min.js\"></script>", "<![endif]-->", "</head>", "<body>", " <main></main>", "</body>", "</html>"]));
main.append(addCaption("Figure 3 - the HTML document associated with the web page shown in figure 2."));
main.append(addParagraph("If you inspect this web page, you will see somting quite different. Actually, you will see that it is made up of a number of HTML elements just as the home page is. The reason this happens is because if you look at line 10 in figure 3, you will see that thre is a link to a script which has the same name as the web page but with a js extension rather than an html extension. This JavaScript is generating the HTML for this page so when you click on the link to call up the web page, the browser downloads all the files required to display the page including the HTML, JavaScript, CSS and any image files. When it displays the HTML document, it runs the JavaScript which generates HTML elements and adds them to the main element we already have in the website. If we wanted to be super-minimalistic, we could have had the JavaScript add the main element and even the body element."));
main.append(addParagraph("To be clear, the web page doesn't use REST but it does the same things that REST does so it is useful for helping to explain what REST is. The webpage you see is a representation of the HTML document which has been generated, as I mentioned using JavaScript. If you inspect the HTML document, you are looking at its state. So, the browser is creating a representation of the page which is used to set the state of the browser (that is, what it is showing). Transfer in this case is handled by the web server and is one way, nothing (at least in this page), is being sent back to the server. However, we do have all of the three aspect of REST present here and hopefully that will help to understand what REST is."));
main.append(addParagraph("Before we dive into an explanation of what this means for us as developers, I want to note a couple of useful references."));
main.append(addParagraph("The first is a tutorial you can find at <a href='https://www.restapitutorial.com/'>www.restapitutorial.com</a>. The second is the REST Cookbook which you can find at <a href='https://restcookbook.com/'>restcookbook.com</a>."));
main.append(addParagraph("You can also find some useful info in the MDN Web Docs including a definition of <a href='https://developer.mozilla.org/en-US/docs/Glossary/REST'>REST</a> which I have reproduced in figure 4."));
main.append(addQuote("REST (Representational State Transfer) refers to a group of software architecture design constraints that bring about efficient, reliable and scalable distributed systems.<br>The basic idea of REST is that a resource, e.g. a document, is transferred via well-recognized, language-agnostic, and reliably standardized client/server interactions. Services are deemed RESTful when they adhere to these constraints.<br>HTTP APIs in general are sometimes colloquially referred to as RESTful APIs, RESTful services, or REST services, although they don't necessarily adhere to all REST constraints. Beginners can assume a REST API means an HTTP service that can be called using standard web libraries and tools.", "Figure 4 - A definition of REST from the MDN Web Docs."));
main.append(addParagraph("So REST is kind of a generic term, as is API, referring to a type of technology rather than anything specific. Similarly, we could say that a REST or RESTful API is not particularly specific. It is essentially an API that meets the constraints of REST. We might summarise that by saying that a REST or RESTful API manages the transitions between different states of some web resource such as a wep page or web application and the transfer of these states between the client and the server."));
main.append(addParagraph("With the example I gave previously of my own website, the changes in state were between one page and another, but each individual page is more or less static in the case that any individual who goes to a particular page on the site will see the same thingh in their browser (barring any browser or device related differences) that any other user visiting the same page would see. There is no API involved."));
main.append(addParagraph("Let's think about another example, this time LinkedIn Learning. You might think of this as more of a web app than a web page. For instance, I can go to the <a href='https://www.linkedin.com/learning/'>Home</a> page and here I can see typical content that any other user would see, but the content is tailored to my account so for example, I see my goals, the courses I am interested in, in some cases how I am progressing on certain courses or learning paths and this is all handled by an API. So, in this case, we can think of this (the LinkedIn API) as being a REST API."));
main.append(addParagraph("This REST API is a collection of tools used to access the REST resources using adverbs including GET, PULL, PUT and DELETE and so on. Going back to our earlier analogy, REST is acting like a librarian and the API is the language used to communicate with it so a REST API is a combination of some actor or service that manages the representation of the data and the transitions between different states and the transfer of these states between a client and a server."));
main.append(addHeader("Sidebar: URL vs URI"));
main.append(addParagraph("A URI is a Universal Resource Identifier and it is used to identify any resource accessible via the Internet. Similarly, a URL includes a string that can be used to identify a resource on the Internet but it also includes a method such as HTTP, HTTPS or FTP used to access the resource. Since it identifies the resource, any URL is also a URI. However, a URI doesn't necessarily provide a method for accessing the resource, so it is not necessarily a URL. We could therefore say that the set of URIs is the set of all identifiers for any web resources and that the set of URLs is a subset of this."));
main.append(addParagraph("URNs or Universal Resource Names are another subset of URIs and this is can be an explicit name such as oasis:names:specification:docbook or a resource name such as http://osztromok.com/index.html. REST code might use URLs, URNs or some combination but since both of these are subsets of the more generic term URI, we tend to use a URI to refer to resources and how they are accessed."));
main.append(addHeader("The Six Constraints of REST"));
main.append(addParagraph("In figure 4, we provided a definition of REST which began with \"REST (Representational State Transfer) refers to a group of software architecture design constraints that bring about efficient, reliable and scalable distributed systems.\" and this leads to the question of what these constraints are and we will look at that now."));
main.append(addSubHeader("1. Client-Server Architecture"));
main.append(addParagraph("A separation of concerns is a common theme in modern programming. It is important that the server handles all of the taske related to the storage and presentation of data. By that, I mean that the server prepares the data in the way that the client expects to receive it. Conversely, the client takes care of any tasks related to the user interface and carrying out any parsing of the data that might be required by the client. Imagine we had an API that returns data relating to books in your collection which you can then view in a web browser on a PC or in a specialised app on an android phone or an iPad. From the clients perspective, it sends a request to the API and requests data inm let's say, JSON format in either case. The PC accesses a web page that requests the data and presents it in a neatly formatted way. Similarly, the app sends a request to the API and gets the same data back and provides its own interface."));
main.append(addParagraph("You therefore have an API that doesn't care about the platform you are using, but rather it presents the data when requested in the format requested by the client."));
main.append(addParagraph("You can also take that data and present it in any way you like on your platform so the server doesn't have to worry about formatting the data or presenting it in a way that is appropriate for the client, the client takes care of that."));
main.append(addSubHeader("2. Statelessness"));
main.append(addParagraph("The server must not store the client state (client information and context) between requests. If data relating to the client context is necessary in order to fulfill the request, the client is responsible for sending that data to the API. If any of the data has to be stored and that might be, for example, an authentication token, the client has the responsibility of passing that data to the API with a request to store it in a database and it will also provide a timeframe for which the data must be retained."));
main.append(addSubHeader("3. Cacheability"));
main.append(addParagraph("In order to ensure that cacheing is performed correctly on the client, the API is required to mark all responses as cacheable or non-cacheable so this essentially means that the decisions on what should be cached (that is, data that is not expected to change very often) or not."));
main.append(addSubHeader("4. Layered System"));
main.append(addParagraph("As we described under the first constraint, the server doesn't know or care what type of client is accessing the data. Similarly, the client doesn't know anything about the server that provides the required response. This might be a single server, or there might be a number of intermediaries such as mirror servers or a CDN (Content Delivery Network). This allows for greater scaleability and security."));
main.append(addSubHeader("5. Code on Demand"));
main.append(addParagraph("The server is able to transfer executable code to the client and this might be in the form of client-side code such as JavaScript or it may be a pre-compiled module. It isn't commonly done, but it allows the API to extend and customize the functionality available to the client."));
main.append(addSubHeader("6. Uniform Interface"));
main.append(addParagraph("This actually breaks down into 4 other constraints."));
main.append(addSyntax("6.1 Resource Identification in Request"));
main.append(addParagraph("When a client submits a request to an API, it is asking the API to provide some representation of some resource stored on the server. The representation is configured for the client so it doesn't have to match the representation on the server. For example, the server might store that data in a database, but return it to the client as JSON data. Since the client is requesting this data which the server sees as part of its resources, it must provide a URI to allow the API to return the correct information."));
main.append(addSyntax("6.2 Resource Manipulation Through Representations"));
main.append(addParagraph("When a client receives a representation of some data, it can then modify or update that data and send the new data back to the client, assuming the user has the appropriate authorization to do that."));
main.append(addSyntax("6.3 Self-Descriptive Messages"));
main.append(addParagraph("When data is passed between the client and the server, in either direction, it is important that it describes its own data format in order for the data to be reliably parsed at the other end. For example, if the client has asked the server to provide some data in the JSON format, it is important that the data that is returned is clearly identified as JSON data."));
main.append(addSyntax("6.4 Hypermedia as the Engine of Application"));
main.append(addParagraph("When a client gains access to a REST resource, it should be possible for the client to then gain access to all available resources and methods through the provided links. By providing links to any available resources and methods in a request, the API is essentially providing a guide to its use every time it issues a response."));
main.append(addParagraph("These are constraints, not suggestions so any API that doesn't operate under one or more of them cannot be considered a RESTful API."));
main.append(addHeader("How REST Relates to HTTP"));
main.append(addParagraph("A REST API will often be accessible via the Internet and more sepcifically, using the HTPP Protocol, but in fact this is not a requirement. HTTP is really just a protocol that makes it possible for REST APIs to work and there are others such as FRP or SMPT, to give a couple of examples."));
main.append(addParagraph("We have referred to REST APIs on occassion as a RESTful API, which is actually a slightly more specific term. This refers to an API that offers access to some web resource over the web via HTTP."));
main.append(addParagraph("We said that if an API met the 6 constraints we listed, it could be considered to be a REST API. We can now extend that a little and say that if it meets the 6 constraints and responds to requests sent over the web via HTTP, it can be considered to be a RESTful API."));
main.append(addHeader("Who or What Interacts with REST APIs?"));
main.append(addParagraph("When we refer to a client accessing the resources exposed by a REST API, we are not referring to a human. Rather, the client is the app or browser that interacts with the API. So, the human operator interacts with the client to generate a request and that client sebds the request to the API, receives the response and presents it to the human user via the client interface."));
main.append(addParagraph("The API really doesn't care what the client is, it just cares that it sends in the request in a way that is compatible with the API. Where the request came from and where the response is being sent to doesn't matter as far as the API is concerned."));
main.append(addParagraph("That's really a good way of thinking about a REST API - it makes some resource or resources available to any client that sends in a proper request."));
main.append(addParagraph("Note that in spite of this, REST APIs are not always completely open. In many cases, it may require a user to provide some authentication, such as an API key that governs what the resources the user can access and other things such as the number of requests the user can send in a specified time frame. So, any client can access the resources of an API provided it proivdes the necessary authentication if necessary."));
main.append(addHeader("Tools to See REST API in Action"));
main.append(addParagraph("In this section, we will interact with a real API, albeit one used for test purposes and that is REQ|RES which you can find at <a hef='https://reqres.in'>reqres.in</a>. With free APIs like this, it is normal for the API provider to supply a list of supported requests which you can see on the req|res homepage by scrolling down and this is shown in figure 5."));
main.append(addImageWithCaption("images/reqres.png", "Figure 5 - The list of requests supported by REQ|RES."));
main.append(addParagraph("Note that in the list shown in figure 5 and I clicked on the second request, SINGLE USER. In the Request panel we can see the syntax for this request which is"));
main.append(addSyntax("/api/users/2"));
main.append(addParagraph("where 2 is the id of the user that we want to find. There is also a response panel which shows what we can expect to see being returned. We can type this into a browser as"));
main.append(addSyntax("https://reqres.in/api/users/2"));
main.append(addParagraph("and we can see the result I got from sending that request in figure 6. Note that the data is the same as that shown in the response panel in figure 5."));
main.append(addImageWithCaption("images/reqres.png", "Figure 6 - The response from sending the request shown above."));
main.append(addParagraph("It might be worth mentioning the fact that REQ|RES is a RESTful API which means we can use any client to send our request if that client uses the HTTP protocol to do that which, of course, our browser does."));
main.append(addParagraph("This course doesn't cover Postman but of course, Postman also uses the HTTP protocol to send requests so we can also use it to send these requests. There are other clients and this can include a code editor if that editor has an extension with a REST client. The course uses Visual Studio Codeas the REST client so I will do that too. In Visul Studio Code, click the Extensions icon in the menu down the left-hand side and then search for REST Client. The one you want should be the first result returned and if it isn't already installed, click on Install to do that."));
main.append(addParagraph("To use it, you will propably want to create a folder to hold your request and for the sake of simplicity, I have created a folder on my desktop called REST_APIs. In Visual Studio Code, you want to then open the folder in VSC so that you can easily access files inside it and then open a new file."));
main.append(addParagraph("Put your request into that file so this is the same as the request you would send via the browser or Postman and it will include the method which in this case is GET. Visual Studio Code should recognise that this is a REST request and provide you with a link you can click to send it. Figure 7 shows Visual Studio Code with the request and the response and you can see that this is similar in terms of content to what we were seeing in the browser."));
main.append(addImageWithCaption("images/vsc.png", "Figure 7 - The request and response in Visual Studio Code."));
main.append(addParagraph("However, the appearance us very different here compared to what we would see in a browser. First of all, we have the HTTP headers displayed at the top and the data itself is formatted in a much more human-readable way."));
addSidebar("webdev");