Firebase Functions + Firestore の応用で チャット や ツイッター サンプルが見つかるが 古く不完全。
BBS として完成させる備忘録。
前提環境
●Google Chrome 114.0.5735.199(Official Build)(64 ビット)
●FireFox 115.0.2 (64 ビット)
●「Firebase Functions」 の Functions 利用登録済。関数名 「a」。[Google Cloud Shell] を利用。
●「Firebase Functions + Firestore」 の Firestore 利用登録済。コレクション名「bbs」。
●v18.12.1 (Node)
●9.7.2 (Node Package Manager)
●12.4.4 (Firebase CLI)
●BBS のURL
https://remix.asia/bbs.html
...▼
前提環境
●Google Chrome 114.0.5735.199(Official Build)(64 ビット)
●FireFox 115.0.2 (64 ビット)
●「Firebase Functions」 の Functions 利用登録済。関数名 「a」。[Google Cloud Shell] を利用。
●「Firebase Functions + Firestore」 の Firestore 利用登録済。コレクション名「bbs」。
●v18.12.1 (Node)
●9.7.2 (Node Package Manager)
●12.4.4 (Firebase CLI)
●BBS のURL
https://remix.asia/bbs.html
...▼
Cloud Shell Editor
https://console.cloud.google.com/cloudshelleditor
functions/index.js を次のように置き換え。
Firestore コレクション名 bbs
ポイントは
★1 https://remix.asia からのアクセスを許可
★2 ブラウザから json 受信する為
▼
関数 a デプロイ
▼
https://remix.asia/bbs.html の内容。
ブラウザで https://remix.asia/bbs.html アクセス直後。
▼
名前とメッセージを送信。
renewボタンで最新メッセージ一覧。
▼
■Firebase Console
https://console.firebase.google.com/
firestore に記録される。
https://console.cloud.google.com/cloudshelleditor
functions/index.js を次のように置き換え。
$ vi functions/index.js
// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers. const {logger}= require("firebase-functions"); const {onRequest}= require("firebase-functions/v2/https"); // The Firebase Admin SDK to access Firestore. const {initializeApp}= require("firebase-admin/app"); const {getFirestore}= require("firebase-admin/firestore"); const cors= require( "cors" )( {origin: true} );// ★2 initializeApp(); exports.a= onRequest( async (req, res) => { const date = new Date(); logger.log( "req.method:", req.method, date ); res.set( "Access-Control-Allow-Origin", "https://remix.asia" );// ★1 let n= "Unknown";// 名前 let m= "";// メッセージ let p= "up";//処理 switch ( req.method ){ case "GET": case "POST": if( undefined === req.body.n ){ p= "list";// パラメータなければ一覧表示 }else if( 0 < req.body.n.length ){ n= req.body.n; } if( undefined !== req.body.m ){ m= req.body.m; } break; case "OPTIONS":// ★2 cors( req, res, () => { res.status( 200 ).send(); }); return ""; default: p= "other"; } switch( p ){ case "list":{ try{ const map= {}; const querySnapshot= await getFirestore().collection( "bbs" ) .orderBy( "when", "asc" ) .get(); querySnapshot.forEach( ( m ) => { map[m.id]= m.data(); }); res.status( 200 ).json( map ); return ""; }catch( err ){ const s= {error: {message: err.toString()}}; res.status( 400 ).json( s ); } break; } case "up":{ const r= await getFirestore() .collection( "bbs" ) .add( { when: date, who: n, msg: m, }); const s= {success: {message: `Message with ID: ${r.id} added.`}}; res.json( s ); break; } default:{ const s= {error: {message: "bad parameter."}}; res.status( 400 ).json( s ); } } return ""; });Firebase Functions 関数名 a
Firestore コレクション名 bbs
ポイントは
★1 https://remix.asia からのアクセスを許可
★2 ブラウザから json 受信する為
▼
関数 a デプロイ
$ firebase deploy --only functions:aFunction URL
https://a-yukh3omtca-uc.a.run.app
▼
https://remix.asia/bbs.html の内容。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>BBS</title> </head> <body style="background-color:black;color:silver"> <form id="myForm"> <input type="button" value="renew" id="btnRenew"> 名前:<input type="text" name="n" autocomplete="on"> メッセージ:<input type="text" name="m"> <input type="submit" value="submit"> <input type="reset" value="reset"> </form> <div id="myList">"renew" update message list.</div> <script> const sURL= "https://a-yukh3omtca-uc.a.run.app";// ★Function URL const myList= document.getElementById( "myList" ); const btnRenew= document.getElementById( "btnRenew" ); const myForm= document.getElementById( "myForm" ); const fetchList= async( str ) => { const response = await fetch( str, { method: "GET" } ); const json = response.json(); if ( 200 == response.status ) { return Promise.resolve( json ); } else { return Promise.reject( json.error ); } }; const getList= ( event ) => { fetchList( sURL ).then( ( obj ) => { let s= ""; Object.keys( obj ).forEach( function( k ){ s= "<hr><div>" + obj[k].who + " : " + obj[k].msg + "</div>" + s; }); myList.innerHTML= s; }).catch( ( err ) => { console.log( err ); myList.innerHTML = err; }); }; const fetchSendData= async( str ) => { let o= new Object(); let formData= new FormData( myForm ); for( let kv of formData.entries() ){ o[kv[0]]= kv[1]; } const s= JSON.stringify( o ); const response= await fetch( str, { method: "POST" , body: s , headers: new Headers( { "Content-type": "application/json" } ) } ); const json= response.json(); if( 200 == response.status ){ return Promise.resolve( json ); }else{ return Promise.reject( json.error ); } }; const sendData= ( event ) => { event.preventDefault();//イベントデフォルト動作をキャンセル fetchSendData( sURL ).then( ( obj ) => { getList(); alert( obj.success.message ); }).catch( ( err ) => { console.log( err ); }); }; btnRenew.addEventListener( "click", getList ); myForm.addEventListener( "submit", sendData ); </script> </body> </html>▼
ブラウザで https://remix.asia/bbs.html アクセス直後。
▼
名前とメッセージを送信。
renewボタンで最新メッセージ一覧。
▼
■Firebase Console
https://console.firebase.google.com/
firestore に記録される。