GAミント至上主義

Web Monomaniacal Developer.

Firebase Functionsのデプロイ時にHTTP Error: 400, The request has errorsで失敗する

Firebase FunctionsをデプロイするときにHTTP Error: 400が出て少しハマった。

?  functions: Finished running predeploy script.
i  functions: ensuring necessary APIs are enabled...
?  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (69.6 KB) for uploading
?  functions: functions folder uploaded successfully
i  functions: current functions in project: callCharge(us-central1), charge(us-central1), hello(us-central1)
i  functions: uploading functions in project: sendReceptionMail(us-central1)
i  functions: creating Node.js 8 function sendReceptionMail(us-central1)...
?  functions: failed to create function sendReceptionMail
HTTP Error: 400, The request has errors


Functions deploy had errors. To continue deploying other features (such as database), run:
    firebase deploy --except functions

Error: Functions did not deploy properly.

400ということでプロジェクトやGoogleアカウントの認証周りを疑ったけど違った。

原因はdocumentを参照しなければいけないところでcollectionのパスを指定してしまっていたことだった。
エラーがちょっと不親切だけどCLIではなくコードの実行時のエラーだと分かっていれば次回はなんとかなりそう。

exports.sendReceptionMail = functions
  .firestore
  .document('share_data/{userId}/corrections/')
  .onCreate((snap, context) => {
//略

exports.sendReceptionMail = functions
  .firestore
  .document('share_data/{userId}/corrections/{correctionId}')
  .onCreate((snap, context) => {
//略

WEB+DB PRESS Vol.105

WEB+DB PRESS Vol.105

  • 作者: 小笠原みつき,西村公宏,柳佳音,志甫侑紀,池田友洋,木村涼平,?橋優介,大塚雅和,飯塚直,吉川竜太,末永恭正,久保田祐史,浜田真成,穴井宏幸,大島一将,桑原仁雄,牧大輔,池田拓司,はまちや2,竹原,WEB+DB PRESS編集部
  • 出版社/メーカー: 技術評論社
  • 発売日: 2018/06/23
  • メディア: 単行本
  • この商品を含むブログを見る

Dockerで動かしたHeadless ChromeでPDFにすると日本語が化ける問題

yagish履歴書でも使っている下記のPDF変換サーバーだけど、日本語の下記のような文字がPDFにすると全部□に化けてしまっていました。

〜◯◎■□◆◇❏★☆

ユーザーが使いそうなのだけ上げたので他にもありそう。

github.com

もちろん日本語フォントはインストールされているので、なんでだろうと思っていましたが、日本語系パッケージとlocale設定が足りなかった模様。
ベースのnode:10-slimはDebianだったので localesとtask-japanese入れてみたら無事表示された。

Dockerfile

FROM node:10-slim
LABEL maintainer="yu_yamazaki@bizocean.co.jp"

# Install fonts
COPY fonts /usr/share/fonts

# Install utilities
RUN apt-get update --fix-missing && apt-get -y upgrade

# Japanese
RUN apt-get install -y locales task-japanese
RUN locale-gen ja_JP.UTF-8
RUN localedef -f UTF-8 -i ja_JP ja_JP
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:jp
ENV LC_ALL ja_JP.UTF-8
# 以下略

ENVはこの記事を参考にしました
DockerfileでDebianコンテナの日本語環境を整える

Vue Router&Firebaseの認証付きページでログアウト後に任意のページに飛ばそうと思ったらハマった話

Vue RouterとFirebase Authenticationで認証が必要なページを作っていたが、ログアウト後に任意のページに飛ばそうと思ってもうまく行かなかった。
いろいろ試したけど、イベントリスナーonAuthStateChangedを多重登録しないよう事前にUnsubscribeしたら大丈夫になった。

SSSS.GRIDMANを見ると原作の内容よりも小学生のときの同級生がグリッドマンの絵つき道具袋を使っていたのを思い出します。

全体的なやり方は下記ページといっしょ。
qiita.com
qiita.com

最終的なコードは下記。
router.jsから抜粋

// 詳しくは公式ドキュメント
// https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onAuthStateChanged
let onAuthStateChangedUnsubscribe

router.beforeEach((to, from, next) => {
  if (typeof onAuthStateChangedUnsubscribe === 'function') {
    onAuthStateChangedUnsubscribe()
  }
  if (!to.matched.some(record => record.meta.requiresAuth)) {
    next()
  } else {
    onAuthStateChangedUnsubscribe = firebase.auth().onAuthStateChanged(function (currentUser) {
      if (currentUser) {
        next()
      } else {
        next({
          name: 'login'
        })
      }
    })
  }
})

認証にfirebase.auth().onAuthStateChangedのコールバックを使うようになっているが、それがbeforeEachのタイミングではなく、Firebaseをログアウトした瞬間先に動いてしまい全部loginに飛んでしまって、飛ばしたいページには行かなかったもよう。

これに限らず、以前も書いたけどonなんちゃらのイベントリスナ登録系はなんども登録しないように、また何度も登録が必要な場合は以前のを消し、多重登録しないようにするのが大事だと改めて思う。
uyamazak.hatenablog.com

追記

上記参考ページにあるとおり、firebase.auth().currentUserがある場合の処理を追加したら、ムダも減るし、Unsubscribeしなくてもほとんど問題ないような気がしてきた。

let onAuthStateChangedUnsubscribe
router.beforeEach((to, from, next) => {

  if (!to.matched.some(record => record.meta.requiresAuth)) {
    next()
  } else {
    if (firebase.auth().currentUser) {
      next()
      return
    } else {
      if (typeof onAuthStateChangedUnsubscribe === 'function') {
        onAuthStateChangedUnsubscribe()
      }
      onAuthStateChangedUnsubscribe = firebase.auth().onAuthStateChanged(function (currentUser) {
        if (currentUser) {
          next()
        } else {
          next({
            name: 'login'
          })
        }
      })
    }
  }
})

Vue.js入門 基礎から実践アプリケーション開発まで

Vue.js入門 基礎から実践アプリケーション開発まで