背景
アルバイトで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) |
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の編集
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の編集
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のような流れで操作すると、結果を確認することができます。
備考
私の場合、以下のようなエラーが出ていました。
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の試験 [機能の紹介]