iOSやAndroid等のクライアントアプリを開発する場合、サーバ側の開発も必要となるケースは多いと思います。その場合、サーバサイドはWeb APIを開発することになると思いますが、アーキテクチャスタイルとしてRESTを採用することは現在当たり前と言っても良いと思います。GoogleやTwitter、Facebookだけでなく、さまざまな企業がREST APIを公開しており、Web系のエンジニアであれば、誰でも一度はREST APIを利用したことがあるのではないでしょうか(APIをラップしたライブラリを使って無意識に利用している可能性もあります)。
もちろんREST APIの活用はスマフォアプリに限らず、JSフレームワークを利用したWebサイトやloTデバイス等、Webに繋がる有りとあらゆるモノが対象となります。今回は、そんなREST APIをGAE/GO上で構築する方法について解説します。GOにはREST APIを構築するためのライブラリやFWがいくつかありますが、本記事ではGAE上で動作するものを2つ程ピックアップして、構築の手順をそれぞれ説明していきます(※1)。
ただし、本記事はGO言語を多少でも触ったことがあるユーザを対象にしています。そのため、基本的なGO言語の設定方法については本記事では説明しません。
※1 記事内容は前後編に分けて説明します。
目次
REST APIとはRESTの原則を満たしたAPI
REST APIとはRESTの原則を満たしたAPIを指します。RESTの原則はいくつもありますが、代表的なものを上げると以下のようなものがあります。
- URIは一意なリソースを表現する
- リソースの扱いはHTTPメソッドで決まる
RESTは決して複雑なものではなく、シンプルな設計をおこなうための設計スタイルです。上記の原則に沿って開発することで、非常に解りやすいAPIを構築することができるようになります。RESTは、前述したGoogleやTwitter等の大手IT企業だけでなく、Webサービスを展開する多くの日本企業にも広く利用されており、Webエンジニアにとっては現在なくてはならない存在になっているのではないでしょうか。
本記事で紹介するREST API構築のためのフレームワーク・ライブラリ
本記事では、以下2種類のREST用ライブラリ・フレームワークの導入方法について説明します。ただし、REST APIの構築には、以下2種類のフレームワークを同時に利用する必要はありません。本記事では、それぞれ独立した導入方法について説明します。
- Gorilla/mux
GorillaはGO言語でWebプログラミングをおこなうためのツールキットです。本記事では、そのツールキットの中の1つであるルーティング用のmuxパッケージを利用したREST API構築方法を説明します。 - Echo
EchoはGO製の軽量Webフレームワークで、ルーティングやセッション、テスト等Webサービスを開発する上で必要になる様々な機能を提供します。また、非常に高速で導入もとても簡単です。Echoについては本記事の後編で取り上げる予定です。
AppEngine SDKのインストール
今回取り上げるフレームワークの構築はGoogle App Engine上でおこないます。ライブラリ・フレームワークをインストールする前にまずはAppEngine SDKのインストールをおこなってください。SDKのインストール手順については以下をご参考ください。
App Engine SDKのインストール手順
https://apps-gcp.com/gae-go-gettingstart-01/#AppEngine_SDK
Gorilla/muxパッケージのインストール
Gorillaを利用してREST APIのインターフェースを構築するためにはmuxパッケージを利用します。gorilla/muxは以下のコマンドでインストール可能です(※2)。
go get github.com/gorilla/mux
https://github.com/astaxie/build-web-application-with-golang/blob/master/ja/01.2.md
Gorilla/muxの利用方法
Gorilla/muxの利用方法について説明します。REST APIのインターフェース構築に必要なURLマッピング、ホスト制限、HTTPメソッドの指定について説明し、その後実際のREST APIのサンプルプログラムとその動作について解説します。
URLマッピング
まずは単純にURIとハンドラのマッピングをおこなう方法について説明します。
1.パッケージのインポート
import (
"github.com/gorilla/mux"
"net/http"
)
2.mux.NewRouter()によってルーターを生成する
import (
"github.com/gorilla/mux"
"net/http"
)
func init() {
r := mux.NewRouter()
}
3.URIとハンドラのマッピングをおこなう
import (
"github.com/gorilla/mux"
"net/http"
)
func init() {
r := mux.NewRouter()
r.HandleFunc("/index", IndexHandler)
r.HandleFunc("/about", AboutHandler)
}
4. 3で定義したマッピング情報をhttp.Handle()で登録する
import (
"github.com/gorilla/mux"
"net/http"
)
func init() {
r := mux.NewRouter()
r.HandleFunc("/index", IndexHandler)
r.HandleFunc("/about", AboutHandler)
http.Handle("/", r)
}
以上で、基本的なURLマッピングの設定手順についての説明は完了です。ここまでの説明で、任意のURIに対するハンドラがリクエストを受け付けるところまで実装できるようなりました。
URIに挿入されたクエリパラメータを取得する
前節では、任意のURIに対するハンドラがリクエストを受信するまでの実装方法について説明しました。次のステップでは、クエリパラメータをURI上から受け渡すためのルーティング設定とURI上のクエリパラメータをハンドラから取得する方法について説明します。
1.クエリパラメータを含むURIのルーティング設定をおこなう
定義するURIに{パラメータ名}を定義します。idというパラメータ名で値を取得したい場合は{id}を定義するURIに挿入します(※3)。
func init() {
r := mux.NewRouter()
r.HandleFunc("/users/{id}", UserHandler)
http.Handle("/", r)
}
2.URIに挿入されたクエリパラメータを取得する
mux.Vars(r *http.Request)からリクエストパラメータMapを取得し、パラメータ名{id}をキーにURIに挿入された値を取得します。
func UserHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
...
}
※3 定義するクエリパラメータについては、以下のように正規表現を利用することも可能です。以下の例では「/users/123」「/users/0」のようなURLで接続した場合に、マッピングしたハンドラが呼び出されます。「/users/abc」のような文字列が含まれたURIで接続した場合はハンドラは呼び出されません。
r.HandleFunc("/users/{id:[0-9]+}", UserHandler)
アクセス元のホストを制限する
アクセス元のホストを制限する場合は、以下のようにHost()関数を利用します。この設定によって対象ホスト以外からアクセスすることができなくなります。
r := mux.NewRouter()
r.HandleFunc("/index", IndexHandler)
r.HandleFunc("/users/{id:[0-9]+}", UserHandler)
r.Host("www.example.com")
HTTPメソッドを限定する
HTTPメソッドを限定する場合はMethods()関数を利用します。この関数には複数のメソッドを登録することが可能です。以下は、GETメソッドでのみハンドラを呼び出しできるようにした例です。
r := mux.NewRouter()
r.HandleFunc("/users/{id:[0-9]+}", UserHandler).Methods("GET")
JSON応答のサンプルプログラムを動作させてみる
実際にサンプルプログラムをローカル環境で動かしてみます(Max/Linux環境を想定)。サンプルプログラムは、URIで渡したパラメータをJSONで返すだけの簡単なプログラムです。
動作後のREST APIにはcurlコマンドで接続してみます。尚、以下の手順はGO言語、AppEngine SDK、GO/muxのインストールが完了していることが前提となります。インストールが完了していない場合は、本記事の「AppEngine SDKのインストール」「Gorilla/muxのインストール」を読み直してください。
1.ローカル環境にフォルダを作成する
以下のコマンドを実行しプログラムや設定ファイルを同梱するフォルダを作成します。
mkdir sample
2.app.yamlの作成
1で作成したフォルダに移動し、以下のファイルを作成します。必ずapp.yamlというファイル名で作成してください。app.yamlはローカル環境でアプリを動作させるための必須ファイルとなります。
application: sample(※3)
version: 1
runtime: go
api_version: go1
handlers:
- url: /.*
script: _go_app
※3 アプリケーションをGAEにデプロイする場合「application」にはGCPプロジェクトのIDを指定します。ただし、ローカル環境でアプリを動作させるだけの場合「application」の設定値は適当な文字列で問題ありません。上記ファイルでは「sample」という適当な文字列を指定しています。
3.サンプルプログラムの作成
1で作成したフォルダ内で以下のファイルを作成します。ファイル名は任意で構いません。
package sample
import (
"github.com/gorilla/mux"
"net/http"
"fmt"
"encoding/json"
)
func init() {
r := mux.NewRouter()
r.HandleFunc("/api/users/{id:[0-9]+}", UserHandler).Methods("GET")
r.Host("localhost")
http.Handle("/", r)
}
type Reply struct {
Message string `json:"message"`
}
func UserHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
reply := Reply {
Message: "id(" + id + ")を取得しました",
}
json, _ := json.Marshal(reply)
fmt.Fprint(w, string(json))
}
4.ローカル環境の起動
以下のコマンドを実行する。引数には1で作成したフォルダのパスを指定します。
goapp serve /path/to/sample
5.curlコマンドの実行
4が起動したら以下のcurlコマンドを実行します。
curl -i http://localhost:8080/api/users/1234
6.実行結果の確認
5のコマンドを実行すると、以下のように結果が出力されます。
curl -i http://localhost:8080/api/users/1234
HTTP/1.1 200 OK
content-type: text/plain; charset=utf-8
Cache-Control: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Content-Length: 43
Server: Development/2.0
Date: Tue, 11 Oct 2016 05:40:52 GMT
{"message":"id(1234)を取得しました"}
以上で、サンプルプログラムの動作確認は完了です。サンプルプログラムを実際にGoogleのサーバにデプロイしたい場合は以下URLをご参考ください。
https://apps-gcp.com/gae-go-gettingstart-01/#GAEGO
まとめ
以上で、GAE/GO上でGorilla/muxによるREST API構築をおこなう手順の説明は完了です。Gorilla/muxの詳細を知りたい場合は以下のリファレンスをご確認ください。
http://www.gorillatoolkit.org/pkg/mux
また、さきほど動作させたサンプルプログラム、または自作したアプリケーションを世界中に公開したい場合は以下のURLを参考にしてください。自分のアプリケーションをとても簡単に公開することができます。
https://apps-gcp.com/gae-go-gettingstart-01/#GAEGO
次回はEchoを利用したREST API構築手順について説明します。
GorillaはWebアプリケーション開発のためのライブラリ集で必要なパッケージ毎にインストールが必要でしたが、EchoはライブラリではなくWebアプリケーションフレームワークです。軽量フレームワークではありますが、セッション・テスト・ロギング等Webアプリ開発に必要な様々な機能を搭載しており開発も活発に行われています。
本格的なアプリケーションを開発する場合は、Echoを利用するケースが多いのではないでしょうか。次回記事もぜひチェックしてください。