REST APIチュートリアル–コード例で説明されているRESTクライアント、RESTサービス、およびAPI呼び出し

Webサイトでのログイン/サインアップがバックエンドでどのように機能するのか疑問に思ったことはありませんか?または、YouTubeで「かわいい子猫」を検索すると、たくさんの結果が得られ、リモートマシンからストリーミングできるのでしょうか。

この初心者向けガイドでは、RESTfulAPIを設定するプロセスについて説明します。専門用語の一部を分類解除し、NodeJSでサーバーをコーディングする方法を見ていきます。JavaScriptについてもう少し詳しく見ていきましょう。

その専門用語を取り除いてください

では、RESTとは何ですか?ウィキペディアによると:

Representational State TransferREST)は、Webサービスの作成に使用される一連の制約を定義するソフトウェアアーキテクチャスタイルです。RESTful Webサービスを使用すると、要求元のシステムは、統一された事前定義されたステートレス操作のセットを使用して、Webリソースのテキスト表現にアクセスして操作できます。

それが何を意味するのかをわかりやすく説明しましょう(完全なフォームを入手できれば幸いです)。RESTは基本的に、クライアントとサーバー間の通信に関する一連のルールです。RESTの定義にはいくつかの制約があります。

  1. クライアントサーバーアーキテクチャ:ウェブサイト/アプリのユーザーインターフェースをデータリクエスト/ストレージから分離して、各部分を個別にスケーリングできるようにする必要があります。
  2. ステートレス:通信では、サーバーにクライアントコンテキストを保存しないでください。つまり、サーバーへの各要求は必要なすべてのデータを使用して行う必要があり、サーバーに以前の要求からのデータがある場合は想定しないでください。
  3. 階層化システム:クライアントは、サーバーと直接通信しているか、何らかの仲介者と通信しているかを判断できないようにする必要があります。これらの中間サーバー(プロキシサーバーまたはロードバランサー)は、基盤となるサーバーのスケーラビリティとセキュリティを可能にします。

さて、RESTfulサービスとは何かがわかったので、見出しで使用されている用語のいくつかを次に示します。

  1. RESTクライアント:これらのRESTサービスにアクセスできるコードまたはアプリ。あなたは今それを使っています!はい、ブラウザは制御されていないRESTクライアントとして機能できます(Webサイトがブラウザの要求を処理します)。ブラウザは長い間、すべてのRESTリクエストにXMLHttpRequestと呼ばれる組み込み関数を使用していました。しかし、これはFetchAPIによって成功しました。これは、要求に対する最新の約束ベースのアプローチです。他の例としては、axios、superagent、gotなどのコードライブラリ、Postman(またはオンラインバージョン、postwoman!)などの専用アプリ、cURL!などのコマンドラインツールがあります。
  2. RESTサービス:サーバー。NodeJS用のExpressJSやPython用のDjangoなど、これらのサーバーの作成を簡単にする人気のあるライブラリがたくさんあります。
  3. REST API:これは、サーバーへのデータへのアクセス/送信を許可されるエンドポイントとメソッドを定義します。これについては、以下で詳しく説明します。これに代わる他の方法は、GraphQL、JSON-Pure、oDataです。

では、RESTはどのように見えるのでしょうか。

非常に大まかに言えば、サーバーに特定のデータを要求するか、一部のデータを保存するように要求すると、サーバーは要求に応答します。

プログラミング用語では、サーバーがリクエストの取得を待機しているエンドポイント(URL)があります。そのエンドポイントに接続して、私たちに関するデータを送信し(RESTはステートレスであり、要求に関するデータは保存されないことを忘れないでください)、サーバーは正しい応答で応答します。

言葉がつまらないので、デモンストレーションをさせてください。Postmanを使用して、リクエストとレスポンスを表示します。

返されるデータはJSON(JavaScript Object Notation)であり、直接アクセスできます。

Here, //official-joke-api.appspot.com/random_joke is called an endpoint of an API. There will be a server listening on that endpoint for requests like the one we made.

Anatomy of REST:

