Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
54
Help us understand the problem. What is going on with this article?
@donaldchi

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

More than 3 years have passed since last update.

背景

アルバイトで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の試験 [機能の紹介]

54
Help us understand the problem. What is going on with this article?
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
scouty
「あらゆる事象を必然化し、 世の中のミスマッチをなくす」ことをミッションとし、AIヘッドハンティングサービスを開発・運営するスタートアップ

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
54
Help us understand the problem. What is going on with this article?