前回の記事で、「Node.jsとExpressで使ってJSONを扱うAPI」に関する話をしました。
もっと正確にいうなら「Node.js + Expressで、JSON形式のデータをやりとりするAPI」と言ったほうがわかりやすいかもしれません。
JSONのNってnotation、つまり表記法って意味なのでJSON形式っていうと被ってるわけですが、そんなことよりわかりやすいほうが大事なので今後も使っていきます。
さて、そのAPIですが、まずは簡単なのを書いてみます。
const express = require('express');//ここから const app = express(); //データを読み取るために必要 app.use(express.urlencoded({ extended: true })); app.get('/api', (req, res) => { res.json({ message: '掲示板API起動。システムオールグリーン。' }); });//ここまで app.listen(3000, () => { console.log('サーバーがポート3000で稼働中'); });
というわけで今回は以下のところをやっていきます。
//データを読み取るために必要 app.use(express.urlencoded({ extended: true }));
と
app.post('/submit', (req, res) => { const username = req.body.username; // フォームから送信されたデータを取得 console.log(`送信された名前: ${username}`); // サーバー側で確認
と
app.listen(3000, () => { console.log('サーバーがポート3000で稼働中'); });
これをやっていきます。
(※追記
app.post('/submit', (req, res) => {
と平気で書いてますけど、完全に間違っていますね。
app.postじゃなくてapp.getでした。
このあとapp.postの説明をしていますが、そこにapp.getの解説を付け足します。)
まずなんとなく分かるのは、最後のコードではExpressのオブジェクトであるappにlistenというメソッドがあって、それが変数と関数を引数に持って処理をしている、といったところでしょうか。
なので一つずつ見ていきます。
繰り返しになりますが、appはExpressのオブジェクト。
useとは
APIに送られてきたデータを、APIが読めるようにするメソッドです。
useはそれを行ってくれます。
フォームに名前やコメントを書いて送られる形式を「URLエンコード文字列」といいます。
掲示板なんかではわかりませんが、検索をしたときにアドレスバーに見られるあれです。
「name=%E7%A9%BA%E6%9D%A1%E6%89%BF%E5%A4%AA%E9%83%8E
&comment=%E3%82%84%E3%82%8C%E3%82%84%E3%82
%8C%E3%81%A0%E3%81%9C」
掲示板に名前とコメントを書いて送信を押したらこういう形式になって送信されます。
これがURLエンコード文字列です。
HTML作成のとき、送信方法はPOSTにしたから、この文字列は誰にも見られません。
ちなみにこれ、名前は「空条承太郎」、コメントは「やれやれだぜ」です。
さて、このわけのわからない文字列ですが、機械なら読めるのかと思ったら実はそうではなく、サーバーも読めません。
なので翻訳する必要があります。
その翻訳機が
app.use(express.urlencoded({ extended: true }));
ということになります。
これを実行することで、あの意味不明な文字列がJavaScriptのコード、オブジェクトとキーに変換されます。
{ name: "空条承太郎", comment: "やれやれだぜ" }
すごくわかりやすくなりましたね。
そしてJavaScript形式になったわけですから、Node.jsが処理できる形となりました。
Node.jsで処理されたデータは、JSON形式でクライアントに返されることになります。
さて、次です。
app.post('/submit', (req, res)とは
app.post('/submit', (req, res)
とは。
初めてだと、なんかパッと見がわかりづらくなってきて嫌な感じです。
これは処理を実行する条件と、処理を表します。
いちいちスクロールして見に行くのも面倒なので、ここにもう一度コードを書きます。
app.post('/submit', (req, res) => { const username = req.body.username; // フォームから送信されたデータを取得 console.log(`送信された名前: ${username}`); // サーバー側で確認
app.postの中では色々やってるのがわかると思います。
で、この処理の条件がapp.post('/submit', (req, res)です。
指定したURLにPOSTリクエストが来たとき、処理を実行しています。
ここでいう指定したURLは「/submit」です。
これはHTMLを書いたときにformタグのactionの中に書きます。
<form action="/submit" method="post">
こんな感じで。
これはHTMLでは宛先を示し、サーバー側では受け取り口を示します。
なのでどっちとも/submitにしておけばデータが届くというわけです。
ちなみにmethodをpostにしていますが、POSTにしてデータの内容が他者に見られないようにするという意味です。
次に(req, res)の部分です。
app.post('/submit', (req, res) => {}
という形で書かれていますので、コールバック関数だということがわかります。
appはExpressのオブジェクトなので、Expressにreq、resというオブジェクトが用意されていて、それを引数にしていることになります。
reqはフロントから来た情報をまとめたオブジェクト、resはサーバーのデータや処理結果をフロントに送るために操作するオブジェクトです。
reqのメソッドでフロントから来た情報をを見たり操作したりできますし、resはサーバーのデータをJSON形式にして送信したりできます。
(データを送るのは人間だけじゃないので、本来はユーザーではなくクライアントというのが正しいのですが、まあ掲示板を使うのは基本人間でしょうし、とりあえずユーザーと言うことにしておきます。)
(※追記 サーバー(バックエンド)に対してユーザー側をフロントエンド、略してフロントという言い方もします。
そのうちその呼び方の方を多用するようになります。)
たとえば上で書いている
const username = req.body.username;
というのは、ユーザーから送られて来たデータのボディ部分にあるユーザーネームを扱う、という意味になります。
で、私はボディの意味がわからないのでchatGPT先生に教えてもらいました。
データ通信はHTTPというルール(プロトコル)で行われます。
イメージとしては、世界にはいろんな言葉がありますが、「ややこしいので英語でやりとりしよう」と決める感じです。
この英語が、通信の世界ではHTTPと呼ばれます。
HTTPにはヘッダー、ボディ、URLが含まれます。
ヘッダーとはデータのの説明が書かれた部分です。
JSONで書かれているとか、どこから送られてきたデータであるとか、他にも色々情報がありますが、とにかくどういうデータなのかという説明です。
で、ボディはデータの中身です。
メールとかの内容そのものです。
URLはデータの宛先を示しています。
まとめると
- ヘッダー:どんなデータかを説明する部分(例:データの形式がJSONかどうか、送信元の情報など)
- ボディ:実際のデータの内容(たとえば、掲示板の投稿内容や名前など)
- URL:データの送り先(サーバー上のどの処理にデータを渡すか)
こんなかんじです。
さて、話をもどします。
つまり
const username = req.body.username;
というのは、送信されてきたデータのボディ(内容)に書かれているユーザーの名前をusernameという変数に放り込めという意味です。
以降、usernameという変数が出てきたら、それは送られてきたデータにかかれていたユーザーネームということになります。
reqはわかったので、次にresです。
上でも言ったとおり、reqはフロントから来た情報をまとめたオブジェクト、resはサーバーのデータや処理結果をフロントに送るために操作するオブジェクトです。
なのでresを使ったコードはこんな感じ。
res.json({ Jotarou: "てめーは俺を怒らせた" });
おそらく勘のいい人はわかると思いますがresのメソッドに入ってるjsonは、サーバーから受け取ったJavaScript形式のデータをJSON形式にするという意味です。
すぐには分かりづらいですけど、JavaScript形式だと、プロパティに「””(ダブルクォーテーション)」が無いんです
Jotarou:"てめーは俺を怒らせた"
これをJSON形式にすると「””」がつきます
"Jotarou":"てめーは俺を怒らせた"
こうすることで、ただの文字列扱いになりJSON形式になります。
つまり
{ Jotarou:"てめーは俺を怒らせた" };
というJavaScriptの形式が
{ "Jotarou":"てめーは俺を怒らせた" }
となるわけです。
app.get('/submit', (req, res)とは
さて、一番最初に提示したコードが
app.get('/api', (req, res) => {};
だったにもかかわらず、上ではいきなりapp.postの話を初めてしまったので、ここに挿入という形で本編を書きます。
とはいってもpostを勉強したのであれば、さほど難しくはありません。
「データを送るぞ」というPOSTリクエストが来たときの処理か、「データをよこせ」というGETリクエストが来た時の処理の違いですから。
コードはこうでした。
app.get('/api', (req, res) => { res.json({ message: '掲示板API起動。システムオールグリーン。' }); });
postがPOSTリクエストが来た時の処理で、getはGETリクエストが来た時の処理になります。
resもreqも上で書いてますので、res.json()の説明をすればいいということになりますね。
res.json()とは
res.json()とは、サーバーからのデータをJSON形式にしてHTTPレスポンスとしてユーザー(クライアント)に送るメソッドです。
上述の通り、resはサーバーからのデータを扱うときに使うオブジェクトで、expressで用意されています。
この中にあるメソッドの一つであるjson()がデータをJSON形式にします。
HTTPレスポンスというのは、データの一式です。
ヘッダーやらHTMLタグやらの情報も含めたものです。
これがHTTPレスポンスでなければ、文字コードが判別できず文字化けしてしまう事態になります。
listenとは
listenはサーバーを起動するメソッドになります。
これを呼ばないと、サーバーがあっても待ち受け状態にならないのでただのでかい文鎮以外の役割を果たしてくれません。
ポートが3000番であればサーバーが起動して待ち受け状態になります。
起動したらコールバック関数が処理されます。
そうやってAPIとして機能します。
コールバック関数の説明はこちら。
さて、またわからない言葉が出てきました。
ポートってなんなんですかね。
なんとなく聞いたことがあるようにも思います。
なんかインターネットの接続がおかしいときとか、Q&Aとか見たら「ポートをどうこうしろ」みたいなのが出てきたように思います。
簡単にいうと、ポートとは部屋番号みたいなものです。
IPアドレスで住所を指定して、ポートで部屋番号を指定。
Node.jsでは慣習的に3000番を使います。
もちろん変更することもできます。
IPアドレスとポート番号で、リクエストを送る先を指定するわけです。
つまり上のコードは「3000番のポートを開けて、そこにリクエストが来たらコールバック関数の処理(console.log("サーバーがポート3000で稼働中")を行う、という意味になります。
さて、これでAPIの作り方はわかりました。
APIがやってることは以下のような感じです。
- Node.jsでExpressを立ち上げる
- URLエンコード文字列を受け取ってJavaScript形式にする
- Node.jsで処理をする
- 以上のことをできるようにしてからサーバーを立ち上げる
とりあえずAPIはこういう機能として作っていくと考えることにします。
※もちろん実際の手順としては、サーバーを立ち上げてから操作をしていますが、処理としてはサーバーは待ち受け状態です。
次回は実際にAPIにデータを送ってみましょう。