Alright, so now we know that data can be requested by the client and the server will respond appropriately. Let's look deeper into how a request is formed.

  1. Endpoint: I have already told you about this. For a refresher, it is the URL where the REST Server is listening.
  2. Method: Earlier, I wrote that you can either request data or modify it, but how will the server know what kind of operation the client wants to perform? REST implements multiple 'methods' for different types of request, the following are most popular:

    - GET: Get resource from the server.

    - POST: Create resource to the server.

    - PATCH or PUT: Update existing resource on the server.

    - DELETE: Delete existing resource from the server.

  3. Headers: The additional details provided for communication between client and server (remember, REST is stateless). Some of the common headers are:

    Request:

    - host: the IP of client (or from where request originated)

    - accept-language: language understandable by the client

    - user-agent: data about client, operating system and vendor

    Response:

    - status: the status of request or HTTP code.

    - content-type: type of resource sent by server.

    - set-cookie: sets cookies by server

  4. Data: (also called body or message) contains info you want to send to the server.

Enough with the details – show me the code.

Let's begin coding a REST Service in Node. We will be implementing all the things we learnt above. We will also be using ES6+ to write our service in.

Make sure you have Node.JS installed and node and npm are available in your path. I will be using Node 12.16.2 and NPM 6.14.4.

Create a directory rest-service-node and cd into it:

mkdir rest-service-node cd rest-service-node

Initialize the node project:

npm init -y

The -y flag skips all the questions. If you want to fill in the whole questionnaire, just run npm init.

Let's install some packages. We will be using the ExpressJS framework for developing the REST Server. Run the following command to install it:

npm install --save express body-parser

What's body-parser there for? Express, by default, is incapable of handling data sent via POST request as JSON. body-parser allows Express to overcome this.

Create a file called server.js and add the following code:

const express = require("express"); const bodyParser = require("body-parser"); const app = express(); app.use(bodyParser.json()); app.listen(5000, () => { console.log(`Server is running on port 5000.`); }); 

The first two lines are importing Express and body-parser.

Third line initializes the Express server and sets it to a variable called app.

The line, app.use(bodyParser.json()); initializes the body-parser plugin.

Finally, we are setting our server to listen on port 5000 for requests.

Getting data from the REST Server:

To get data from a server, we need a GET request. Add the following code before app.listen:

const sayHi = (req, res) => { res.send("Hi!"); }; app.get("/", sayHi);

We have created a function sayHi which takes two parameters req and res (I will explain later) and sends a 'Hi!' as response.

app.get() takes two parameters, the route path and function to call when the path is requested by the client. So, the last line translates to: Hey server, listen for requests on the '/' (think homepage) and call the sayHi function if a request is made.

app.get also gives us a request object containing all the data sent by the client and a response object which contains all the methods with which we can respond to the client. Though these are accessible as function parameters, the general naming convention suggests we name them res for response and req for request.

Enough chatter. Let's fire up the server! Run the following server:

node server.js

If everything is successful, you should see a message on console saying: Server is running on port 5000.

Note: You can change the port to whatever number you want.

Open up your browser and navigate to //localhost:5000/ and you should see something like this:

There you go! Your first GET request was successful!

Sending data to REST Server:

As we have discussed earlier, let's setup how we can implement a POST request into our server. We will be sending in two numbers and the server will return the sum of the numbers. Add this new method below the app.get :

app.post("/add", (req, res) => { const { a, b } = req.body; res.send(`The sum is: ${a + b}`); });

Here, we will be sending the data in JSON format, like this:

{ "a":5, "b":10 }

Let's get over the code:

On line 1, we are invoking the .post() method of ExpressJS, which allows the server to listen for POST requests. This function takes in the same parameters as the .get() method. The route that we are passing is /add, so one can access the endpoint as //your-ip-address:port/add or in our case localhost:5000/add. We are inlining our function instead of writing a function elsewhere.

On line 2, we have used a bit of ES6 syntax, namely, object destructuring. Whatever data we send via the request gets stored and is available in the body of the req object. So essentially, we could've replaced line 2 with something like:

const num1 = req.body.a; const num2 = req.body.b;

On line 3, we are using the send() function of the res object to send the result of the sum. Again, we are using template literals from ES6. Now to test it (using Postman):

So we have sent the data 5 and 10 as a and b using them as the body. Postman attaches this data to the request and sends it. When the server receives the request, it can parse the data from req.body , as we did in the code above. The result is shown below.

Alright, the final code:

const express = require("express"); const bodyParser = require("body-parser"); const app = express(); app.use(bodyParser.json()); const sayHi = (req, res) => { res.send("Hi!"); }; app.get("/", sayHi); app.post("/add", (req, res) => { const { a, b } = req.body; res.send(`The sum is: ${a + b}`); }); app.listen(5000, () => { console.log(`Server is running on port 5000.`); }); 

REST Client:

