আমরা এই বাগটিটিও অনুভব করছিলাম তবে আমরা একটি সম্পদ পরিচালনার লাইব্রেরি (ক্যাসেট) ব্যবহার করছিলাম। এই ইস্যুটির বিস্তৃত তদন্তের পরে, আমরা দেখতে পেয়েছি যে এএসপি.এনইটি, আইআইএস এবং ক্যাসেটের সংমিশ্রণে এই সমস্যার মূল কারণ। আমি নিশ্চিত নই যে এটি আপনার সমস্যা ( Headers
এপিআইয়ের পরিবর্তে এপিআই ব্যবহার করা Cache
) তবে প্যাটার্নটি একই রকম বলে মনে হচ্ছে।
বাগ # 1
ক্যাসেটটি Vary: Accept-Encoding
একটি বান্ডিলের প্রতিক্রিয়ার অংশ হিসাবে শিরোনাম সেট করে যেহেতু এটি gzip / deflate সহ সামগ্রীটিকে এনকোড করতে পারে:
তবে, এএসপি.নেট আউটপুট ক্যাশে সর্বদা ক্যাশে হওয়া প্রতিক্রিয়াটি সর্বদা ফিরিয়ে দেবে। উদাহরণস্বরূপ, যদি প্রথম অনুরোধ আছে Accept-Encoding: gzip
এবং ক্যাসেট gzipped বিষয়বস্তু ফেরৎ, ASP.NET আউটপুট ক্যাশ হিসাবে URL টি ক্যাশে করবে Content-Encoding: gzip
। একই ইউআরএলের পরবর্তী অনুরোধ কিন্তু ভিন্ন গ্রহণযোগ্য এনকোডিং সহ (যেমন Accept-Encoding: deflate
) এর সাথে ক্যাশে দেওয়া প্রতিক্রিয়া ফিরে আসবে Content-Encoding: gzip
।
এই বাগ ব্যবহার ক্যাসেট দ্বারা ঘটিত হয় HttpResponseBase.Cache
আউটপুট ক্যাশে সেটিংস (যেমন সেট করতে এপিআই Cache-Control: public
) কিন্তু ব্যবহার HttpResponseBase.Headers
সেট করতে এপিআই Vary: Accept-Encoding
হেডার। সমস্যা হল ASP.NET হয় OutputCacheModule
হয় না প্রতিক্রিয়া হেডার সচেতন; এটি কেবলমাত্র Cache
API এর মাধ্যমে কাজ করে । এটি, এটি প্রত্যাশা করে যে বিকাশকারী কেবলমাত্র স্ট্যান্ডার্ড এইচটিটিপি-র পরিবর্তে অদৃশ্যভাবে দৃ tight়-জোড়াযুক্ত API ব্যবহার করবে।
বাগ # 2
আইআইএস 7.5 (উইন্ডোজ সার্ভার 2008 আর 2) ব্যবহার করার সময়, বাগ # 1 আইআইএস কার্নেল এবং ব্যবহারকারীর ক্যাশে পৃথক সমস্যা সৃষ্টি করতে পারে। উদাহরণস্বরূপ, একবার একটি বান্ডিল সফলভাবে ক্যাশে হয়ে গেলে Content-Encoding: gzip
, এটি দিয়ে আইআইএস কার্নেল ক্যাশে এটি দেখা সম্ভব netsh http show cachestate
। এটি 200 স্থিতি কোড এবং "জিজিপ" এর সামগ্রী এনকোডিং সহ একটি প্রতিক্রিয়া দেখায়। যদি পরবর্তী অনুরোধটির আলাদা গ্রহণযোগ্য এনকোডিং থাকে (উদাহরণস্বরূপ
Accept-Encoding: deflate
) এবংIf-None-Match
বান্ডেলের হ্যাশের সাথে মিলে এমন একটি শিরোলেখ থাকে, তবে আইআইএসের কার্নেল এবং ব্যবহারকারী মোড ক্যাশে অনুরোধটি মিস হিসাবে বিবেচিত হবে । সুতরাং, অনুরোধ ক্যাসেট দ্বারা পরিচালিত হতে পারে যা 304 ফেরত দেয়:
তবে, একবার আইআইএসের কার্নেল এবং ব্যবহারকারী মোডগুলি প্রতিক্রিয়াটি প্রক্রিয়া করার পরে, তারা দেখতে পাবে যে ইউআরএলটির প্রতিক্রিয়া বদলেছে এবং ক্যাশে আপডেট করা উচিত। যদি আইআইএস কার্নেল ক্যাশেটি netsh http show cachestate
আবার পরীক্ষা করা হয় তবে ক্যাশেড 200 প্রতিক্রিয়া 304 টি প্রতিক্রিয়া দ্বারা প্রতিস্থাপিত হবে। বান্ডলে পরবর্তী সমস্ত অনুরোধগুলি নির্বিশেষে Accept-Encoding
এবং If-None-Match
304 টি প্রতিক্রিয়া ফিরিয়ে দেবে। আমরা এই বাগের ধ্বংসাত্মক প্রভাবগুলি দেখেছি যেখানে সমস্ত ব্যবহারকারীদের আমাদের মূল স্ক্রিপ্টের জন্য একটি এলোমেলো অনুরোধের কারণে একটি অপ্রত্যাশিত Accept-Encoding
এবং এর জন্য 304 সরবরাহ করা হয়েছিল If-None-Match
।
সমস্যাটি মনে হচ্ছে যে আইআইএস কার্নেল এবং ব্যবহারকারী মোড ক্যাশেগুলি Accept-Encoding
শিরোনামের ভিত্তিতে পরিবর্তিত হতে পারে না । এর প্রমাণ হিসাবে, Cache
নীচের কাজের সাথে API ব্যবহার করে , আইআইএস কার্নেল এবং ব্যবহারকারী মোড ক্যাশে সর্বদা এড়ানো যায় বলে মনে হয় (কেবলমাত্র ASP.NET আউটপুট ক্যাশে ব্যবহৃত হয়)। এটি netsh http show cachestate
নীচের কাজের সাথে খালি কিনা তা পরীক্ষা করে নিশ্চিত হওয়া যায়। এএসপি.এনইটি আইআইএস কর্মীর সাথে সরাসরি প্রতি অনুরোধে আইআইএস কার্নেল এবং ব্যবহারকারী মোড ক্যাশে সক্ষম বা অক্ষম করতে যোগাযোগ করে।
আমরা এই বাগটি আইআইএসের নতুন সংস্করণগুলিতে পুনরায় উত্পাদন করতে পারিনি (যেমন আইআইএস এক্সপ্রেস 10)। তবে, বাগ # 1 এখনও পুনরুত্পাদনযোগ্য ছিল।
এই বাগের জন্য আমাদের আসল ফিক্সটি কেবলমাত্র অন্যের মতো উল্লিখিত ক্যাসেট অনুরোধের জন্য আইআইএস কার্নেল / ব্যবহারকারী মোড ক্যাশেিং অক্ষম করা ছিল। এটি করে, আমরা আমাদের ওয়েব সার্ভারের সামনে ক্যাশিংয়ের একটি অতিরিক্ত স্তর স্থাপন করার সময় বাগ # 1টি অনাবৃত করেছিলাম। কোয়েরি স্ট্রিং হ্যাকটি যে কারণে কাজ করেছে তা হ'ল কারণ, OutputCacheModule
যদি Cache
API এর উপর ভিত্তি করে পরিবর্তিত হওয়ার জন্য API ব্যবহার করা না হয় QueryString
এবং অনুরোধটির একটি থাকে তবে একটি ক্যাশে মিস রেকর্ড করবেQueryString
।
কার্যসংক্রান্ত
আমরা যাইহোক ক্যাসেট থেকে সরে যাওয়ার পরিকল্পনা করে চলেছি, সুতরাং আমাদের নিজস্ব ক্যাসেটের কাঁটাচামড়া (বা পিআর মার্জ করার চেষ্টা করা) রক্ষা না করে আমরা এই ইস্যুটি সম্পর্কে কাজ করার জন্য এইচটিটিপি মডিউলটি ব্যবহার করার বিকল্প বেছে নিয়েছি।
public class FixCassetteContentEncodingOutputCacheBugModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PostRequestHandlerExecute += Context_PostRequestHandlerExecute;
}
private void Context_PostRequestHandlerExecute(object sender, EventArgs e)
{
var httpContext = HttpContext.Current;
if (httpContext == null)
{
return;
}
var request = httpContext.Request;
var response = httpContext.Response;
if (request.HttpMethod != "GET")
{
return;
}
var path = request.Path;
if (!path.StartsWith("/cassette.axd", StringComparison.InvariantCultureIgnoreCase))
{
return;
}
if (response.Headers["Vary"] == "Accept-Encoding")
{
httpContext.Response.Cache.VaryByHeaders.SetHeaders(new[] { "Accept-Encoding" });
}
}
public void Dispose()
{
}
}
আমি আশা করি এটি কাউকে সাহায্য করবে 😄!