Help us understand the problem. What is going on with this article?

Node.js + ExpressでREST API開発を体験しよう[作成編]

More than 3 years have passed since last update.

はじめに

本内容は、Node.js + Expressを使って、簡単なAPIを実際に作ってみる手順になります。
環境の準備が出来ていない場合は、以下を参照してください。

Node.js + ExpressでREST API開発を体験しよう for Windows[準備編]

上記ページで「myapp」というプロジェクトを作成している前提で話を進めます。

推奨の道具

用意しなくても出来るけど、あると便利です。

Chrome

  • ブラウザ。
  • 今回は以下の拡張機能を使うので、Chromeにしています。

Advanced REST client

https://goo.gl/nukPy0

  • Chromeの拡張機能。
  • 各種HTTPリクエストを送信できる。
  • 他にも似たようなツールがあるのでお好みで。

JSON Formatter

https://goo.gl/F7RWXP

  • Chromeの拡張機能。
  • ブラウザでJSONデータを表示する時、見易く整形してくれる。
  • 他にも似たようなツールがあるのでお好みで。

API作成

まずは、何も考えずにAPIを作ってみましょう。
2ステップで出来ます。

ステップ1
./myapp/app.jsを開いて、以下の2行を追記します。

app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var index = require('./routes/index');
var users = require('./routes/users');
var samples = require('./routes/samples');                        // ★★★★★ 追記箇所1 ★★★★★

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);
app.use('/users', users);
app.use('/samples', samples);                                     // ★★★★★ 追記箇所2 ★★★★★

//(以下略)

ステップ2

./myapp/routesフォルダに、samples.jsというファイルを作成して、以下の内容を貼り付けます。

samples.js
var express = require('express');
var router = express.Router();

/* サンプルAPI① 
 * http://localhost:3000/samples にGETメソッドのリクエストを投げると、
 * JSON形式で文字列を返す。
 */
router.get('/', function(req, res, next) {
  var param = {"":"これはサンプルAPIです"};
  res.header('Content-Type', 'application/json; charset=utf-8')
  res.send(param);
});

/* サンプルAPI② 
 * http://localhost:3000/samples/hello にGETメソッドのリクエストを投げると、
 * JSON形式で文字列を返す。
 */
router.get('/hello', function(req, res, next) {
  var param = {"result":"Hello World !"};
  res.header('Content-Type', 'application/json; charset=utf-8')
  res.send(param);
});

module.exports = router;

実行
これでAPIは完成です。
npm startでmyappアプリを起動して、今回作成した2つのAPIにGETメソッドのリクエストを送ってみましょう。
以下のような結果になると思います。

サンプルAPI①
http://localhost:3000/samples

結果
{
"値": "これはサンプルAPIです"
}

サンプルAPI②
http://localhost:3000/samples/hello

結果
{
"result": "Hello World !"
}

このサンプルで何となく分かると思いますが、仕組みはシンプルです。
app.jsの「追記箇所2」で、アプリに送られてきたリクエストの振り分け先と、具体的な処理が書いてあるファイルの在り処を設定しています。今回は、ファイルの在り処は「追記箇所1」で設定しています。(拡張子*.jsは省略)

具体的な処理が書いてあるsamples.jsには、/samples/samples/helloの2つのAPIの処理が書いてあります。

以下に、もう少し詳しい解説をします。

解説

構成ファイルの概要

myappアプリのプロジェクトフォルダの構成ファイルの説明です。
色々ファイルがありますが、今回使うのは app.jsファイル と、routesフォルダ配下に置くファイル だけです。

myapp
│  app.js            // アプリのメインファイル。各種宣言やミドルウェア関数(後述)へのルーティング情報(後述)を記載する。
│  package.json      // アプリに必要なNode.jsのパッケージ情報等を記載する。
│  
├─bin
│      www           // アプリの起動に関わる情報が記載されている。基本的に触らなくて良い。
│      
├─node_modules       // アプリに必要なNode.jsのパッケージ置き場。
│  ├─(中略)
│          
├─public             // 静的ファイル置き場。Webアプリ開発では使うが、API開発では使わない。
│  ├─images
│  ├─javascripts
│  └─stylesheets
│          style.css
│          
├─routes             // ミドルウェア関数が書かれいているファイル置き場。
│      index.js
│      users.js
│      
└─views              // HTMLのテンプレートファイル置き場。Webアプリ開発では使うが、API開発では使わない。
        error.jade
        index.jade
        layout.jade

