Last-Modified একটি HTTP রেসপন্স হেডার যা সার্ভারে রিসোর্সের শেষ পরিবর্তনের তারিখ এবং সময় নির্দেশ করে, যা ক্লায়েন্টকে If-Modified-Since এর মাধ্যমে শর্তসাপেক্ষ অনুরোধ করতে দেয়। যদি নির্দিষ্ট তারিখের পর থেকে রিসোর্স পরিবর্তিত না হয়, সার্ভার রেসপন্স বডি না পাঠিয়ে 304 Not Modified রিটার্ন করে, যা ব্যান্ডউইথ যথেষ্ট পরিমাণে সাশ্রয় করে। RFC 7232 (IETF, 2014) অনুসারে, Last-Modified-এর সাথে শর্তসাপেক্ষ অনুরোধ পুনরায় ভিজিটে পৃষ্ঠা লোডের সময় 30-60% হ্রাস করে। হেডারটি বেশিরভাগ HTTP সার্ভার এবং প্রক্সি দ্বারা স্বয়ংক্রিয়ভাবে সমর্থিত।
মূল পয়েন্ট
Last-Modified একটি HTTP হেডার যা শর্তসাপেক্ষ অনুরোধ হেডারের গ্রুপের অন্তর্গত। সার্ভার এটি GET বা HEAD-এর উত্তরে যোগ করে, HTTP-date ফরম্যাটে অনুরোধ করা রিসোর্সের শেষ পরিবর্তনের তারিখ এবং সময় নির্দেশ করে: Last-Modified: Wed, 02 Jul 2025 14:30:00 GMT। ক্লায়েন্ট (ব্রাউজার, মোবাইল অ্যাপ্লিকেশন, প্রক্সি) ক্যাশড রিসোর্সের সাথে এই তারিখ সংরক্ষণ করে। পুনরায় অনুরোধে, ক্লায়েন্ট একই তারিখসহ If-Modified-Since হেডার পাঠায়, এবং সার্ভার এটি রিসোর্সের বর্তমান পরিবর্তনের সময়ের সাথে তুলনা করে।
Last-Modified-এর সাথে শর্তসাপেক্ষ অনুরোধ প্রোটোকল RFC 7232-এ সংজ্ঞায়িত এবং সমস্ত আধুনিক HTTP সার্ভার দ্বারা সমর্থিত। তারিখের ফরম্যাট কঠোরভাবে নিয়ন্ত্রিত — শুধুমাত্র GMT (গ্রিনউইচ মিন টাইম) সময় অঞ্চল নির্দেশ ছাড়া। সার্ভারকে তিনটি সম্ভাব্য ফরম্যাটে তারিখ ফেরত দিতে হবে: RFC 1123 (স্ট্যান্ডার্ড), RFC 850 (অপ্রচলিত) বা ANSI C asctime। বাস্তবে, প্রায় সব সার্ভার ২৯ অক্ষরের নির্দিষ্ট দৈর্ঘ্যের RFC 1123 ফরম্যাট ব্যবহার করে।
Last-Modified ক্যাশিং ভ্যালিডেশন মেকানিজমের বিভাগের অন্তর্গত: এটি ক্লায়েন্টকে বলে না যে রেসপন্স ক্যাশ করা যাবে কিনা, বরং ইতিমধ্যে ক্যাশ করা রিসোর্সের বৈধতা পরীক্ষার একটি টুল সরবরাহ করে। ক্যাশিং নীতি আলাদাভাবে Cache-Control হেডারের মাধ্যমে নির্ধারিত হয়। Akamai (2025)-এর একটি গবেষণা অনুসারে, Cache-Control-এর সাথে Last-Modified-এর সঠিক কনফিগারেশন স্ট্যাটিক কন্টেন্টের জন্য মূল সার্ভারের লোড ৭০% পর্যন্ত কমায়।
Last-Modified হেডার HTTP/1.0 (RFC 1945, 1996)-এ সংজ্ঞায়িত হয়েছিল এবং ওয়েবে ক্যাশিং ব্যবস্থাপনার প্রথম প্রক্রিয়াগুলির মধ্যে একটি হয়ে ওঠে। HTTP/1.1-এ ETag আসার আগে, এটি শর্তসাপেক্ষ অনুরোধ করার একমাত্র উপায় ছিল। বয়স সত্ত্বেও, হেডারটি তার সরলতার কারণে প্রাসঙ্গিক রয়ে গেছে — সার্ভারকে কন্টেন্ট হ্যাশ গণনা করতে হবে না, শুধু ফাইল সিস্টেম থেকে ফাইল টাইমস্ট্যাম্প বা ডাটাবেস থেকে updated_at ফিল্ড পড়তে হবে।
সম্পূর্ণ চক্রটি তিনটি ধাপে সম্পন্ন হয়। প্রথম অনুরোধে, সার্ভার Last-Modified হেডার এবং HTTP স্ট্যাটাস 200 OK-সহ রিসোর্স রিটার্ন করে। ক্লায়েন্ট তারিখসহ রেসপন্স ক্যাশ করে। পুনরায় অনুরোধে, ক্লায়েন্ট সংরক্ষিত তারিখসহ If-Modified-Since হেডার পাঠায়। সার্ভার এই তারিখটি রিসোর্সের বর্তমান পরিবর্তনের সময়ের সাথে তুলনা করে। যদি রিসোর্স পরিবর্তিত না হয় — খালি বডিসহ 304 Not Modified রিটার্ন করে। যদি পরিবর্তিত হয় — নতুন ডেটা এবং নতুন Last-Modified-সহ 200 OK রিটার্ন করে।
// প্রথম অনুরোধ — সার্ভার তারিখসহ রিসোর্স রিটার্ন করে
HTTP/1.1 200 OK
Content-Type: application/json
Last-Modified: Wed, 02 Jul 2025 14:30:00 GMT
[{"id": 1, "name": "Alice"}]
// পুনরায় অনুরোধ — ক্লায়েন্ট সংরক্ষিত তারিখ পাঠায়
GET /api/users HTTP/1.1
Host: example.com
If-Modified-Since: Wed, 02 Jul 2025 14:30:00 GMT
// প্রতিক্রিয়া — ডেটা পরিবর্তিত হয়নি
HTTP/1.1 304 Not Modified
মোবাইল অ্যাপ্লিকেশনের জন্য, ডেটা সিঙ্ক্রোনাইজেশনের জন্য Last-Modified বিশেষভাবে কার্যকর। অ্যাপ্লিকেশন শেষ সফল আপডেটের তারিখ সংরক্ষণ করে এবং If-Modified-Since-এ সার্ভারে পাঠায়। যদি আরও ডেটা থাকে বা তা পরিবর্তিত হয় — সার্ভার সম্পূর্ণ সেট রিটার্ন করে। যদি না হয় — 304, এবং অ্যাপ্লিকেশন লোকাল কপি ব্যবহার করে। OkHttp এবং URLSession বিল্ট-ইন ক্যাশিং সিস্টেমের মাধ্যমে স্বয়ংক্রিয়ভাবে এই প্রক্রিয়া সমর্থন করে।
স্ট্যাটিক ফাইলের জন্য, Nginx এবং Apache ফাইল সিস্টেম অ্যাট্রিবিউট — mtime (পরিবর্তনের সময়) — থেকে তারিখ নেয়। ডায়নামিক কন্টেন্টের জন্য, সার্ভার কোডকে ব্যবসায়িক যুক্তির ভিত্তিতে স্পষ্টভাবে Last-Modified সেট করতে হবে: ডাটাবেস থেকে updated_at ফিল্ড, Git-এ শেষ কমিটের তারিখ, বিল্ড আর্টিফ্যাক্ট টাইমস্ট্যাম্প। যদি Last-Modified স্পষ্টভাবে সেট না করা হয়, সার্ভার হেডার একেবারেই না-ও পাঠাতে পারে, এবং ক্লায়েন্ট তারিখ অনুসারে শর্তসাপেক্ষ অনুরোধ করতে পারবে না।
Last-Modified এবং ETag একই রকম কাজ করে — ক্লায়েন্টকে ক্যাশের বৈধতা পরীক্ষা করতে দেওয়া — তবে এদের মৌলিক পার্থক্য রয়েছে। Last-Modified টাইমস্ট্যাম্প ব্যবহার করে, ETag একটি অনন্য সংস্করণ আইডেন্টিফায়ার ব্যবহার করে। প্রতিটি পদ্ধতির নিজস্ব পরিস্থিতি রয়েছে যেখানে এটি বেশি কার্যকর, এবং HTTP স্পেসিফিকেশন উভয় হেডার একসাথে ব্যবহার করার পরামর্শ দেয়।
| মানদণ্ড | Last-Modified | ETag |
|---|---|---|
| সারমর্ম | শেষ পরিবর্তনের তারিখ | অনন্য সংস্করণ আইডেন্টিফায়ার |
| নির্ভুলতা | সেকেন্ড পর্যন্ত | বিট পর্যন্ত (হ্যাশ) |
| বাস্তবায়ন জটিলতা | কম — ফাইল সিস্টেম থেকে স্বয়ংক্রিয় | মধ্যম — হ্যাশ গণনা প্রয়োজন |
| ক্লাস্টারড সার্ভার | সমস্যা: mtime নোডে ভিন্ন হতে পারে | নোডে অভিন্ন ডেটায় স্থিতিশীল |
| রেঞ্জ সমর্থন | Range অনুরোধ প্রভাবিত করে না | রেঞ্জের জন্য শক্তিশালী ETag প্রয়োজন |
| সুপারিশ | স্ট্যাটিক ফাইল এবং সরল API-র জন্য | API যেখানে সঠিক পরীক্ষা গুরুত্বপূর্ণ |
Last-Modified-এর প্রধান সুবিধা সরলতা। সার্ভারকে কন্টেন্ট হ্যাশ গণনা করতে হয় না, যা প্রতিটি অনুরোধে CPU রিসোর্স সাশ্রয় করে। স্ট্যাটিক ফাইল বা স্পষ্ট টাইমস্ট্যাম্পযুক্ত ডেটা পরিবেশনকারী উচ্চ-ট্রাফিক প্রকল্পের জন্য, Last-Modified সর্বোত্তম পছন্দ হিসেবে থাকে। অন্যদিকে, ETag সম্পূর্ণ নির্ভুলতা দেয় — JSON রেসপন্সে একটি অক্ষর পরিবর্তন করলে ETag পরিবর্তিত হবে, কিন্তু তারিখ পরিবর্তিত নাও হতে পারে (যদি ফাইল একই সংস্করণে ওভাররাইট করা হয়)।
স্পেসিফিকেশন একসাথে উভয় হেডার ফেরত দেওয়ার পরামর্শ দেয়। সার্ভার 200 OK রেসপন্সে Last-Modified এবং ETag উভয়ই অন্তর্ভুক্ত করে। ক্লায়েন্ট উভয় শর্তসাপেক্ষ হেডার — If-Modified-Since এবং If-None-Match পাঠায়। সার্ভার প্রথমে ETag পরীক্ষা করে (এর অগ্রাধিকার রয়েছে), তারপর Last-Modified। যদি অন্তত একটি পরিবর্তনের সংকেত দেয় — সম্পূর্ণ রেসপন্স ফেরত দেওয়া হয়। এটি সর্বাধিক নমনীয়তা দেয়: ETag নির্ভুলতা নিশ্চিত করে, Last-Modified ETag সমর্থন করে না এমন ক্লায়েন্টের জন্য রিজার্ভ পরীক্ষা সরবরাহ করে।
Last-Modified-এর কনফিগারেশন সার্ভারের ধরণের উপর নির্ভর করে। Nginx এবং Apache-র জন্য, Last-Modified স্ট্যাটিক ফাইলের জন্য mtime-এর ভিত্তিতে স্বয়ংক্রিয়ভাবে সেট হয়। ডায়নামিক অ্যাপ্লিকেশনের জন্য, সার্ভার কোডে হেডার সেট করতে হবে। চলুন জনপ্রিয় প্ল্যাটফর্মে কনফিগারেশন দেখি।
// Express.js — Last-Modified সেট করা
app.get("/api/users", async (req, res) => {
const updatedAt = await getLastUpdate()
const ifModifiedSince = req.get("If-Modified-Since")
// If-Modified-Since পরীক্ষা করা
if (ifModifiedSince && new Date(ifModifiedSince)
>= updatedAt) {
return res.status(304).end()
}
const users = await getUsers()
res.set("Last-Modified", updatedAt.toUTCString())
res.json(users)
})
Express.js উদাহরণে, সার্ভার ডাটাবেস থেকে ডেটার শেষ আপডেটের তারিখ পায়, ক্লায়েন্টের If-Modified-Since পরীক্ষা করে, এবং যদি ক্যাশ এখনও তাজা থাকে — 304 রিটার্ন করে। যদি ডেটা পরিবর্তিত হয় — নতুন Last-Modified সেট করে এবং সম্পূর্ণ রেসপন্স রিটার্ন করে। toUTCString() তারিখকে প্রয়োজনীয় HTTP ফরম্যাটে রূপান্তর করে। প্রোডাকশনে, প্রতিটি অনুরোধে ডাটাবেস কোয়েরি এড়াতে Redis-এ updatedAt ক্যাশ করা ভাল।
Nginx ফাইলের শেষ পরিবর্তনের সময়ের ভিত্তিতে স্ট্যাটিক ফাইলের জন্য স্বয়ংক্রিয়ভাবে Last-Modified সেট করে। etag ডিরেক্টিভ (ETag নিষ্ক্রিয় করা) বা ngx_http_headers_module মডিউলের মাধ্যমে এই আচরণ নিষ্ক্রিয় বা পরিবর্তন করা যেতে পারে। ব্যাকএন্ডে প্রক্সি করা অনুরোধের জন্য, Last-Modified আপস্ট্রিম রেসপন্স থেকে অপরিবর্তিত পাস হয়। গুরুত্বপূর্ণ: যদি ব্যাকএন্ড Last-Modified না রিটার্ন করে, Nginx ডায়নামিক রেসপন্সের জন্য এটি স্বয়ংক্রিয়ভাবে যোগ করবে না।
Last-Modified-এর বেশ কয়েকটি পরিচিত সীমাবদ্ধতা রয়েছে। প্রধানটি হল সেকেন্ড নির্ভুলতা। যদি একটি রিসোর্স এক সেকেন্ডের মধ্যে দুবার পরিবর্তিত হয়, ক্লায়েন্ট নতুন সংস্করণ হারাতে পারে। বাস্তবে এটি একটি বিরল পরিস্থিতি, তবে উচ্চ-ফ্রিকোয়েন্সি আপডেটের (টিকার ফিড, চ্যাট) জন্য ETag সুপারিশ করা হয়। দ্বিতীয় সীমাবদ্ধতা হল ক্লাস্টারিং সমস্যা: বিভিন্ন সার্ভারে একটি ফাইলের mtime কপি বা ডিপ্লয়মেন্টের কারণে ভিন্ন হতে পারে, যা Last-Modified-কে অসামঞ্জস্যপূর্ণ করে।
তৃতীয় সীমাবদ্ধতা — সেকেন্ড নির্ভুলতার সাথে If-Modified-Since হ্যান্ডলিং বারবার সার্ভার পোল করার সময় অপ্রয়োজনীয় অনুরোধের কারণ হতে পারে। যদি ক্লায়েন্ট প্রতি ৫০০ মিলিসেকেন্ডে If-Modified-Since পাঠায়, সার্ভার প্রতিবার 200 OK রিটার্ন করে কারণ তারিখ পরিবর্তিত হয়নি, কিন্তু রিসোর্স আসলে ইতিমধ্যে আপডেট হয়েছে। সমাধান হল ETag-এর সাথে সংমিশ্রণ ব্যবহার করা: ETag এক সেকেন্ডের মধ্যে পরিবর্তন ধরবে, যেখানে Last-Modified রিজার্ভ হিসেবে থাকবে।
চতুর্থ সমস্যা — Last-Modified একই তারিখের একই রিসোর্সের ভিন্ন সংস্করণের মধ্যে পার্থক্য করে না। যদি একটি ফাইল ব্যাকআপ থেকে পুনরুদ্ধার করা হয় এবং তার mtime মূলের সাথে মিলে যায়, ক্লায়েন্ট লক্ষ্য করবে না যে কন্টেন্ট পরিবর্তিত হয়েছে। ETag এই সমস্যা সমাধান করে: কন্টেন্ট হ্যাশ টাইমস্ট্যাম্প নির্বিশেষে ডেটার যেকোনো পরিবর্তনে নিশ্চিতভাবে পরিবর্তিত হবে। গুরুত্বপূর্ণ ডেটার জন্য, সর্বদা উভয় হেডার ব্যবহার করুন।
সচরাচর জিজ্ঞাসিত প্রশ্ন
শুধুমাত্র GMT (গ্রিনউইচ মিন টাইম) RFC 1123 ফরম্যাটে: সপ্তাহের দিন, তারিখ, মাস, বছর, ঘন্টা:মিনিট:সেকেন্ড। উদাহরণ: Wed, 02 Jul 2025 14:30:00 GMT। সময় অঞ্চল সর্বদা GMT, অন্যান্য ফরম্যাট অনুমোদিত নয়।
প্রযুক্তিগতভাবে হ্যাঁ, কিন্তু এটি RFC 7232 লঙ্ঘন করে। যদি সার্ভার ভবিষ্যতের তারিখ রিটার্ন করে, ক্লায়েন্ট সেই তারিখ আসা পর্যন্ত রিসোর্স আপডেট করবে না। এই ধরনের কনফিগারেশন ত্রুটি হিসাবে বিবেচিত হয় — তারিখ অতীত বা বর্তমানে হওয়া উচিত।
না, If-Modified-Since শর্তসাপেক্ষ অনুরোধ শুধুমাত্র GET এবং HEAD-এর সাথে কাজ করে। POST অনুরোধ ক্যাশ হয় না এবং তারিখ-ভিত্তিক ভ্যালিডেশন ব্যবহার করে না। POST-এ সতেজতা পরীক্ষার জন্য, ETag বা কাস্টম মেকানিজম ব্যবহার করুন।
Cache-Control ক্যাশিং নীতি (সর্বোচ্চ সংরক্ষণ সময়, কে ক্যাশ করতে পারে) নির্ধারণ করে, যেখানে Last-Modified মেয়াদোত্তীর্ণ ক্যাশের ভ্যালিডেশন মেকানিজম। max-age শেষ হওয়ার পর, ক্লায়েন্ট সতেজতা পরীক্ষার জন্য If-Modified-Since পাঠায়।
পরীক্ষা করুন যে সার্ভার সঠিক উৎস — ডাটাবেস, ফাইল সিস্টেম বা API — থেকে হেডার সেট করছে। ডায়নামিক রেসপন্সের জন্য, নিশ্চিত করুন যে আপনি হ্যান্ডলার কোডে স্পষ্টভাবে res.setHeader("Last-Modified", ...) কল করছেন।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন