কম্পিউটার টিউটোরিয়াল

Vercel Edge Functions এবং আপস্ট্যাশ রেডিস দিয়ে ডেটা লিক প্রতিরোধ: নিরাপদ, লো-লেটেন্সি ফিল্টারিং

ইন্টারনেটে ডেটা লিক একটি বড় সমস্যা। Statista-র মতে, ২০২২ সালে একক ৪০ কোটি বেশি মানুষ ডেটা লিকের আশ্রয়িত হন। কেউই চায় না তাদের ডেটা ইন্টারনেটে সর্বত্র ছড়িয়ে পড়ে। তাই ব্যবহারকারীর গোপনীয়তা মেনে নিরাপদ অ্যাপ্লিকেশন বানানো অনেক শিল্পে অত্যন্ত গুরুত্বপূর্ণ।

লিক প্রতিরোধের একটি উপায় হলো সমস্যাযুক্ত ডেটা অন্য সার্ভিস বা ব্যবহারকারীদের কাছে ডেলিভার করার আগে ফিল্টার করে দেওয়া। এই পদ্ধতিতে আপ-টু-ডেট ফিল্টার রয়ে যাতে ডেটা ফাঁক পড়ে না যাবে, এবং লো-লেটেন্সি ইনফ্রাস্ট্রাকচার যাতে ফিল্টারিং-এর পারফরম্যান্স ইম্প্যাক্ট যতটা সম্ভব কম থাকে।

আপস্ট্যাশ ফর রেডিস® এবং Vercel Edge Functions একটি শক্তিশালী টিম গঠন করে যা উভয় শর্তেই খরা উতরে এই সমস্যা সমাধান করতে। এই দুটি লো-লেটেন্সি সার্ভারলেস সমাধান আমাদের ব্যবহারকারীদের কাছাকাছি ডিপ্লয় করা যেতে পারে। Vercel-এর নতুন cron ফিচারের সাথে, আমরা নিশ্চিত করতে পারি ফিল্টার ডেটা নিয়মিত আপডেট হয়।

একটি ফিল্টার কীভাবে কাজ করতে পারে তা বোঝাতে, আমরা একটি ফ্রন্টএন্ড এবং ব্যাকএন্ড তৈরি করব যা এই সার্ভারলেস এজ টেকনোলজি ব্যবহার করে অশ্লীল শব্দ ফিল্টার করে।

ফিচারসমূহ

অ্যাপটি Vercel-এর cron ফিচার ব্যবহার করে একটি রিমোট API থেকে বর্তমান অশ্লীল শব্দগুলো আপস্ট্যাশ ফর রেডিস ডেটাবেসে আপডেট করবে।

আমাদের ডেটা পাওয়ার তিনটি মাধ্যম থাকবে:

  1. ফিল্টার করা টেক্সট সহ একটি ওয়েবসাইট রিটার্ন করা।
  2. একটি ডেটা স্টোর থেকে ফিল্টার করা টেক্সট সহ JSON রিটার্ন করা।
  3. টেক্সট গ্রহণ করে ফিল্টার করা টেক্সট সহ JSON ফেরত দেওয়া।

টেকনোলজি

আমরা Next.js ব্যবহার করে অ্যাপটি বানাব এবং Vercel-এ ডিপ্লয় করব; এইভাবে, Edge ফাংশন ব্যবহার করার সময় আমাদের একটি স্মুথ সার্ভারলেস ডেভেলপমেন্ট অভিজ্ঞতা হবে।

আমরা ডেটা স্টোরেজের জন্য আপস্ট্যাশ ফর রেডিস® ব্যবহার করব এর লো লেটেন্সি এবং ব্যবহারিক সুবিধার জন্য।

দুই সার্ভিসই ফ্রি টিয়ারের সাথে আসে এবং অন-ডিমান্ড প্রাইসিং আছে।

প্রয়োজনীয় শর্তসমূহ

সার্ভিসগুলোর জন্য অ্যাকাউন্ট দরকার:

  • GitHub কোড আপলোড করার জন্য যাতে Vercel ডাউনলোড এবং ডিপ্লয় করতে পারে
  • Vercel অ্যাপ্লিকেশন হোস্ট করার জন্য, হোম পেজ এবং Edge ফাংশন সহ
  • আপস্ট্যাশ ফিল্টার করতে চাওয়া শব্দের তালিকা সংরক্ষণ করার জন্য

বাস্তবায়ন

শুরু করতে, আমরা একটি নতুন GitHub রিপোজিটরি তৈরি করব এবং নিশ্চিত করব। "Add a README file" চেক করব, যাতে এটি খালি না থাকে। যেহেতু রিপোজিটরি খালি নয়, GitHub আমাদের কোডস্পেস শুরু করার অনুমতি দেবে, যা Node.js এবং Git-to-GitHub কানেকশন দিয়ে প্রিকনফিগারড থাকে।

Vercel Edge Functions এবং আপস্ট্যাশ রেডিস দিয়ে ডেটা লিক প্রতিরোধ: নিরাপদ, লো-লেটেন্সি ফিল্টারিং Figure 1: Start Codespace

প্রথমে, আমাদের একটি নতুন Next.js প্রজেক্ট তৈরি করতে হবে এবং আপস্ট্যাশ রেডিস ক্লায়েন্ট ইনস্টল করতে হবে নিচের কমান্ডগুলো দিয়ে:

$ npx create-next-app@latest --typescript
$ npm i @upstash/redis

রিফ্রেশ ফাংশন বাস্তবায়ন

প্রথম ফিচার যা আমরা বাস্তবায়ন করব তা হলো আমাদের খারাপ শব্দের তালিকা রিফ্রেশ করার ফাংশন। সেটির জন্য, pages/api/refresh-list.ts-এ একটি নতুন ফাইল তৈরি করুন নিচের কন্টেন্টসহ:

File pages/api/refresh-list.ts:

import { Redis } from "@upstash/redis";
export const config = {
  runtime: "edge"
};
const redisClient = new Redis({
  url: process.env.UPSTASH_REDIS_URL,
  token: process.env.UPSTASH_REDIS_TOKEN,
});
export default async function handler() {
  const wordResponse = await fetch(
    "https://raw.githubusercontent.com/kay-is/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/master/en",
  );
  const words = await wordResponse.text();
  const redisCommands = redisClient.pipeline();
  words
    .trim()
    .split("\n")
    .forEach((word) => redisCommands.sadd("words", word));
  await redisCommands.exec();
}

আমরা ফাংশনটি Edge-এ রান করার জন্য কনফিগার করছি। এটি এখানে অপরিহার্য নয় কারণ এই ফাংশন ব্যাকগ্রাউন্ডে চলবে, কিন্তু Vercel Edge Functions Cloudflare Workers দ্বারা চালিত, যা আমাদের fetch মেথড ব্যবহার করতে দেয়, যা Node.js নেটিভলি সাপোর্ট করে না।

হ্যান্ডলার একটি টেক্সট ফাইল থেকে খারাপ শব্দগুলো লোড করবে আপস্ট্যাশ রেডিসে। পাইপলাইন ফিচার নিশ্চিত করে যে আমরা সব রেডিস কমান্ডগুলো একটি রিকোয়েস্টে পাঠাচ্ছি।

আমরা একটি সেট ব্যবহার করছি শব্দগুলো সংরক্ষণ করার জন্য, যাতে ডুপ্লিকেট না হয়। এটি পরে একটি কমান্ডে সব শব্দগুলো স্ট্রিং অ্যারে হিসেবে লোড করতে সক্ষম করে।

আমরা যদি ব্যক্তিগত ডেটা ফিল্টার করতে চাই, তবে আমরা একটি অ্যাকাউন্ট ডেটাবেস ব্যবহার করতে পারি আমাদের ব্যবহারকারীদের ইমেইল, ফোন নম্বর, নাম এবং ঠিকানা পাওয়ার জন্য ফিল্টারের বেসিস হিসেবে।

Vercel কে বলতে হবে আমরা এই ফাংশনটি একটি ক্রন ফাংশন হিসেবে চাই, সেটির জন্য প্রজেক্ট রুটে একটি vercel.json ফাইল তৈরি করতে হবে নিচের কন্টেন্টসহ:

File vercel.json:

{
  "crons": [
    {
      "path": "/api/refresh-list",
      "schedule": "0 10 * * *"
    }
  ]
}

এই কনফিগ Vercel কে প্রতিদিন ১০:০০ UTC-তে refresh-list ফাংশন এক্সিকিউট করতে বাধ্য করবে।

ফ্রি Vercel অ্যাকাউন্ট শুধু একটি অটোমেটিক এক্সিকিউশন প্রতি দিন সাপোর্ট করে। আমাদের উদাহরণের জন্য এটা যথেষ্ট, কিন্তু আপনার ডেটা যদি আরও ঘন ঘন পরিবর্তন হয়, আপডেট রেট বাড়াতে হবে।

