こんにちは。株式会社ラクスで先行技術検証を行っている技術推進課のt_okkanです。
現在、フロントエンドの技術検証をしているのですが、手頃にバックエンドのAPIを構築したいと思いJSON Serverを利用しました。 同じようにバックエンドを手軽に構築する手段としては、FirebaseなどのBaaSを利用することがあげられますが、より手軽にローカルで構築できる手法を紹介しようと思います。 さらに今回はDockerでのJSON Serverの構築と、デフォルトのJSON Serverの機能を拡張し認証機能を追加する方法を紹介しようと思います。
JSON Server
JSON Serverは、フロントエンド開発者向けプロトタイピング時のバックエンドAPIのモック作成ライブラリです。ローカルに用意したJSONファイルをリソースとしてAPIを構築することができ、そのJSONファイルの構成から自動的にURLが生成されます。
Expressベースでサーバーを構築しているので、Expressのモジュールを使用してカスタマイズを実装できます。 今回はその仕組みを利用して、認証機能付きのJSON Serverを構築します。
タイトルの30秒で構築できる
はコードがあれば、30秒で構築できるということです。
デフォルトの認証なしの機能なら、Getting started通りに構築するとコードレスで、30秒でREST APIを構築できます。
公式ドキュメントでもアピールしています。
Get a full fake REST API with zero coding in less than 30 seconds (seriously)
JSON Serverの実装
フォルダー構成
今回構築するAPIサーバーのフォルダー構成は以下のようになります。./server
フォルダー内にDockerコンテナへ配置する、JSON Server用のファイル群を配置します。
./ |- server | |- data | | |- data.json | |- server.js | |- package.json |- docker-compose.yml |- Dockerfile
server.js
にはExpressのモジュールを利用してデフォルトのJson Serverをカスタマイズした機能を実装します。今回は認証処理を実装します。
data.json
にはAPIで管理するリソースデータを記述します。
API仕様
今回構築するAPIサーバーの主な仕様です。このほかにもPUT
やDELETE
も使用できます。
今回はブログ記事のAPIを想定しています。ログイン・ブログ記事取得、のAPIにのみ認証なしアクセスでき、それ以外のAPIにアクセスするには認証が必要となります。
URL | メソッド | 機能 | 認証 |
---|---|---|---|
http://localhost:33000/blogs | GET | ブログ一覧取得 | なし |
http://localhost:33000/blogs | POST | ブログ記事追加 | あり |
http://localhost:33000/blogs/:id | GET | ブログ取得 | なし |
http://localhost:33000/users | GET | ユーザー一覧取得 | あり |
http://localhost:33000/users/:id | GET | ユーザー一覧取得 | あり |
http://localhost:33000/auth/login | POST | ログイン | なし |
data.json
data.json
はデータベースのように、APIで扱うデータを保存します。今回は、ユーザー情報とブログ情報を保存するようにします。
{ "blogs": [ { "id": 1, "title": "Java", "body": "Java Beans", "post": "2020/10/01", "userid": 1 }, { "id": 2, "title": "Python", "body": "Python3.10", "post": "2020/10/04", "userid": 1 }, { "id": 3, "title": "JavaScript", "body": "Vue.js", "post": "2020/10/10", "userid": 2 } ], "users": [ { "id": 1, "name": "user one", "email": "one@example.com", "password": "userone" }, { "id": 2, "name": "user two", "email": "two@example.com", "password": "usertwo" } ] }
JSON Serverの実装
ではプログラムを実装し、JSON Serverを拡張し認証付きREST APIサーバーを構築していきます。
まずはNode.jsのプロジェクトのpackage.json
を以下のように設定します。
{ "name": "json-server-docker", "version": "1.0.0", "description": "Json Server on Docker", "author": "XXXX@example.com", "main": "server.js", "scripts": { "start": "node server.js" }, "dependencies": { "body-parser": "^1.19.0", "helmet": "^4.1.1", "json-server": "^0.16.1", "jsonwebtoken": "^8.5.1" } }
main
, scripts
, dependencies
以外は好みの値に設定してください。
今回は認証にJWTでのトークン認証を使用するので、jsonwebtoken
を依存関係に追加します。
では次に、サーバー本体となるserver.js
を以下のように実装します
const jsonServer = require("json-server"); const fs = require("fs"); const bodyParser = require("body-parser"); const jwt = require("jsonwebtoken"); const helmet = require("helmet"); // JSON Serverで使用するJSONファイルを設定 const server = jsonServer.create(); const router = jsonServer.router("./data/data.json"); // JSON形式のリクエスト対応 server.use(bodyParser.urlencoded({ extended: true })); server.use(bodyParser.json()); // 署名 const JWT_SECRET = "jwt_json_server"; // 有効時間 const EXPIRATION = "1h"; // データーベースの作成 const db = JSON.parse(fs.readFileSync("./data/data.json", "UTF-8")); // ①ログイン用のルート server.post("/auth/login", (req, resp) => { const { email, password } = req.body; // ログイン検証 if ( db.users.findIndex( (user) => user.email === email && user.password === password ) === -1 ) { resp.status(401).json("Unauthorized"); return; } // ログイン後、アクセストークンの生成 const access_token = jwt.sign({ email, password }, JWT_SECRET, { expiresIn: EXPIRATION, }); resp.status(200).json({ access_token }); }); // ②ログイン認証が必要ないルート // 記事一覧を取得 server.get("/blogs", (req, resp) => { const blogs = db.blogs; resp.status(200).json({ blogs }); }); // 記事IDから記事を取得 server.get("/blog/:id", (req, resp) => { const id = req.params.id; const blog = db.blogs.find((blog) => blog.id === Number(id)); resp.status(200).json({ blog }); }); //③ 認証が必要なルート server.use((req, resp, next) => { // 認証形式チェック if ( req.headers.authorization === undefined || req.headers.authorization.split(" ")[0] !== "Bearer" ) { // 認証形式が異なる場合 resp.status(401).json("Unauthorized"); return; } // 認証チェック try { var decode = jwt.verify( req.headers.authorization.split(" ")[1], JWT_SECRET ); // 認証に成功した場合は、next関数を実行しJSON Serverの機能を利用する next(); } catch (e) { // 認証に失敗した場合 resp.status(401).json("Unauthorized"); } }); // JSON Serverを起動する server.use(router); server.use(helmet); server.listen(33000, () => { console.log("JSON Server Start"); });
JsonServer Access Controlを参考に実装しました。 実装したルーターとしては、
- ログイン用(
/auth/login
) - 認証なしで公開(
/blogs
、/blogs/:id
) - 上記以外で認証が必要
の3種類を実装しています。
jsonwebtoken
や、body-parser
の使い方はこちらを参考にしています。
Docker環境
Dockerを用いてJSON Serverを構築します。Dockerfile
とdocker-compose.yml
は以下のようにしました。
- Dockerfile
FROM node:latest RUN yarn add global json-server
- docker-compose.yml
version: "3" services: json-server: build: context: . dockerfile: Dockerfile volumes: - ./server:/data/server:delegated tty: true working_dir: /data/server command: sh -c "yarn install && yarn start" container_name: jsonserver-docker ports: - "33000:33000"
実行
では最後にDockerコンテナ上で実行しましょう。
$ docker-compose build $ docker-compose up -d
起動後にcurl
でhttp://localhost:33000/users
にアクセスしてください。認証をしていないので、Unauthorized
が返ってきます。
$ curl http://localhost:33000/users "Unauthorized"
/auth/login
でログインしてから、レスポンスのアクセストークンをヘッダーに付与して同じURLにアクセスしてみます。
$ curl -X POST -H "Content-Type: application/json" -d '{"email": "one@example.com", "passowrd": "userone"}' http://localhost:33000/auth/login { "access_token": "アクセストークン" } $ curl -H "Content-Type:application/json" -H "Authorization:Bearer アクセストークン" http://localhost:33000/users [ { "id": 1, "name": "user one", "email": "one@example.com", "password": "userone" }, { "id": 2, "name": "user two", "email": "two@example.com", "password": "usertwo" } ]
レスポンスから分かるように、ユーザー一覧を取得できます。/blogs
のGETメソッドとPOSTメソッドでも試してみてください。
まとめ
JSON Serverを利用して認証機能付きのモックREST APIを構築しました。 一度作成してしまえば、Dockerを起動するだけでいつでも30秒でバックエンドのAPIを構築できます。 日々の勉強や、ちょっとした検証などに利用してみてください。 GitHubにもコードを上げています。参考にしてみてください。
https://github.com/txkxyx/jsonserver-docker
エンジニア中途採用サイト
ラクスでは、エンジニア・デザイナーの中途採用を積極的に行っております!
ご興味ありましたら是非ご確認をお願いします。
https://career-recruit.rakus.co.jp/career_engineer/カジュアル面談お申込みフォーム
どの職種に応募すれば良いかわからないという方は、カジュアル面談も随時行っております。
以下フォームよりお申込みください。
rakus.hubspotpagebuilder.comラクスDevelopers登録フォーム
https://career-recruit.rakus.co.jp/career_engineer/form_rakusdev/イベント情報
会社の雰囲気を知りたい方は、毎週開催しているイベントにご参加ください!
◆TECH PLAY
techplay.jp
◆connpass
rakus.connpass.com