Edited at

Google Cloud Functions の HTTP トリガーで matplotlib を使って生成した画像を返す


はじめに

BigQuery に溜まったデータに対して Python のロジックをかまして、画像を返したいというケースがあったので、 Google Cloud Functions で実現できるか検証しました。自分の欲しいところまではできたので、記事としてまとめておきます。

GitHub でソースコード公開してますので、そちらも合わせてご参照ください。

https://github.com/tanabee/functions-matplotlib

screenshot20190113.png

完成物


最小限の実装

以下のコードで動作する。 Cloud Functions の動作環境にはデフォルトで Flask がインストールされているので、 Flask の記法で HTTP リクエストを処理できる。 matplotlib は別でインストールする必要があるので、 requirements.txt に記載。

Cloud Functions のローカル環境での開発〜デプロイは以下を参照。

Google Cloud Functions のプログラムを Mac のローカル環境で開発〜デプロイする


main.py

from flask import make_response

import matplotlib.pyplot
from matplotlib.backends.backend_agg import FigureCanvasAgg
from io import BytesIO
import random

def graph(request):

# グラフ生成部分
fig, ax = matplotlib.pyplot.subplots()
ax.set_title(u'GRAPH')
x_ax = range(1, 200)
y_ax = [x * random.randint(100, 200) for x in x_ax]
ax.plot(x_ax, y_ax)

canvas = FigureCanvasAgg(fig)
buf = BytesIO()
canvas.print_png(buf)
data = buf.getvalue()

response = make_response(data)
response.headers['Content-Type'] = 'image/png'
response.headers['Content-Length'] = len(data)
return response



requirements.txt

matplotlib


ソースコード: https://github.com/tanabee/functions-matplotlib/tree/f27e307e5044d0a236b47c44576e82fa1f9be05d


トークンで簡易認証

スクリーンショット 2019-01-14 0.06.44.png

トークンを使って認証をしてみる。 Cloud Functions の環境変数を使って認証している。これにより [URL]?token=[環境変数で設定したトークン] のようにリクエストしないと 403 エラーを返すようになる。


main.py

- from flask import make_response

+ from flask import make_response, abort
import matplotlib.pyplot
from matplotlib.backends.backend_agg import FigureCanvasAgg
from io import BytesIO
import random
+ import os

def graph(request):

+ if request.args.get('token') != os.environ.get('TOKEN', 'token123'):
+ return abort(403)
+
fig, ax = matplotlib.pyplot.subplots()


スクリーンショット 2019-01-14 0.09.54.png

TOKEN はオレンジ枠で囲った部分で設定できる。デプロイコマンド時に設定することも可能。


まとめ

matplotlib で生成した画像を Cloud Functions を使って、 HTTP リクエストで返せるようにできました。公開範囲を絞りたい場合には、簡易なトークンも実装できます。 Cloud Functions は無料枠も多くて、簡単に実装できるので良いですね。

以上!