app.jsの説明

アプリのメインファイルであるapp.js(デフォルト状態)の内容です。
※ Express Ver.4.14.0時点

app.js
var express = require('express');                   // requireで使用するNode.jsパッケージをインスタンス化。
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var index = require('./routes/index');              // requireで、使用するミドルウェア(後述)をセット。
var users = require('./routes/users');

var app = express();                                // Expressのサーバ生成処理を app にセット。

// view engine setup                                // HTMLテンプレートエンジンのセット。
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));                             // 先頭で定義したNode.jsパッケージのインスタンスを使って、各種処理を設定。
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);                                // ルーティング(後述)の設定。
app.use('/users', users);

// catch 404 and forward to error handler           // ルーティングで該当先が無かったら、404画面を表示するミドルウェア。
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler                                    // エラーが発生したら、500画面を表示するミドルウェア。
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

コメントで簡単に説明しましたが、今回のAPI開発で関わるのはルーティングミドルウェアの部分です。

ルーティング

ルーティングとは

ルーティング とは、アプリケーション・エンドポイント (URI) と、クライアント要求に対するそれらの応答の定義のことです。

引用:http://expressjs.com/ja/guide/routing.html

例えば、http://localhost:3000/hogeにリクエストが来たら、○○という処理をしましょう」といった具合に定義する部分の事です。

アプリのルーティング設定

今回のmyappアプリでルーティングを定義しているのは、app.jsの以下の部分です。

app.js
app.use('/', index);                                // ルーティング(後述)の設定。
app.use('/users', users);

