第6章 WEBアプリ開発(バックエンドAPIアプリ)

6-1. HTTPリクエストを検査する curl コマンド
6-2. DB接続クレデンシャル
6-3. バックエンドAPIアプリの設計
6-4. connectDatabase()関数
6-5. closeDatabase(db)関数
6-6. app.get( ‘/get’ ) データ読み込み

フロントWEBアプリとバックエンドAPIアプリをHTTPメソッドで通信します。

6-1. HTTPリクエストを検査する curl コマンド

HTTPリクエスト:GET, PUT, POST, DELETE のコマンドでの呼び出しを参考に、バックエンドAPI機能をテストしながら開発します。ポート番号は自分の環境に合わせること。

$ curl -X GET http://127.0.0.1:3002/get
$ curl -X DELETE http://127.0.0.1:3002/delete/1
$ curl -X PUT http://127.0.0.1:3002/update/1 -H "Content-Type: application/x-www-form-urlencoded"  -d "flag=111&plan=2222&result=33333"
$ curl -X POST http://127.0.0.1:3002/create -H "Content-Type: application/x-www-form-urlencoded" -d "flag=aaaa&plan=bbbbb&result=cccc"

6-2. DB接続クレデンシャル

コードの中にユーザー名やパスワードを記載すると、ログインするためのクレデンシャルが漏洩するリスクがあります。これを防ぐために、コードと環境変数のファイルを分離して記述します。
Node.jsアプリを配置するディレクトリに環境ファイル[.env]を作成、もしくはDBに接続するための環境変数を追加します。

DB_HOST=DBサーバーのドメイン名(もしくはIPアドレス)
DB_USER=データベースに接続するユーザー名
DB_PASS=データベースに接続するユーザーのパスワード
DB_NAME=使うデータベース名

6-3. バックエンドAPIアプリの設計

URIアクセスを待ち受けし、データベースのレコードを読み書きした結果を返す関数を設計します。
ディレクトリ[~/app]に、新しいファイル[app-api.js]を作成します。

// ----------------------------
// 初期設定:モジュール読み込み。変数定義。
// ----------------------------
const express = require("express");                 // Expressモジュール読み込み
const app = express();                              // アプリサーバーとしてインスタンス化
const mysql = require('mysql');                     // MySQLモジュール読み込み
const cors = require('cors');                       // CORS(Cross-Origin Resource Sharing)モジュールを読み込み
const port = 3003;                                  // TCPポート番号を指定
require('dotenv').config();                         //環境変数[~/app/.env]を process.env に代入

// ----------------------------
// `.bashrc` で設定した環境変数からユーザー情報を取得
// ----------------------------

// ----------------------------
// listen()メソッドを実行して3000番台ポートで待ち受け。
// ----------------------------
var server = app.listen(port, function(){
    console.log("Node.js待ち受けポート:" + server.address().port);
});

// ----------------------------
// WEBブラウザは、異なるオリジン(ドメイン)へのアクセスは基本的にブロックする。
// CORS()関数は、リモートサーバーからのPOST, GET, PUT, DELETEメソッドのアクセスを許可する。詳細な制御も可能。
// ----------------------------
//app.use(cors({
//    origin: 'https://example.com',
//    methods: ['GET', 'POST', 'PUT', 'DELETE'],
//    allowedHeaders: ['Content-Type', 'Authorization']
//  }));
//app.use(cors());

// ----------------------------
// フォームデータを解析
// ----------------------------
app.use(express.urlencoded({ extended: true })); // フォーム形式(name=value)
app.use(express.json());                         // JSON形式({ "key": "value" })


// ------------------------------------
// データベースに接続する関数
// ------------------------------------
function connectDatabase() {}

// ------------------------------------
// データベースを閉じる関数
// ------------------------------------
function closeDatabase(db) {}

// ------------------------------------
// データ読み込み
// ------------------------------------
app.get('/get', (req, res) => {});

// ------------------------------------
// データ書き込み
// ------------------------------------
app.post('/create', (req, res) => {});