ফিল্টার ইউটিলিটি বাস্তবায়ন

পরবর্তী ফিচার হলো একটি ইউটিলিটি ফাংশন যা টেক্সটের শব্দগুলো মাস্ক করবে যখন সেগুলো আমাদের ডেটাবেসের শব্দগুলোর সাথে মিলে যাবে। utils/word-filter.ts-এ একটি নতুন ফাইল তৈরি করুন এবং নিচের কোড যোগ করুন।

File utils/word-filter.ts:

import { Redis } from "@upstash/redis";
const redisClient = new Redis({
  url: process.env.UPSTASH_REDIS_URL,
  token: process.env.UPSTASH_REDIS_TOKEN,
});
export async function filter(text: string) {
  const filteredWords = await redisClient.smembers("words");
  let maskedText = text;
  for (let word of filteredWords)
    maskedText = maskedText.replaceAll(new RegExp(word, "gi"), "[REDACTED]");
  return maskedText;
}

আবার, ফাংশনটি আপস্ট্যাশ রেডিস ক্লায়েন্ট ব্যবহার করে, কিন্তু এইবার এটি আগে সংরক্ষিত ডেটা লোড করে।

যেহেতু আমরা স্ট্রিং এর একটি অ্যারে পাই, আমরা সিম্পলি এর ওপর লুপ চালিয়ে একটি রিপ্লেসমেন্ট ফাংশন কল করতে পারি যা টেক্সটের প্রতিটি খারাপ শব্দকে "[REDACTED]"-এর সাথে রিপ্লেস করে।

এই ফাংশনটি কোনো এহাম্বশ্না করছে না যে এটি কী ধরনের শব্দ ফিল্টার করছে। এই কেসে, শব্দগুলো "not safe for work", কিন্তু ফিল্টার প্রসেসটি শুধু আমাদের আগে সংরক্ষিত ডেটার ওপর নির্ভরশীল।

হোম পেজ বাস্তবায়ন

ফিল্টারটি একশনে দেখতে, pages/index.ts-এর কন্টেন্ট নিচের কোড দিয়ে রিপ্লেস করুন:

File pages/index.ts:

import Head from "next/head";
import { filter } from "@/utils/word-filter";
export const config = {
  runtime: "experimental-edge"
};
interface HomeProps {
  maskedText: string;
}
export default function Home(props: HomeProps) {
  return (
    <>
      
        Text with Filtered Words
      
      

Text with Filtered Words

{props.maskedText}

); } export async function getServerSideProps(): Promise<{ props: HomeProps }> { const maskedText = await filter( "He slipped and fell on his butt. Well, that wasn't very sexy." ); return { props: { maskedText } }; }

কনফিগ নিশ্চিত করে সব কিছু Edge-এ এক্সিকিউট হচ্ছে, এমনকি সার্ভার-সাইড রেন্ডারিংও। এই Vercel ফিচারটি এখনও এক্সপেরিমেন্টাল।

দিলচস্প অংশ হলো getServerSideProps ফাংশন, যা আমাদের আগের filter ফাংশন ব্যবহার করে একটি স্ট্যাটিক টেক্সটের ওপর। এটি শুধু সার্ভারে কল হয়, তাই আনফিল্টারড ডেটা কখনো ক্লায়েন্টের কাছে যায় না।

একটি রিয়েল অ্যাপ্লিকেশনে, এই টেক্সটটি একটি ডেটাবেস থেকে আসতে পারে যেটে ব্যক্তিগত ডেটা থাকে যা প্রদর্শনের আগে ক্লিন আপ করা দরকার।

প্রথম API রুট বাস্তবায়ন

প্রথম API রুট হোম পেজের মতো কাজ করে; এটি JSON রিটার্ন করে এবং কোনো HTML নয়। pages/api/filtered-data.ts-এ একটি ফাইল তৈরি করুন এই কোডসহ:

File pages/api/filtered-data.ts:

import { filter } from "@/utils/word-filter";
export const config = {
  runtime: "edge"
};
export default async function handler() {
  const maskedText = await filter(
    "He slipped and fell on his butt. Well, that wasn't very sexy.",
  );
  return new Response(JSON.stringify({ text: maskedText }), {
    status: 200,
    headers: {
      "content-type": "application/json"
    },
  });
}

আবার, রানটাইম Edge, এবং getServerSideProps ফাংশনের মতো, আমরা একটি স্ট্যাটিক টেক্সট ব্যবহার করছি।

দ্বিতীয় API রুট বাস্তবায়ন

