KDE BLOG

バイブス

【Node.js】cookieを使ったクライアント ~ サーバー間のデータのやりとりサンプル

ブラウザにデータを保存するという役割でいうと、localStoragecookie が代表的かと思いますが、localStorage はクライアント側のみで使える機能で、サーバからは扱えません。
そのためクライアントとサーバ間のデータのやり取りではcookieを使うことで手軽に行えます。

というわけで理解を深めるために書籍のサンプルデータを参考に簡単なサンプルを作ってみました。

仕様

f:id:jinseirestart:20190105163339g:plain

  • cookieuserName がなければ「ゲスト」と表示する
  • cookieuserName があればその値を表示する
  • テキストボックスに入力してsubmitしたら、その値がcookieuserName として保存される

というシンプルな作りです。

コード

index.ejs(クライアント側)

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title><%= title %></title>
</head>
<body>
  <header>
    <h1><%= title %></h1>
  </header>
  <main>
    <p>こんにちは、<%= userName %>さん</p>
    <form action="/" method="post">
      <p>ユーザー名: <input type="text" name='userName'><input type="submit" value="送信"></p>
    </form>
  </main>
</body>
</html>

app.js(サーバ側)

const http = require('http');
const fs = require('fs');
const url = require('url');
const qs = require('querystring');
const ejs = require('ejs');

const INDEX_PAGE = fs.readFileSync('./index.ejs', 'utf8');

/**
 * クッキーの値を取得
 */
function getCookie(key, request) {
  const cookieData = request.headers.cookie !== undefined ? request.headers.cookie : '';
  const datas = cookieData.split(';').map(data => data.trim());
  const msgKeyValue = datas.find(data => data.startsWith(`${key}=`));
  if (msgKeyValue === undefined) return '';
  const msgValue = msgKeyValue.replace(`${key}=`, '');
  return unescape(msgValue);
}

/**
 * クッキーの値を設定
 */
function setCookie(key, value, response) {
  const escapedValue = escape(value);
  response.setHeader('Set-Cookie', [`${key}=${escapedValue}`]);
}

function getFromClient(request, response) {
  const urlParts = url.parse(request.url, true);
  const pathName = urlParts.pathname;
  switch (pathName) {
    case '/':
      if (request.method === 'POST') {
        let body = '';
        request.on('data', data => {
          body += data;
        });
        request.on('end', () => {
          const postData = qs.parse(body);
          setCookie('userName', postData.userName, response);
          response.writeHead(303, { Location: '/' });
          response.end();
        });
      } else {
        const userNameFromCookie = getCookie('userName', request);
        const userName = userNameFromCookie ? userNameFromCookie : 'ゲスト';
        const content = ejs.render(INDEX_PAGE, {
          title: 'Index',
          userName
        });
        response.writeHead(200, { 'Content-Type': 'text/html' });
        response.write(content);
        response.end();
      }
      break;
    default:
      response.writeHead(200, { 'Content-Type': 'text/plain' });
      response.write('No page...');
      response.end();
      break;
  }
}

const server = http.createServer(getFromClient);
server.listen(3000);
console.log('====== Server start!! ======');

解説・まとめ

ポイントとしては、クッキーの読み書きのタイミングかと思います。

サーバーサイド初心者の自分にとっては最初ちゃんと理解できなかったのですが、今回はフォーム上からcookieに登録する仕様なので、POST完了後のタイミングでその処理を行う必要があります。
POST完了後、response.setHeader('Set-Cookie', [key=value]) の形でレスポンスのヘッダーにCookieを渡すことができます。これによりクライアントのcookieに保存されます。

ページ表示時(GET)には、cookieを読み取る必要があるため、request.header.cookiecookieを参照します。
今回はcookieuserName というキーに値がなければ 「ゲスト」と表示しています。
取得したらそれをテンプレート側に渡してあげるだけとなります。

機能追加として、たとえばユーザーの訪問回数をカウントするのであれば、GET時のログを貯めておいてそれをユーザー名をキーにしてカウントすれば簡単に実装できそうです。

参考