ここで、'/'(http://localhost:3000/ )にアクセスしたらindexに誘導して、'/users'(http://localhost:3000/users )にアクセスしたら、usersに誘導するように設定されています。

この時の、indexusersは何を指しているかというと、ミドルウェアが書かれているファイルになります。

app.js
var index = require('./routes/index');              // requireで、使用するミドルウェア(後述)をセット。
var users = require('./routes/users');

ミドルウェア

ミドルウェアとは

ミドルウェアとは、簡単に言うとルーティングで振り分けた先の処理の事です。

今回のmyappアプリで言うと、routesフォルダ配下のindex.jsusers.jsに中に書かれています。
サンプルとして、http://localhost:3000/users にアクセスしたら誘導される、users.jsを見てみましょう。

users.js
var express = require('express');
var router = express.Router();

/* GET users listing. */
router.get('/', function(req, res, next) {
  res.send('respond with a resource');
});

module.exports = router;

この、router.get(・・・)の部分が、GETメソッドのリクエストを処理する、1つのミドルウェアです。
第一引数の'/'は、http://localhost:3000/users 以降のパスを意味しています。
第二引数のミドルウェア関数は特に処理は無く、res.send('respond with a resource');で、リクエストに対して'respond with a resource'という文字列をレスポンスとして返しています。

image11.png

ミドルウェア関数とは

ミドルウェア 関数は、要求オブジェクト (req)、応答オブジェクト (res)、およびアプリケーションの要求応答サイクルにおける次のミドルウェア関数に対するアクセス権限を持つ関数です。

引用:http://expressjs.com/ja/guide/using-middleware.html

要するに、クライアントからのリクエスト関係の情報一式と、クライアントへ返すレスポンス関係一式と、必要であれば進む次の処理を操作できる関数の事です。

ミドルウェア
router.get('/', function(req, res, next) {
  res.send('respond with a resource');
});

上記のソースを簡単に説明すると、以下の通りです。

router.get(・・・)

  • ミドルウェア関数が適用される HTTP メソッドで、この例はGETメソッド。

router.getの第一引数の'/'

  • ミドルウェア関数が適用されるパス (ルート)。
  • もし'/hoge'だと、http://localhost:3000/hoge にリクエストが来たら、この処理に誘導します。

router.getの第二引数のfunction(req, res, next) {・・・}

  • ミドルウェア関数。
  • リクエストを受けて、具体的に何をするかここに書きます。

ミドルウェア関数function(req, res, next)については以下の通りです。

第一引数のreq

  • ミドルウェア関数への HTTP 要求引数。
  • この中に、リクエストに関する様々な情報(クエリストリング、エンドポイント、etc)がセットされている。

第二引数のres

  • ミドルウェア関数への HTTP 応答引数。
  • この中に、レスポンスに関する様々な情報(各種ヘッダー、ペイロード、etc)がセットされている。

第三引数のnext

  • ミドルウェア関数へのコールバック引数。
  • 簡単に言うと、nextがあると、処理が終わると次のミドルウェアに進みます。無ければ終了。
  • 「次のミドルウェア」というのは、今のミドルウェア以降に記述されているミドルウェアです。(ソースは上から順番に読まれます。)

引用:http://expressjs.com/ja/guide/writing-middleware.html

続・API作成

それでは、色々なAPIを作成してみましょう。

URIにパラメータをセットするAPI

http://localhost:3000/hoge/(任意の値)のように、URIにパラメータをセットできるAPIのサンプルになります。
./myapp/routes/samples.jsに、以下の内容を貼り付けて、mayappアプリを起動してみてください。

samples.js
var express = require('express');
var router = express.Router();

// (中略)

/* サンプルAPI③ 
 * http://localhost:3000/samples/hello/(任意の文字列) にGETメソッドのリクエストを投げると、
 * JSON形式で(任意の文字列)を返す。
 */
router.get('/hello/:place', function (req, res, next) {
  var param = {"result":"Hello "+ req.params.place + " !"};      // レスポンスで返す値。JSON形式。
  res.header('Content-Type', 'application/json; charset=utf-8')  // 「レスポンスはJSON形式で返すよ」の意味
  res.send(param);                                               // 「レスポンス送るよ」の意味
});

module.exports = router;

任意のパラメータをセットして、リクエストを投げます。
http://localhost:3000/samples/hello/博多

結果
{
"result": "Hello 博多 !"
}

URIにクエリストリングをセットするAPI

http://localhost:3000/hoge?q=(任意の値)のように、URIにクエリストリングセットできるAPIのサンプルになります。
./myapp/routes/samples.jsに、先程貼り付けたソースを以下のように修正して、mayappアプリを起動してみてください。

samples.js
var express = require('express');
var router = express.Router();

// (中略)

/* サンプルAPI③ 
 * http://localhost:3000/samples/hello/(任意の文字列) にGETメソッドのリクエストを投げると、
 * JSON形式で(任意の文字列)を返す。
 */
router.get('/hello/:place', function (req, res, next) {
  // var param = {"result":"Hello "+ req.params.place + " !"};                          // ← ★★ 削除 ★★
  var param = {"result":"Hello "+ req.params.place + " !","shop name":req.query.shop};  // ← ★★ 追加 ★★
  res.header('Content-Type', 'application/json; charset=utf-8')
  res.send(param);
});

module.exports = router;

任意のパラメータをセットして、リクエストを投げます。
http://localhost:3000/samples/hello/博多?shop=キャナルシティ

結果
{
"result": "Hello 博多 !",
"shop name": "キャナルシティ"
}

POSTメソッドのリクエストを受けるAPI

POSTメソッドを受けるAPIのサンプルになります。
./myapp/routes/samples.jsに、先程貼り付けたソースを以下のように修正して、mayappアプリを起動してみてください。

samples.js
var express = require('express');
var router = express.Router();

// (中略)

/* サンプルAPI④ 
 * http://localhost:3000/samples にPOSTメソッドのリクエストを投げると、
 * JSON形式で文字列を返す。
 */
router.post('/', function(req, res, next) {
  var param = {"":"POSTメソッドのリクエストを受け付けました","bodyの値":req.body.card};
  res.header('Content-Type', 'application/json; charset=utf-8')
  res.send(param);
});

module.exports = router;

JSON形式のペイロードに"card"というパラメータをセットして、POSTメソッドのリクエストを投げます。
ブラウザではPOSTメソッドのリクエストは投げられないので、最初に紹介したブラウザ拡張機能や、cURLコマンドを使用しましょう。

http://localhost:3000/samples
{"card":"よかネットカード"}

結果
{
"値": "POSTメソッドのリクエストを受け付けました",
"bodyの値": "よかネットカード"
}

まとめ

このように、Node.js + Expressを使えば、簡単にREST APIを作成する事ができます。

今回紹介したサンプルのような単純のもの以外にも、Node.jsパッケージを追加する事で、高度な処理も手軽に実装する事ができます。
小さなAPIをどんどん肉付けしていって、色々試してみてください。

参考

Express - ガイド
http://expressjs.com/ja/guide/routing.html

Express - APIリファレンス
http://expressjs.com/ja/4x/api.html

tamura_CD
אני מהנדס מערכת.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした