GoogleCloudFunctionsにふれる

※ ここに書かれているものは beta の時にかかれているもので正式リリースされた時にはかわっているかもしれません

最近個人的にGoogleCloudPlatformを使用している
今回はpublic betaになったCloudFunctionsにふれる

Google Cloud Functions?

https://cloud.google.com/functions/docs/

Google Cloud Functions is a lightweight compute solution for developers to create single-purpose, stand-alone functions that respond to Cloud events without the need to manage a server or runtime environment.

  • Node.jsで動く
  • サーバーレス
  • イベント駆動
    • 現状は Cloud Pub/Sub, Cloud Storage, HTTP トリガー
  • ローカルエミュレータで開発することも出来る
  • 現状は動作するリージョンはus-central1

AWSでいうところのLambdaのようなもの

ふれてみる

今回はhttpリクエストするとQiitaから指定されたユーザーの投稿のタイトルを返すものを作成する

コード自体はブラウザでも書ける
が折角ならローカルな好きなエディタで開発したいし毎回CloudFunctionsにデプロイするのは時間が勿体ない

まずはローカルで開発できる環境を整える

CloudFunctionsにはlocalで検証できるエミュレータが用意されている(※ 現在はアルファ版)

github.com

インストールしてとりあえず動かすところまでは記載されている
ただzshユーザーは一点だけ注意が必要

エミュレータを使用する際に使用する際のコマンドが functions なのだが zshにはbuild in commandとして functions が用意されておりそちらが使用されてしまう( zshのdoc にて functions [grepすると出て来る)

aliasとして functions-emulator が用意されているのでこちらを使用すれば動く

コードをかいていく

今回はAPIにリクエストを送る必要があるのでrequestにはrequestを使う

github.com

package.json

{
  "name": "sample",
  "version": "1.0.0",
  "description": "google cloud functions sample",
  "main": "index.js",
  "author": "hatappi",
  "license": "MIT",
  "dependencies": {
    "request": "^2.81.0"
  }
}

index.js

/**
 * Responds to any HTTP request that can provide a "message" field in the body.
 *
 * @param {!Object} req Cloud Function request context.
 * @param {!Object} res Cloud Function response context.
 */
const request = require('request');

exports.qiita = function helloWorld(req, res) {
  let parameters = {};

  if (req.body.qiita_user_id) { parameters['query'] = `user:${req.body.qiita_user_id}`; }

  request.get('https://qiita.com/api/v2/items', {
    qs: parameters,
    json: true
  }, function (err, response, body) {
    if(err) {
      console.log(err);
      res.status(response.statusCode).send('QiitaAPI Request ERROR');
    } else {
      const titles = body.map(function(row) { return row['title']; });
      res.status(response.statusCode).send(titles);
    }
  });
};

リクエストとしては

$ curl --request POST \
  --url [trigger url] \
  --header 'content-type: application/json' \
  --data '{"qiita_user_id":"hatappi"}'

のようなものを想定しておりcontent-typeに application/json を指定している
CloudFunctions側ではcontent-typeを見てparseしてくれているので、下記のようなリクエストでも同じプログラムを使うことが出来る

$ curl --request POST \
    --url [trigger url] \
    --header 'content-type: application/x-www-form-urlencoded' \
    --data 'qiita_user_id=hatappi'

あとはプログラムのポイントとしては最終的に send(), end(), json()などの終了メッソドを呼び出して終わりを明示してあげる必要があること
これを指定しないといつまで終わりを待ち続けてしまいCloudFunctions側で設定されるタイムアウトによって事切れてしまう

デプロイ

ブラウザ上でコピペしても良いが今回はgcloud コマンドでデプロイする

$ gcloud beta functions deploy qiita --stage-bucket [コードを保存するGCSのバケット名] --trigger-http

確認

無事デプロイが終わりCloudFunctionsのページにいくとFunctionsが生成されている

f:id:hatappi1225:20170422163015p:plain

詳細ページ
f:id:hatappi1225:20170422163158p:plain

詳細ページのトリガータブでトリガーを確認出来る
今回はhttpを指定したのでurlが表示される

またテストタブからは任意のイベントを渡すことも出来る

f:id:hatappi1225:20170422163347p:plain

最後に

スケジュール機能ほしい