oinume journal

Scratchpad of what I learned

Google Apps Scriptで外部のREST APIを呼び出す

Google Apps Script(GAS)から外部のREST APIを呼ぶには、UrlFetchApp.fetch というメソッドを呼び出せば良い。例えばJSONをリクエストのペイロードとして送る場合のサンプルコードはこんな感じ。

  var data = {
    'email': email,
    'subject': subject,
    'message': message,
  };
  var credential = PropertiesService.getScriptProperties().getProperty('FRESHDESK_CREDENTIAL');
  var options = {
    'method': 'post',
    'contentType': 'application/json',
    'headers': {
      'Authorization': 'Bearer ' + Utilities.base64Encode(String(credential))
    },
    'payload': JSON.stringify(data)
  };
  
  var response = UrlFetchApp.fetch('<api endpoint>', options);

fetchの第2引数に渡すoptions に以下のフィールドをセットしている。

  • method: HTTP method
  • contentType: application/json を指定
  • headers.Authorization でAPIのトークンを指定
    • ベーシック認証もできる
  • payload: リクエストのペイロードをJSONにしておく

また、上のコードのAPIのキーである credential はスクリプトのプロパティから値を取得している。ログインIDやパスワードなどをスクリプトの中に埋め込みたくない場合は環境変数みたいな感じで使えるスクリプトのプロパティを使うのが良いみたい(ソース)。

ハマったポイントとして、外部のAPIを呼び出す場合は、scopeに https://www.googleapis.com/auth/script.external_request がないと権限がないというエラーになるので注意。ファイル→プロジェクトのプロパティ→スコープ のタブで確認できる。スクリプトに対するスコープを再設定したい場合は、GUIだとプロジェクトを作り直してコードをコピペするしかなさそうな雰囲気。

自分は、Googleフォームで受けた問い合わせをFreshDeskというSaaSのシステムにAPIで投げて問い合わせを管理するということがやりたかったので、頑張ってスクリプトを書いた。これでGoogleフォームのインタフェースを使いつつ、バックエンドはちゃんとしたシステムで問い合わせを管理するということができるようになりましたとさ。

仕事で使える!Google Apps Script (仕事で使える!シリーズ(NextPublishing))

仕事で使える!Google Apps Script (仕事で使える!シリーズ(NextPublishing))

Google Driveの画像をブログに埋め込む

いっっっつもやり方を忘れるので未来の自分のためにメモ。

1.Google Driveで対象の画像ファイルを選択して開く

2.画像が表示されるので、右上のメニュー(縦の...のアイコン)から 新しいウィンドウで開く をクリックする。

3.開いたウィンドウの右上のメニューから アイテムを埋め込む をクリックすると iframe のHTMLコードが表示されるので、それをコピーしてブログに貼り付ける。

Googleフォームでメールアドレスを収集する場合にそのメールアドレスをGASから取得する

ググってもあまり出てこなかったのでメモ。Googleフォームで メールアドレスを収集する という設定をONにすると、フォームの回答を記録するSpreadsheetにメールアドレスが保存されるようになる。

これをGASのスクリプトからどうやって取るんだろうと思って調べてみたら、e.response.getRespondentEmail()というメソッドを呼ぶと取れるということがわかった。

試しにやってみたら見事にメールアドレスが取れた...! これでメアドを取るために独自のフィールドを足さなくて済む!

HerokuのName lookup timeoutが短すぎて困ってる話

最近HerokuのDynoで以下のようなエラーが出るようになった。アプリケーションから接続するMySQLのホスト名の解決が失敗しているっぽい。

Jan 18 08:20:25 ***** app/web.1:  {"level":"error","ts":"2018-01-17T23:20:24Z","msg":"InternalServerError","error":"errors.Internal: Failed to gorm.Open(): dial tcp: lookup ******** on 172.16.0.23:53: write udp 172.18.167.70:36855->172.16.0.23:53: i/o timeout

なんで?って思って /etc/resolv.conf を見てみたら

$ cat /etc/resolv.conf
options timeout:2
nameserver 172.16.0.23
search ec2.internal

↑のように timeout が2秒に設定されていた... 妥当な値かもしれないけど、ログにエラーが残るのが嫌だったのでIP直指定することで対応した... なんかいい方法ないかな。

webpackで<script>タグでロードしたライブラリをbundleされたJSから外したい

webpackのconfigには externals というものがある(ドキュメント)。このexternalsで定義したライブラリは、importで参照していてもwebpackでビルドして生成される成果物(bundle.js)には含まれなくなるというもの。

自分のユースケース

  • もともとReactを使っていないプロジェクトで一部のページだけでReactを使っていきたい
  • 全ページでReactを使うわけではないので、bundle.js には含めたくない(サイズ削減)
  • Reactが必要なページのみHTML上の <script> タグでロード

webpack.config.js

externalsでreactを除外するよ、ということを定義すれば bundle.js には含まれないようになる。webpackの設定ファイルはこんな感じ。

const config = {
  externals: {
    'react': 'React',
    'react-dom': 'ReactDOM',
  },
  ...
};

module.exports = config;