এই রুট টেক্সট রিকোয়েস্টের মাধ্যমে গ্রহণ করে এবং ফিল্টার করা ভার্সন ফেরত দেয়। pages/api/filter.ts-এ একটি নতুন ফাইল তৈরি করুন এবং নিচের কোড যোগ করুন:

File pages/api/filter.ts:

import type { NextApiRequest } from "next";
import { filter } from "@/utils/word-filter";
export const config = {
  runtime: "edge"
};
export default async function handler(request: NextApiRequest) {
  const { text } = await new Response(request.body).json();
  const maskedText = await filter(text);
  return new Response(JSON.stringify({ text: maskedText }), {
    status: 200,
    headers: {
      "content-type": "application/json"
    },
  });
}

এবার, আমাদের রিকোয়েস্ট বডি পার্স করতে হবে যাতে ফিল্টার করতে চাওয়া টেক্সটটি পাওয়া যায়। Vercel-এর Edge Functions-এ, body একটি ReadableStream; যদি আমরা এটি একটি Response-এ কনভার্ট করি, আমরা নেটিভ JSON পার্সার ব্যবহার করে ডেটা এক্সট্র্যাক্ট করতে পারি।

রিকোয়েস্ট থেকে ডেটা পাওয়ার পর, সব কিছু আগের মতো কাজ করে।

কোড পরিবর্তন পুশ করা

এখন সব কিছু বাস্তবায়ন হয়ে গেলে, আমাদের কোডটি আমাদের GitHub রিপোজিটরিতে পুশ করতে হবে এই কমান্ডগুলো দিয়ে:

$ git add -A
$ git commit -m "Init"
$ git push

এটি করার পর, কোডটি অনলাইনে উপলব্ধ থাকবে Vercel ডাউনলোড এবং ডিপ্লয় করার জন্য।

ডিপ্লয়মেন্ট

আমাদের একটি আপস্ট্যাশ রেডিস ডেটাবেস তৈরি করতে হবে, এনভায়রনমেন্ট ভেরিয়েবলগুলোর জন্য ক্রেডেনশিয়াল পাওয়ার জন্য এবং একটি Vercel প্রজেক্ট।

রেডিস ডেটাবেস তৈরি করা

আপস্ট্যাশ কনসোলে "Create database" বাটনে ক্লিক করে একটি নতুন রেডিস ডেটাবেস তৈরি করতে পারি। Figure 2 কনফিগারেশন দেখাচ্ছে। এই উদাহরণের জন্য, একটি রিজনাল ডেটাবেস যথেষ্ট, কিন্তু আপনার যদি গ্লোবালি বিতরণ করা ব্যবহারকারী থাকে এবং লেটেন্সি কম রাখতে চান, তবে আপনি গ্লোবাল টাইপও বেছে নিতে পারেন।

Vercel Edge Functions এবং আপস্ট্যাশ রেডিস দিয়ে ডেটা লিক প্রতিরোধ: নিরাপদ, লো-লেটেন্সি ফিল্টারিং

Figure 2: Create a new database

তैयার হওয়ার পর, আমরা REST API ক্যাটেগরি আন্ডারে আমাদের এনভায়রনমেন্ট ভেরিয়েবলগুলোর জন্য প্রয়োজনীয় URL এবং টোকেন পেতে পারি; এটি Figure 3-র মতো দেখাবে।

Vercel Edge Functions এবং আপস্ট্যাশ রেডিস দিয়ে ডেটা লিক প্রতিরোধ: নিরাপদ, লো-লেটেন্সি ফিল্টারিং

Figure 3: Database credentials

Vercel প্রজেক্ট তৈরি করা

একটি নতুন Vercel প্রজেক্ট তৈরি করতে, ব্রাউজারে Vercel Dashboard খুলুন, এবং সেন্টারে "Create a New Project"-এ ক্লিক করুন। GitHub-এর সাথে Vercel কানেক্ট করার পর, আপনি ইম্পোর্ট করার জন্য একটি রিপোজিটরি বেছে নিতে পারেন।

আমরা ডিফল্ট কনফিগারেশন রাখতে পারি এবং উপরের ধাপ থেকে আপস্ট্যাশ রেডিস ক্রেডেনশিয়াল দিয়ে আমাদের এনভায়রনমেন্ট ভেরিয়েবলগুলো যোগ করতে পারি। Figure 4 রেফারেন্সের জন্য Vercel-এর ক্রিয়েশন UI দেখাচ্ছে।