// ------------------------------------
// データ削除
// ------------------------------------
app.delete('/delete/:id', (req, res) => {});

// ------------------------------------
// データ更新
// ------------------------------------
app.put('/update/:id', (req, res) => {});

// ------------------------------------
// アプリサーバーが応答することを検査
// ------------------------------------
app.get('/', (req, res) => {
    res.send('いえーい');
    console.log('いえーい');
});

CORSモジュールをインストールします(未インストールの場合、エラーが表示されます:Error: Cannot find module ‘cors’)

$ npm install cors

アプリをテストします。

$ node app-api.js
Node.js待ち受けポート:3003

待ち受けポート番号が表示されたら成功です。

ブラウザからアクセスできること

http://ドメイン名:3003/

同じホストの別のシェルからアクセスできること

$ curl -X GET http://localhost:3003/

6-4. connectDatabase()関数

データベースに接続するコードを記述します。データベースを閉じる関数とペアで呼び出します。

function connectDatabase() {
  // MySQLデータベースの接続情報を設定
  const db = mysql.createConnection({
    host: process.env.DB_HOST,
    user: process.env.DB_USER,
    password: process.env.DB_PASS,
    database: process.env.DB_NAME
  });
  // データベースに接続
  db.connect((err) => {
      if (err) throw err;
      console.log('MySQL接続は成功');
  });
  return db;
}

6-5. closeDatabase(db)関数

接続しているデータベース db を指定して閉じます。

function closeDatabase(db) {
  // データベース接続を閉じる
  db.end((err) => {
    if (err) throw err;
    console.log('MySQL接続を閉じました');
  });
}

6-6. app.get( ‘/get’ ) データ読み込み

CURDにおけるデータ操作の基本形は 1. DB接続 2. クエリ実行 3. DB閉じる。
読み出し[SELECT * FROM テーブル]の場合:

app.get('/get', (req, res) => {
  // 1.データベースに接続
  const db = connectDatabase(); 
  // 2.データを読み出すクエリ
  let sql = 'SELECT * FROM todo';
  db.query(sql, (err, results) => {
      if (err) throw err;
      res.json(results);
      // 3.データベースを閉じる
      closeDatabase(db); 
  });
});

アプリをテストします。

$ node app-api.js
Node.js待ち受けポート:3003

待ち受けポート番号が表示されたら成功です。

ブラウザからアクセスできること

http://ドメイン名:3003/

# 読み出したレコードが表示される
[{"id":1,"flag":"0","plan":"テスト","result":"-"}]

同じホストの別のシェルからアクセスできること

$ curl -X GET http://localhost:3003/

6-7. APIとポート番号のプロキシ設定

APIアプリのURL 例えば https://servername.com/app や /login などにアクセスしたときに、ポート番号 http://localhost:3000 などに遷移させる設定

$ sudo nano /etc/nginx/sites-available/ドメイン名(例:web.hogehoge.com)

# APIアプリ用に追加
server {
    listen 80;
    server_name web.funnygeekjp.com;
    return 301 https://$host$request_uri;       # HTTPをHTTPSにリダイレクト; 404;  managed by Certbot

    location /user {                            # webコンテンツのディレクトリ
        alias /home/user/www;
        index index.html;
    }

    # アプリ用に追加(Node.js APIへのプロキシ)
    location /app {
        proxy_pass http://localhost:3000/chat;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_buffering off;
    }

    location /login {
        proxy_pass http://localhost:3000/login;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_buffering off;
    }

    listen 443 ssl; # SSサーバー証明書の管理 by Certbot
    ssl_certificate /etc/letsencrypt/live/web.hogehoge.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/web.hogehoge.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    # アプリ用にプロキシを追加
    location /api3001/ {
        proxy_pass http://localhost:3001/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
    }
    location /api3002/ {
        proxy_pass http://localhost:3002/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
    }
}

設定を変更したら nginx を再起動する

$ sudo systemctl restart nginx

ブラウザで検査する

# ポート番号でアクセス
http://ome.funnygeekjp.com:3007/

# URIでアクセス
https://ome.funnygeekjp.com/api3007/

コメントを残す