57
60

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Node.js + Express + mysqlを使った簡単な RESTful API デモ

Last updated at Posted at 2017-05-27

#背景
アルバイトでbitflyer apiを叩いてbitcoinトレードをするアプリを作ることになりました。その表現の仕方として、RESTful APIの形にすることになったので、グーグル先生に聞きながら作っていたサンプルコードをポスティングします。

本プログラムは、主に以下の文章を参照に作りました。
RESTful API Using Node and Express 4

#概略
このサンプルコードは、Node.jsとExpressを使って、mysqlとやりとりをし、その結果をjson形式で返すような簡単なREST apiです。

#具体的な内容
1).データベースの設計

データベース名: Test, table名 : users

カーラム名 タイプ
id INT(70)
email VARCHAR(45)
password VARCHAR(45)
created_date TIMESTAMP

コマンド:

create database Test;
use Test;
CREATE TABLE IF NOT EXISTS `users` (
  `id` INT(70) NOT NULL AUTO_INCREMENT,
  `email` VARCHAR(45) NOT NULL,
  `password` VARCHAR(45) NULL,
  `created_date` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `email_UNIQUE` (`email` ASC))
ENGINE = InnoDB;

2). api一覧

api タイプ 説明
/users/create POST 新しいユーザーの作成
/users GET ユーザーリストの取得
/users/:id GET 特定ユーザー情報の取得
/users/:password/:email PUT ユーザー情報の更新
/users/:email DELETE ユーザー情報の削除
/users/validate/:id/:email GET ユーザー認証結果の取得

3). プロジェックトの作成とpackage.jsonファイルの修正、インストール

プロジェックトの作成

 create RESTDemo
 cd RESTDemo
 npm init 

これまでのプロジックトファイル構成
RESTDemo
|--- Server.js
|--- REST.js
|--- package.json
|--- node_modules (npm installした時に、生成されたdependencyファイル)

package.jsonの修正

{
  "name": "restdemo",
  "version": "0.0.1",
  "scripts": {
    "start": "node Server.js"
  },
  "dependencies": {
    "express": "~4.12.2",
    "mysql": "~2.5.5",
    "body-parser": "~1.12.0",
    "MD5": "~1.2.1", 
    "request": "~2.81.0"
  }
}

dependenciesのインストール

npm install

4). プログラムの入り口としてのServer.jsの編集

Server.js
var express = require("express");
var mysql   = require("mysql");
var bodyParser  = require("body-parser");
var md5 = require('MD5');
var rest = require("./REST.js");
var app  = express();

function REST(){
    var self = this;
    self.connectMysql();
};

REST.prototype.connectMysql = function() {
    var self = this;
    var pool      =    mysql.createPool({
        connectionLimit : 100,
        host     : 'localhost',
        user     : 'db user name',
        password : 'db password',
        database : 'Test',
        debug    :  false
    });
    pool.getConnection(function(err,connection){
        if(err) {
          self.stop(err);
        } else {
          self.configureExpress(connection);
        }
    });
}

REST.prototype.configureExpress = function(connection) {
      var self = this;
      app.use(bodyParser.urlencoded({ extended: true }));
      app.use(bodyParser.json());
      var router = express.Router();
      app.use('/api', router);
      var rest_router = new rest(router,connection,md5);
      self.startServer();
}

REST.prototype.startServer = function() {
      app.listen(3000,function(){
          console.log("サーバ起動中... ポート: 3000");
      });
}

REST.prototype.stop = function(err) {
    process.exit(1);
}

new REST();

5). 各種リクエストをhandlerとしてのREST.jsの編集

REST.js
var mysql = require("mysql");

var request = require('request');
var crypto = require('crypto');

var timestamp = Date.now().toString();

function REST_ROUTER(router,connection,md5) {
    var self = this;
    self.handleRoutes(router,connection,md5);
}