Vercel Edge Functions এবং আপস্ট্যাশ রেডিস দিয়ে ডেটা লিক প্রতিরোধ: নিরাপদ, লো-লেটেন্সি ফিল্টারিং

Figure 4: Vercel project creation

এনভায়রনমেন্ট ভেরিয়েবলগুলোর নাম হলো UPSTASH_REDIS_URL এবং UPSTASH_REDIS_TOKEN। আমরা আগের ধাপের মানগুলো ব্যবহার করে এগুলো তৈরি করব।

"Deploy"-এ ক্লিক করার পর Vercel আমাদের GitHub রিপোজিটরি থেকে কোড ডাউনলোড এবং ডিপ্লয় করবে।

অ্যাপ টেস্ট করা

ডিপ্লয়মেন্টের পর, অ্যাপটি এখনো আনফিল্টারড শব্দ দেখাবে যেহেতু ক্রন জব এখনো রান করেনি। কিন্তু আমরা প্রথম এক্সিকিউশন ম্যানুয়ালি করতে পারি। "Continue to Dashboard" বাটনে ক্লিক করুন এবং "Cron Jobs" ট্যাব বেছে নিন।

এখানে আমাদের /api/refresh-list ফাংশনটি একটি "Run" বাটনের সাথে দেখতে পাবেন।

ফাংশনটি ফিনিশ হলে, "Project" ট্যাবে নেভিগেট করুন এবং "Domain" আন্ডারের যেকোনো URL-এ ক্লিক করুন। এটি ব্রাউজারে ফিল্টার করা টেক্সট সহ ওয়েবসাইটটি খুলবে; এটি Figure 5-র মতো দেখাবে।

Vercel Edge Functions এবং আপস্ট্যাশ রেডিস দিয়ে ডেটা লিক প্রতিরোধ: নিরাপদ, লো-লেটেন্সি ফিল্টারিং Figure 5: Filtered website

আমাদের URL-এ /api/filtered-data অ্যাড করলে, আমরা দেখতে পাব এটি API রেসপন্সের জন্যও কাজ করে। সেগুলোর দেখতে এমনই হবে:

{
  "text": "He slipped and fell on his [REDACTED]. Well, that wasn't very [REDACTED]y."
}

শেষে, যদি আমরা /api/filter এন্ডপয়েন্টে cURL ব্যবহার করে একটি রিকোয়েস্ট পাঠাই, আমরা আমাদের কাস্টম টেক্সট ফিল্টার করা পাব। &lt;PROJECT>-কে আপনার Vercel প্রজেক্ট দিয়ে রিপ্লেস করতে ভুলবেন না।

$ curl -X POST https://<PROJECT>.vercel.app/api/filter \
 -H "Content-Type: application/json" \
 -d '{"text":"He fell on his butt."}' 

রেসপন্স:

{
  "text": "He fell on his [REDACTED]."
}

পরবর্তী কী

এই টিউটোরিয়ালের পর, আপনি ভাবতে পারেন ডেটা আপডেট হলে কিন্তু ক্রন জব ডেটাবেস আপডেট না করলে কী হবে? ভালো পর্যবেক্ষণ!

একটি ক্রন জব আমাদের রিফ্রেশ ফাংশন ট্রিগার করে, কিন্তু এটা এখনো একটি রেগুলার API ফাংশন, তাই আমরা যেভাবেই চাই সেভাবে কল করতে পারি।

একটি রিয়েল ডেটা ফিল্টারের কেসে, আমরা হয়তো ডেটা পরিবর্তনের প্রতিক্রিয়াস্বরূপ ফাংশনটি ট্রিগার করতে চাই, কিন্তু বাস্তবায়নের ডিটেইলস একদম নির্ভর করে আমরা ফিল্টারের বেসিস হিসেবে কোন ডেটা স্টোরেজ ব্যবহার করছি সেটার ওপর। তাই এটি মনে রাখুন বানানোর সময়!

অতিরিক্ত রিসোর্স

আপনি GitHub-এ সম্পূর্ণ প্রজেক্ট পেতে পারেন।

  1. রুবি WebSocket সার্ভার স্ক্র্যাচ থেকে বানান: ধাপে ধাপে গাইড

  2. HTML DOM parentElement প্রোপার্টি

  3. অ্যান্ড্রয়েডে StringBuffer ক্লাস ব্যবহার করার পদ্ধতি

  4. বৃত্তে 'k' সমদূরবর্তী বিন্দুর মধ্যে ২টি বিন্দু দিয়ে……、 কোণের গণনা (C++ প্রোগ্রাম)