এতদিন Firebase এর হাতেখড়ি সিরিজে আমরা ফ্রন্টএন্ড থেকে সরাসরি Firebase SDK ব্যবহার করেছি — Security Rules দিয়ে সুরক্ষিত। কিন্তু কিছু কাজ আছে যা ফ্রন্টএন্ড থেকে করা ঠিক না — যেমন Security Rules বাইপাস করে পুরো ডেটাবেজ অ্যাক্সেস করা, বা একটা সিক্রেট থার্ড-পার্টি API-এর সাথে Firebase ডেটা মেলানো। এই পর্বে শিখব Cloudflare Worker থেকে Firebase-এর সাথে নিরাপদে কথা বলা।
কেন Worker থেকে Firebase দরকার হতে পারে
- Admin-level অ্যাক্সেস — Security Rules উপেক্ষা করে সরাসরি পূর্ণ অ্যাক্সেস দরকার হলে (Firebase এর হাতেখড়ি পর্ব ১১-এ Cloud Functions-এ যেমন
firebase-adminব্যবহার করেছিলাম, এখানে Worker দিয়েও একই কাজ করা যায়) - একাধিক সার্ভিস মেলানো — যেমন একটা পেমেন্ট গেটওয়ে থেকে রেসপন্স পেয়ে Firebase-এ ডেটা আপডেট করা
- Rate limiting ও ক্যাশিং — RTDB-তে বারবার একই রিকোয়েস্ট না পাঠিয়ে Worker-এ ক্যাশ করে রাখা
মনে রাখা জরুরি: সাধারণ Auth, Read, Write-এর জন্য ফ্রন্টএন্ড SDK + Security Rules-ই যথেষ্ট (Firebase এর হাতেখড়ি পর্ব ৮)। Worker দিয়ে Firebase অ্যাক্সেস শুধু তখনই দরকার যখন সত্যিই সার্ভার-সাইড নিয়ন্ত্রণ লাগে।
পদ্ধতি — REST API দিয়ে RTDB অ্যাক্সেস
Cloudflare Workers-এ Node.js-এর মতো সব npm প্যাকেজ সরাসরি চলে না (Workers একটা ভিন্ন runtime, V8 isolate-ভিত্তিক)। তাই সবচেয়ে সহজ ও নির্ভরযোগ্য পদ্ধতি হলো — Firebase-এর REST API সরাসরি fetch() দিয়ে কল করা।
RTDB-এর REST API খুবই সহজ — যেকোনো path-এর শেষে .json যোগ করলেই সেটা একটা সাধারণ HTTP endpoint হয়ে যায়।
// Worker থেকে বই তালিকা পড়া
export default {
async fetch(request, env, ctx) {
const dbUrl = "https://my-first-app-default-rtdb.firebasedatabase.app/books.json";
const response = await fetch(dbUrl);
const books = await response.json();
return new Response(JSON.stringify(books), {
headers: { "content-type": "application/json" },
});
},
};
লক্ষ্য করুন — এটা ঠিক পর্ব ৫-এর fetch()-ভিত্তিক প্যাটার্নেরই একটা প্রয়োগ, শুধু এবার URL-টা Firebase-এর।
Admin অ্যাক্সেস — Secret দিয়ে প্রমাণীকরণ
উপরের কোড শুধু তখনই কাজ করবে যদি সেই path-এর Security Rules-এ পাবলিক read থাকে (পর্ব ৮-এর ".read": true)। যদি Rules বাইপাস করে পূর্ণ অ্যাক্সেস দরকার হয়, তাহলে RTDB-এর একটা Database Secret লাগবে।
- Firebase Console-এ Project Settings → Service Accounts → Database secrets-এ যান (পুরনো লিগ্যাসি সিস্টেম, তবে Worker-এর জন্য সহজ)
- একটা সিক্রেট জেনারেট করুন, কপি করে রাখুন
- রিকোয়েস্টের URL-এ
?auth=প্যারামিটার হিসেবে যোগ করুন
export default {
async fetch(request, env, ctx) {
const dbUrl = `https://my-first-app-default-rtdb.firebasedatabase.app/books.json?auth=${env.FIREBASE_DB_SECRET}`;
const response = await fetch(dbUrl, {
method: "POST",
body: JSON.stringify({ title: "নতুন বই", ownerId: "admin" }),
});
const result = await response.json();
return new Response(JSON.stringify(result), {
headers: { "content-type": "application/json" },
});
},
};
এখানে env.FIREBASE_DB_SECRET — এটাই এই পর্বের সবচেয়ে গুরুত্বপূর্ণ অংশ, কারণ এই সিক্রেট কখনো কোডে সরাসরি লেখা যাবে না।
সিক্রেট নিরাপদে সংরক্ষণ করা
Worker-এর নিজস্ব সিক্রেট ম্যানেজমেন্ট সিস্টেম আছে — GitHub Secrets-এর (পর্ব ২) মতোই ধারণা, কিন্তু Cloudflare-এর নিজের জায়গায়।
# টার্মিনাল থেকে সিক্রেট যোগ করা wrangler secret put FIREBASE_DB_SECRET # একটা প্রম্পট আসবে, সেখানে সিক্রেট মান পেস্ট করলেই এনক্রিপ্টেড হয়ে সেভ হয়
এই সিক্রেট Cloudflare-এর সার্ভারে এনক্রিপ্টেড থাকে, কোডে বা Git হিস্টোরিতে কখনো দেখা যায় না — শুধু env.FIREBASE_DB_SECRET দিয়ে রানটাইমে অ্যাক্সেস করা যায়।
বাস্তব উদাহরণ — একটা প্রক্সি API
একটা সম্পূর্ণ উদাহরণ — Worker একটা "middle-man" হিসেবে কাজ করছে, ফ্রন্টএন্ড থেকে সরাসরি Firebase Database Secret কখনো এক্সপোজ না করেই।
const corsHeaders = {
"Access-Control-Allow-Origin": "https://arifstack.com",
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
};
export default {
async fetch(request, env, ctx) {
if (request.method === "OPTIONS") {
return new Response(null, { headers: corsHeaders });
}
const url = new URL(request.url);
if (url.pathname === "/api/admin-books" && request.method === "GET") {
const dbUrl = `https://my-first-app-default-rtdb.firebasedatabase.app/books.json?auth=${env.FIREBASE_DB_SECRET}`;
const res = await fetch(dbUrl);
const books = await res.json();
return new Response(JSON.stringify(books), {
headers: { "content-type": "application/json", ...corsHeaders },
});
}
return new Response("পেজ পাওয়া যায়নি", { status: 404, headers: corsHeaders });
},
};
এখানে পর্ব ৫-এর রুটিং, CORS হেডার, আর এই পর্বের সিক্রেট-ভিত্তিক Firebase কল — সবকিছু একসাথে জোড়া লেগেছে।
ইন্টারেক্টিভ — Proxy Flow দেখো
নিচে দেখো ফ্রন্টএন্ড থেকে Worker হয়ে Firebase পর্যন্ত রিকোয়েস্ট কীভাবে যায়, আর কেন এই "মাঝখানের" ধাপটা সিক্রেট সুরক্ষিত রাখে।
🔒 চিহ্নিত ধাপগুলোই সেই জায়গা যেখানে সিক্রেট ব্যবহার হয় — লক্ষ্য করো এটা কখনো ফ্রন্টএন্ড পর্যন্ত পৌঁছায় না।
ভালো অভ্যাস
- যেখানে ফ্রন্টএন্ড SDK + Rules যথেষ্ট, সেখানে Worker দরকার নেই — অপ্রয়োজনীয় জটিলতা বাড়ানো এড়িয়ে চলুন
- Database Secret সবসময়
wrangler secret putদিয়ে যোগ করুন, কখনো কোডে বাwrangler.toml-এ লিখবেন না - CORS-এ নির্দিষ্ট origin রাখুন — এই Worker-ই যেহেতু সিক্রেট অ্যাক্সেস দিচ্ছে, সবার জন্য খোলা রাখা আরও ঝুঁকিপূর্ণ
নিজে চেষ্টা করো
Exercise:
- নিজের RTDB-এর একটা পাবলিক-read নোড থেকে সাধারণ
fetch()দিয়ে Worker-এ ডেটা আনো (সিক্রেট ছাড়াই)। - Firebase Console থেকে একটা Database Secret জেনারেট করো,
wrangler secret putদিয়ে Worker-এ যোগ করো। - সেই সিক্রেট দিয়ে এমন একটা নোডে লেখো যেখানে Security Rules-এ পাবলিক write বন্ধ — যাচাই করো Worker দিয়ে ঠিকই লেখা যাচ্ছে।
- উপরের প্রক্সি প্যাটার্ন নিজের একটা Pages প্রজেক্ট থেকে কল করে দেখো, CORS ঠিকমতো কাজ করছে কিনা।
পরের পর্বে যা থাকছে
পরের পর্বে আমরা ঢুকব Cloudflare-এর নিজস্ব স্টোরেজ সার্ভিসে — R2 পরিচিতি, যা ফাইল ও ইমেজ স্টোরেজের জন্য Firebase Storage-এর একটা শক্তিশালী বিকল্প, বিশেষ করে egress ফি না থাকার কারণে।