Okay, we have created a server, but how do we access it from our website or webapp? Here the REST client libraries will come in handy.

We will be building a webpage which will contain a form, where you can enter two numbers and we will display the result. Let's start.

First, let's change the server.js a bit:

const path = require("path"); const express = require("express"); const bodyParser = require("body-parser"); const app = express(); app.use(bodyParser.json()); app.get("/", (req, res) => { res.sendFile(path.join(__dirname, "index.html")); }); app.post("/add", (req, res) => { const { a, b } = req.body; res.send({ result: parseInt(a) + parseInt(b) }); }); app.listen(5000, () => { console.log(`Server is running on port 5000.`); }); 

We imported a new package path, which is provided by Node, to manipulate path cross-platform. Next we changed the GET request on '/' and use another function available in res, ie. sendFile, which allows us to send any type of file as response. So, whenever a person tries to navigate to '/', they will get our index.html page.

Finally, we changed our app.post function to return the sum as JSON and convert both a and b to integers.

Let's create an html page, I will call it index.html, with some basic styling:

     REST Client   * { margin: 0; padding: 0; box-sizing: border-box; } .container { height: 100vh; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; display: flex; flex-direction: column; justify-content: center; align-items: center; } form { display: flex; flex-direction: column; margin-bottom: 20px; } label, input[type="submit"] { margin-top: 20px; } 

Simple POST Form

Number 1: Number 2: Click Add!

Let's add a script tag just before the closing body tag, so we don't need to maintain a .js file. We will begin by listening for the submit event and call a function accordingly:

 document.addEventListener("submit", sendData); 

First we need to prevent page refresh when the 'Add' button is clicked. This can be done using the preventDefault() function. Then, we will get the value of the inputs at that instant:

function sendData(e) { e.preventDefault(); const a = document.querySelector("#num1").value; const b = document.querySelector("#num2").value; }

Now we will make the call to the server with both these values a and b. We will be using the Fetch API, built-in to every browser for this.

Fetch takes in two inputs, the URL endpoint and a JSON request object and returns a Promise. Explaining them here will be out-of-bounds here, so I'll leave that for you.

Continue inside the sendData() function:

fetch("/add", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify({ a: parseInt(a), b: parseInt(b) }) }) .then(res => res.json()) .then(data => { const { result } = data; document.querySelector( ".result" ).innerText = `The sum is: ${result}`; }) .catch(err => console.log(err));

First we are passing the relative URL of the endpoint as the first parameter to fetch. Next, we are passing an object which contains the method we want Fetch to use for the request, which is POST in this case.

We are also passing headers, which will provide information about the type of data we are sending (content-type) and the type of data we accept as response (accept).

Next we pass body. Remember we typed the data as JSON while using Postman? We're doing kind of a similar thing here. Since express deals with string as input and processes it according to content-type provided, we need to convert our JSON payload into string. We do that with JSON.stringify(). We're being a little extra cautious and parsing the input into integers, so it doesn't mess up our server (since we haven't implemented any data-type checking).

Finally, if the promise (returned by fetch) resolves, we will get that response and convert it into JSON. After that, we will get the result from the data key returned by the response. Then we are simply displaying the result on the screen.

At the end, if the promise is rejected, we will display the error message on the console.

Here's the final code for index.html:

     REST Client   * { margin: 0; padding: 0; box-sizing: border-box; } .container { height: 100vh; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; display: flex; flex-direction: column; justify-content: center; align-items: center; } form { display: flex; flex-direction: column; margin-bottom: 20px; } label, input[type="submit"] { margin-top: 20px; } 

Simple POST Form

Number 1: Number 2: Click Add! document.addEventListener("submit", sendData); function sendData(e) { e.preventDefault(); const a = document.querySelector("#num1").value; const b = document.querySelector("#num2").value; fetch("/add", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify({ a: parseInt(a), b: parseInt(b) }) }) .then(res => res.json()) .then(data => { const { result } = data; document.querySelector( ".result" ).innerText = `The sum is: ${result}`; }) .catch(err => console.log(err)); }

I have spun up a little app on glitch for you to test.

Conclusion:

So in this post, we learnt about REST architecture and the anatomy of REST requests. We worked our way through by creating a simple REST Server that serves GET and POST requests and built a simple webpage that uses a REST Client to display the sum of two numbers.

You can extend this for the remaining types of requests and even implement a full featured back-end CRUD app.

I hope you have learned something from this. If you have any questions, feel free to reach out to me over twitter! Happy Coding!