Cloudflare Workers برای توسعهدهندگان ASP.NET Core؛ بخش سوم: ذخیرهسازی و مدیریت حالت در Edge
نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۰۵/۲۳ ۰۸:۱۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
IMemoryCache برای کش، و از سرویسهایی مانند Azure Blob Storage یا Amazon S3 برای ذخیرهسازی فایلها استفاده میکردیم. در این بخش، با سه سرویس قدرتمند Cloudflare آشنا میشویم که به ما اجازه میدهند این وظایف را به لبه شبکه (Edge) منتقل کنیم و به عملکردی بینظیر دست یابیم.Dictionary در #C یا یک نمونه Redis دارید، با این تفاوت که این دیکشنری به صورت خودکار در صدها دیتاسنتر در سراسر جهان توزیع شده است. این دقیقاً همان کاری است که Cloudflare KV انجام میدهد.wrangler kv:namespace create "URL_STORE"
[[kv_namespaces]] binding = "URL_STORE" id = "..." preview_id = "..."
env.URL_STORE به آن دسترسی پیدا کنید.POST request یک URL بلند را میگیرد، یک کد کوتاه تصادفی تولید میکند و آن را در KV ذخیره میکند.GET request با کد کوتاه، URL بلند را از KV میخواند و کاربر را به آن ریدایرکت میکند.export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
if (request.method === 'POST') {
// ۱. دریافت URL بلند از بدنه درخواست
const longUrl = await request.text();
if (!longUrl) return new Response('Missing URL in body', { status: 400 });
// ۲. تولید یک کد کوتاه تصادفی
const shortCode = Math.random().toString(36).substring(2, 8);
// ۳. ذخیره در KV
await env.URL_STORE.put(shortCode, longUrl);
return new Response(`Your short URL is: ${url.origin}/${shortCode}`);
}
if (request.method === 'GET') {
// ۴. دریافت کد کوتاه از مسیر
const shortCode = url.pathname.slice(1);
if (!shortCode) return new Response('Homepage - POST a URL to shorten it.', { status: 404 });
// ۵. خواندن از KV
const longUrl = await env.URL_STORE.get(shortCode);
if (!longUrl) {
return new Response('Short URL not found', { status: 404 });
}
// ۶. ریدایرکت کاربر
return Response.redirect(longUrl, 302);
}
return new Response('Method not allowed', { status: 405 });
},
};
interface Env {
URL_STORE: KVNamespace;
}wrangler r2 bucket create "USER_UPLOADS"
wrangler.toml:[[r2_buckets]] binding = "USER_UPLOADS" bucket_name = "USER_UPLOADS" preview_bucket_name = "USER_UPLOADS"
PUT request فایل را در بدنه خود دریافت کرده و مستقیماً در R2 ذخیره میکند.GET request فایل را از R2 میخواند و برای کاربر ارسال میکند.export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const objectKey = url.pathname.slice(1);
if (request.method === 'PUT') {
// ۱. آپلود مستقیم بدنه درخواست در R2
await env.USER_UPLOADS.put(objectKey, request.body);
return new Response(`Object ${objectKey} uploaded successfully!`);
}
if (request.method === 'GET') {
// ۲. دریافت آبجکت از R2
const object = await env.USER_UPLOADS.get(objectKey);
if (object === null) {
return new Response('Object Not Found', { status: 404 });
}
// ۳. ساخت پاسخ با هدرهای مناسب
const headers = new Headers();
object.writeHttpMetadata(headers);
headers.set('etag', object.httpEtag);
// ۴. ارسال بدنه آبجکت (فایل) به کاربر
return new Response(object.body, { headers });
}
return new Response('Method Not Allowed', { status: 405 });
},
};
interface Env {
USER_UPLOADS: R2Bucket;
}Cache-Control را به پاسخها اضافه میکند. کلادفلر به صورت پیشفرض نیز بسیاری از محتوا را بر اساس همین هدرها کش میکند.export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
// ۱. دسترسی به کش پیشفرض Edge
const cache = caches.default;
// ۲. بررسی وجود درخواست در کش
let response = await cache.match(request);
if (response) {
console.log('Cache HIT!');
// ۳. اگر در کش بود، همان را برگردان
return response;
}
console.log('Cache MISS!');
// ۴. اگر در کش نبود، درخواست را به سرور اصلی بفرست
response = await fetch(request);
// ۵. یک کپی قابل تغییر از پاسخ بساز تا بتوانیم هدرها را تغییر دهیم
response = new Response(response.body, response);
// ۶. تنظیم هدر برای کش شدن در شبکه کلادفلر به مدت ۶۰ ثانیه
response.headers.set('Cache-Control', 's-maxage=60');
// ۷. پاسخ را در کش ذخیره کن. ctx.waitUntil باعث میشود این کار در پسزمینه انجام شود
// و کاربر منتظر اتمام آن نماند.
ctx.waitUntil(cache.put(request, response.clone()));
// ۸. پاسخ را به کاربر برگردان
return response;
},
};