RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのITエンジニアによる技術ブログです。

Web API開発入門

こんにちは。開発エンジニアの沼本です。

みなさんはWeb APIについてよくご存じでしょうか?
私はこれまでエンジニアとしていくつかのサービス開発に携わってきましたが、Web APIと接する機会が非常に増えてきていると感じています。
今回はWeb APIについて基本的な概念をおさらいし、PHPを使用してWeb APIの開発入門をまとめたいと思います。

Web APIとは

そもそもWeb APIとはいったい何なのでしょうか。

専門的に言うと、Web APIとは「HTTPプロトコルを用いてネットワーク越しに呼び出すAPI」のことです。
(API とは「Application Programming Interface」の略で、「ソフトウェアコンポーネント同士が互いに情報をやりとりするのに使用するインタフェースの仕様」のこと)

この説明だとピンとこない方もいるかもしれません。 より簡単に一言で言ってしまうと、Web APIとは「URIにアクセスすることで、特定の情報の取得・操作ができるシステム」のことです。

Web APIを使ってみる

ここではWeb APIの理解を深めるため、実際にWeb APIを利用してみます。
世の中には数多くのWeb APIが公開されていますが、今回はビットコインの販売価格を取得できるAPIを利用してみたいと思います。

bitflyer.com

以下のURIにアクセスしてみて下さい。

https://bitflyer.jp/api/echo/price

コマンドラインだとこうです。

curl -X GET 'https://bitflyer.jp/api/echo/price'

すると以下のようなビットコインの価格情報が取得できると思います。

{"ask":4519932.0,"bid":4256241.000000000000,"mid":4388086.500000000000}

(ask: bitFlyerの1BTC販売価格、bid: bitFlyerの1BTC買取価格、mid: 仲値)

URIにアクセス(リクエストを送信する)だけで簡単にビットコインの価格情報を取得することができました。
例えば、自分の開発しているサービス内でこのWeb APIを利用することで、開発コストを抑えつつビットコイン価格の情報を利用した機能を作成することができます。

Web APIの開発

今回はWeb API開発の入門ということで、簡単なWeb APIを作成してみます。

作成するもの

リクエストを送ると、登録してあるユーザーを取得できるWeb APIを作成します。 ユーザーの一覧を取得できるだけでなく、IDをパラメータとして送ることで、特定のユーザーを取得できるようにします。

本来であればDBにユーザーデータを持たせ、新規登録・更新・削除などもできるようにしますが、今回は簡略化のために省きます。 ユーザーのデータはあらかじめ配列で持たせておくことにします。

言語

Web APIを開発するにあたり、スタンダードとなっている言語は特にありません。
今回は私が普段の開発で使用しており、使用者数も多いPHPを使います。

エンドポイント(URI)

Web APIURIにリクエストを送ることで、データの取得や操作を行います。
そのため、簡潔で、どのような機能を持つのかが分かりやすいURIを設計することが重要です。
一般的に重要だとされる点は以下のようなことです。

  • 短く入力しやすいURI
  • 人間が読んで理解できるURI
  • 大文字小文字が混在していないURI
  • 改造しやすいURI
  • サーバ側のアーキテクチャが反映されていないURI
  • ルールが統一されたURI

今回は以下のように設計します。 本来はURIに拡張子を含めるのはよくありませんが(サーバー側のアーキテクチャが反映されているため)、今回は簡略化のため表示したままとしています。

目的 エンドポイント HTTPメソッド
ユーザーの一覧取得 http://localhost/api/users.php GET
特定のユーザーの情報の取得 http://localhost/api/users.php?id=X GET

今回は実装しませんが、ユーザーの新規登録・更新・削除を行う場合は以下のようになるはずです。

目的 エンドポイント HTTPメソッド
ユーザーの新規登録 http://localhost/api/users.php POST
ユーザーの情報の更新 http://localhost/api/users.php?id=X PUT/PATCH
ユーザーの情報の削除 http://localhost/api/users.php?id=X DELETE

HTTPメソッドについて簡単に説明しておきます。 HTTPメソッドとは、HTTPでのアクセス時に指定するもので、GETやPOSTなどが有名です。 URIとHTTPメソッドの関係は、「操作する対象」と「操作方法」の関係にあります。 以下に一覧を示しておきます。

HTTPメソッド名 説明
GET 情報の取得
POST 情報の新規登録
PUT 既存の情報の更新
DELETE 情報の削除
PATCH 情報の一部変更
HEAD 情報のメタ情報の取得

レスポンスデータ

Web APIURIにリクエストを送ると、その結果(レスポンスデータ)が返ってきます。
Web APIのレスポンスは他の開発者が利用することが前提なので、なるべくプログラム内部で利用しやすい形式にすることが望ましいです。

データフォーマット

まず最初に、レスポンスデータをどのようなデータフォーマットで返すのかを考える必要があります。
現在、Web APIで利用されている主なデータフォーマットは大きく分けて以下の2つです。

かつてはXMLがよく使用されていましたが、現在はJSON形式で返すのが主流になっています。
今回もレスポンスデータはJSONで返すこととします。

{
    "status": "OK",
    "users": [
        {
            "name": "yamada",
            "age": 20
        },
        {
            "name": "suzuki",
            "age": 25
        },
        {
            "name": "matsuda",
            "age": 30
        }
    ]
}
ステータスコード

レスポンスを返す際には、適切なステータスコードを返します。
ステータスコードとは、「200」や「404」など3桁の数字で表され、HTTPレスポンスヘッダの先頭行に記載されています。
「200 OK」や「404 Not Found」などはブラウザ画面にも表示されるため有名です。

以下にステータスコードの分類を示しておきます。

ステータスコード 意味
100番台 情報
200番台 成功
300番台 リダイレクト
400番台 クライアントサイドに起因するエラー
500番台 サーバーサイドに起因するエラー
エラー表示

Web APIは様々な要因でエラーを返す可能性があります。
エラーを返す際にはステータスコードを付与しますが、それだけでは不十分です。
Web APIを利用している側が、なぜエラーになったのかを具体的に分かるようにしておきます。 エラーを返す際にはエラーの詳細について、レスポンスボディに含めて返すのが一般的ですので今回もそのようにします。

{
    "status": "NG",
    "message": "Invalid parameter"
}

セキュリティ

今回は入門の記事ということで実装は行いませんが、Web API開発に置いてセキュリティ対策に気を配ることは重要です。
特に機密情報などを扱っている場合、悪意のある利用者から情報を保護するための対策を行っておかなければ大事故に繋がりかねません。
本格的なWeb APIの開発・公開を考えておられる方は、別途セキュリティについての情報を確認することをおすすめします。

実装

実装方法は様々ありますが、今回はapiディレクトリ以下にusers.phpというファイルを作成し、リクエストを受けるようにします。 users.phpでリクエストを受けた後はサービスクラスに処理を投げ、返ってきた結果をレスポンスとして返すことにします。

users.php

<?php
namespace api;

require('UsersApiService.php');

$usersApiService = new UsersApiService();

if (isset($_GET["id"])) {
    // IDの指定がある場合
    list($statusCode, $res) = $usersApiService->getUser($_GET["id"]);
} else {
    //IDの指定がない場合
    list($statusCode, $res) = $usersApiService->getUserList();
}

// 文字コード設定
header('Content-Type: application/json; charset=UTF-8');

// HTTPステータスコード設定
http_response_code($statusCode);

// レスポンスをJSON形式で返す
print json_encode($res, JSON_PRETTY_PRINT);

UsersApiService.php

<?php
namespace api;

class UsersApiService
{
    private $userList = [
        ["name" => "yamada", "age" => 20],
        ["name" => "suzuki", "age" => 25],
        ["name" => "matsuda", "age" => 30]
    ];
    private $statusCode = 200;
    private $res = [];

    /**
     * ユーザーのリストを取得する
     *
     * @return array httpステータスコード,ユーザーのリスト
     */
    public function getUserList()
    {
        try {
            // 全てのUserリストを返す
            $this->res["status"] = "OK";
            $this->res["users"] = $this->userList;
        } catch (Exception $e) {
            $this->statusCode = 500;
            $this->res["status"] = "NG";
            $this->res["message"] = $e->getMessage();
        }

        return [$this->statusCode, $this->res];
    }

    /**
     * 特定のユーザーを取得する
     *
     * @return array httpステータスコード,ユーザーのリスト
     */
    public function getUser($userId)
    {
        try {
            if ($this->validate($userId)) {
                // IDで指定されたユーザーを返す
                $this->res["status"] = "OK";
                $this->res["users"] = $this->userList[$userId];
            }
        } catch (Exception $e) {
            $this->statusCode = 500;
            $this->res["status"] = "NG";
            $this->res["message"] = $e->getMessage();
        }

        return [$this->statusCode, $this->res];
    }

    /**
     * パラメーターのバリデーション
     *
     * @param int ユーザーID
     * @return boolean バリデーション結果
     */
    private function validate($userId)
    {
        if (preg_match('/[^0-9]/', $userId)) {
            // パラメーターが不正だった場合
            $this->statusCode = 400;
            $this->res["status"] = "NG";
            $this->res["message"] = 'Invalid parameter';
            return false;
        } elseif (!isset($this->userList[$userId])) {
            // 指定されたユーザーが見つからなかった場合
            $this->statusCode = 404;
            $this->res["status"] = "NG";
            $this->res["message"] = 'User not found';
            return false;
        }

        return true;
    }
}

動作確認

ちゃんと動くか確認しておきます。

ユーザー一覧の取得
http://localhost/api/users.php

{
    "status": "OK",
    "users": [
        {
            "name": "yamada",
            "age": 20
        },
        {
            "name": "suzuki",
            "age": 25
        },
        {
            "name": "matsuda",
            "age": 30
        }
    ]
}

特定のユーザーの取得
http://localhost/api/users.php?id=2

{
    "status": "OK",
    "users": {
        "name": "matsuda",
        "age": 30
    }
}

パラメータのフォーマットが不正な場合
http://localhost/api/users.php?id=a

{
    "status": "NG",
    "message": "Invalid parameter"
}

ユーザーが存在しない場合
http://localhost/api/users.php?id=99

{
    "status": "NG",
    "message": "User not found"
}

おわりに

今回は入門として簡単なWeb APIを作成してみました。
実際に本格的な実装を行う場合は、今回書いた以外にも様々な考慮が必要になります。
今回を機に、さらにWeb APIについての知識を深めていきたいと思います。


◆TECH PLAY
techplay.jp

◆connpass
rakus.connpass.com

Copyright © RAKUS Co., Ltd. All rights reserved.