REST_ROUTER.prototype.handleRoutes= function(router,connection,md5) {
    router.get("/",function(req,res){
        res.json({"Message" : "NodeJS REST API Demo"});
    });

    //====================================
    //
    //			   Operate Users
    //
    //====================================
    //create user, POST request
    router.post("/users/create",function(req,res){
        var query = "INSERT INTO ??(??,??) VALUES (?,?)";
        var table = ["users","email","password",req.body.email,md5(req.body.password)];
        query = mysql.format(query,table);
        connection.query(query,function(err,rows){
            if(err) {
                res.json({"Error" : true, "Message" : "Error executing MySQL query"});
            } else {
                res.json({"Error" : false, "Message" : "User created !"});
            }
        });
    });

    //show user list, GET request
    router.get("/users",function(req,res){
        var query = "SELECT * FROM ??";
        var table = ["users"];
        query = mysql.format(query,table);
        connection.query(query,function(err,rows){
            if(err) {
                res.json({"Error" : true, "Message" : "Error executing MySQL query"});
            } else {
                res.json({"Error" : false, "Message" : "Success", "Users" : rows});
            }
        });
    });
    
    //show specific user, GET request
    router.get("/users/:id",function(req,res){
        var query = "SELECT * FROM ?? WHERE ??=?";
        var table = ["users","id",req.params.id];
        query = mysql.format(query,table);
        connection.query(query,function(err,rows){
            if(err) {
                res.json({"Error" : true, "Message" : "Error executing MySQL query"});
            } else {
                res.json({"Error" : false, "Message" : "Success", "Users" : rows});
            }
        });
    });
    
    //update uses, PUT request
    router.put("/users",function(req,res){
        var query = "UPDATE ?? SET ?? = ? WHERE ?? = ?";
        var table = ["users","password",md5(req.body.password),"email",req.body.email];
        query = mysql.format(query,table);
        connection.query(query,function(err,rows){
            if(err) {
                res.json({"Error" : true, "Message" : "Error executing MySQL query"});
            } else {
                res.json({"Error" : false, "Message" : "Updated the password for email "+req.body.email});
            }
        });
    });
    
    //delete users, DELETE request
    router.delete("/users/:email",function(req,res){
        var query = "DELETE from ?? WHERE ??=?";
        var table = ["users","email",req.params.email];
        query = mysql.format(query,table);
        connection.query(query,function(err,rows){
            if(err) {
                res.json({"Error" : true, "Message" : "Error executing MySQL query"});
            } else {
                res.json({"Error" : false, "Message" : "Deleted the user with email "+req.params.email});
            }
        });
    });
    
    //validate users by id and email, GET request
    router.get("/users/validate/:id/:email",function(req,res){
		var query = "SELECT * FROM ?? WHERE ??=? and ??=?";
        var table = ["users","email",req.params.email,"id", req.params.id];
        query = mysql.format(query,table);
        connection.query(query,function(err,rows){
            if(err) {
                res.json({"Error" : true, "Message" : "Error executing MySQL query!"});
            } else {
            	if (rows=="") {
                	res.json({"Error" : true, "Message" : "User not exist!"});
               	} else {
               		res.json({"Error" : true, "Message" : "OK", "token" : rows[0]["user_password"]});
                }
            }
        });
    });
}

module.exports = REST_ROUTER;

#実行結果の確認
API機能確認のツールとして、POSTMANというソフトがよく使われるようです。今回このツールを使って実行結果を確認します。

POSTMANの使い方は簡単なので、詳しい紹介は省略します。

今回のデモプログラムに対して、以下の図のようなpostmanのUI上、

1. 一番目の枠でapiのrequestタイプを選択 (get, post, put, deleteなど)
2. 二番目の枠にapiのurlを入力
3. post タイプの場合, 三番目の枠にパラメータのkeyとvalueを入力
4. 四番目の枠で出力タイプを選択 (JSON, XMLなど)
5. Sendボータンを押すと四番目の枠で結果が出力される

1~5のような流れで操作すると、結果を確認することができます。

postman.png

#備考

私の場合、以下のようなエラーが出ていました。

###Error:

events.js:161
      throw er; // Unhandled 'error' event
      ^

Error: listen EADDRINUSE :::3000
    at Object.exports._errnoException (util.js:1023:11)
    at exports._exceptionWithHostPort (util.js:1046:20)
    at Server._listen2 (net.js:1261:14)
    at listen (net.js:1297:10)
    at Server.listen (net.js:1375:9)
    at Function.app.listen (/Users/chi/qiita-blog/RESTDemo/node_modules/express/lib/application.js:595:24)
    at REST.startServer (/Users/chi/qiita-blog/RESTDemo/Server.js:43:11)
    at REST.configureExpress (/Users/chi/qiita-blog/RESTDemo/Server.js:39:12)
    at /Users/chi/qiita-blog/RESTDemo/Server.js:27:16
    at Handshake.onConnect [as _callback] (/Users/chi/qiita-blog/RESTDemo/node_modules/mysql/lib/Pool.js:59:7)

###原因:
ポート3000がすでに使われている。
###解決策:
node.js起動時エラー : Error: listen EADDRINUSE

#コード
以下のURLからソースコードがダウンロードできます。
デモソースコード

#参考
RESTful API Using Node and Express 4
Mac へ MySQL を Homebrew でインストールする手順
nvm + Node.js + npmのインストール
Node.jsとnpmをアップデートする方法
[ツール] Postmanを利用したAPIの試験 [機能の紹介]

57
60
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
57
60

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?