LoginSignup
12
12

More than 1 year has passed since last update.

node.js + express + sqlite3でWebAPI(CRUD)を作る

Last updated at Posted at 2021-07-17

node.js + express + sqlite3でWebAPIを作るニーズがあったのでメモ。

準備

場所の作成と必要モジュールインストール。実装ファイル生成。

cd
mkdir node-api-test
cd node-api-test

npm init -y

npm install express
npm install sqlite3

touch index.js

実装

淡々と実装。

知っておいた方がいいこと

sqlite3ではinsertしたりupdateしたIDをthis.lastIDやthis.changesで取得することができるが、this.*という構文はラムダ関数の中では利用できません。幸いなことに?const stmt = db.prepare();を利用すると、stmt.lastID, stmt.changesで取得できるようになるので、冗長とはなりますが、stmt.prepare()を利用しています。

最適な書き方は引き続き模索中。今後変えるかも。

index.js
const express = require("express");
const app = express();

//POSTできたりするように(おまじない)
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

//sqlite3関連設定
const sqlite3 = require("sqlite3");
const db = new sqlite3.Database("./test.db", (err) => {
    if (err) {
        console.error("database error: " + err.message);
    } else {
        db.serialize(() => {
            //都度table削除(あれば)
            db.run("drop table if exists members");
            //table生成(無ければ)
            db.run("create table if not exists members( \
                id integer primary key autoincrement, \
                name nverchar(32), \
                age integer \
            )", (err) => {
                if (err) {
                    console.error("table error: " + err.message);
                } else {
                    //初期データinsert
                    db.run("insert into members(name,age) values(?,?)", "hoge", 11);
                    db.run("insert into members(name,age) values(?,?)", "foo", 22);
                    db.run("insert into members(name,age) values(?,?)", "bar", 33);
                }
            });
        });
    }
});

//リッスン開始
app.listen(3000, () => {
    console.log("Start server on port 3000.");
});

app.get("/", (req, res) => {
    res.send("welcome");
});

//create
app.post("/members", (req, res) => {
    const reqBody = req.body;
    const stmt = db.prepare("insert into members(name,age) values(?,?)"); //lastID取得のため
    stmt.run(reqBody.name, reqBody.age, (err, result) => { //lambda式を使うとthis.lastIDでは取得できない
        if (err) {
            res.status(400).json({
                "status": "error",
                "message": err.message
            });
            return;
        } else {
            res.status(201).json({
                "status": "OK",
                "lastID": stmt.lastID
            });
        }
    });
});

//get members
app.get("/members", (req, res) => {
    db.all("select * from members", [], (err, rows) => {
        if (err) {
            res.status(400).json({
                "status": "error",
                "message": err.message
            });
            return;
        } else {
            res.status(200).json({
                "status": "OK",
                "members": rows
            });
        }
    });
});

//get member
app.get("/members/:id", (req, res) => {
    const id = req.params.id;
    db.get("select * from members where id = ?", id, (err, row) => {
        if (err) {
            res.status(400).json({
                "status": "error",
                "message": err.message
            });
            return;
        } else {
            res.status(200).json({
                "status": "OK",
                "members": row
            });
        }
    })
})

//update member
app.patch("/members", (req, res) => {
    const reqBody = req.body;
    const stmt = db.prepare("update members set name = ?, age = ? where id = ?");
    stmt.run(reqBody.name, reqBody.age, reqBody.id, (err, result) => {
        if (err) {
            res.status(400).json({
                "status": "error",
                "message": err.message
            });
            return;
        } else {
            res.status(200).json({
                "status": "OK",
                "updatedID": stmt.changes
            });
        }
    })
})

//delete member
app.delete("/members/:id", (req, res) => {
    const id = req.params.id;
    const stmt = db.prepare("delete from members where id = ?");
    stmt.run(id, (err, result) => {
        if (err) {
            res.status(400).json({
                "status": "error",
                "message": err.message
            });
            return;
        } else {
            res.status(200).json({
                "status": "OK",
                "deletedID": stmt.changes
            });
        }
    })
})

動作確認

では動作確認をしていきます。APIのテストにはPastmanやVSCodeのプラグインが利用できますが、ここではcurlを利用します。

実行

いつもの。

node index.js

CREATE

挿入。

curl -s -X POST -H "Content-Type: application/json" -d '{"name":"user1","age":"44"}' http://localhost:3000/members

READ(ALL/単体)

取得は全件と単体。全件に関しては実務ではページネーション機能の実装が必要でしょう。

全てを取得

curl -s -X GET http://localhost:3000/members

IDを指定して取得

curl -s -X GET http://localhost:3000/members/1

UPDATE

URLパラメータでIDを指定する方法もあるかと思いますが、ここではmemberオブジェクト全部を投げる。

curl -s -X PATCH -H "Content-Type: application/json" -d '{"id":"1","name":"hoge","age":"99"}' http://localhost:3000/members

DELETE

削除。

curl -s -X DELETE http://localhost:3000/members/1

存在しないIDを投げるとエラーではなく、changesとして0が戻る。

本番環境では

下記が最低限必要です(まあ、そもそもsqlite3を本番で使うことないですが)

  • CORS対応
  • 受け取った値のバリデーション
12
12
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
12
12