IIS 7, 200 yerine 304 değerini döndürüyor


10

IIS 7 ile ilgili garip bir sorunum var.
Bazen 200 yerine 304 döndürüyor gibi görünüyor.

İşte Fiddler ile yakalanan örnek bir istek:
(İstenen dosyanın henüz tarayıcı önbelleğimde olmadığını unutmayın.)

GET https://[mysite]/Content/js/jquery.form.js HTTP/1.1
Accept: */*
Referer: https://[mysite]/Welcome/News
Accept-Language: sv-SE
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; OfficeLiveConnector.1.4; OfficeLivePatch.1.3; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Host: [mysite]
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: ...

İstekte If-Modified-Since veya If-None-Match bulunmadığını unutmayın.
Ama yine de yanıt:

HTTP/1.1 304 Not Modified
Cache-Control: public
Expires: Tue, 02 Mar 2010 06:26:08 GMT
Last-Modified: Mon, 22 Feb 2010 21:58:44 GMT
ETag: "1CAB40A337D4200"
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Mon, 01 Mar 2010 17:06:34 GMT

Burada neyin yanlış olabileceğine dair bir ipucu var mı?

IIS 7'yi Windows Web Server 2008 R2 üzerinde çalıştırıyorum.

DÜZENLE:

Bir geçici çözüm buldum, önbelleğe almayı etkinleştirdim ve sonra bir uzantı düzeyinde devre dışı bıraktım benim için hile yaptı.

<configuration>
  <system.webServer>
    <caching enabled="true" enableKernelCache="true">
      <profiles>
        <add extension=".png" policy="DisableCache" kernelCachePolicy="DisableCache" />
        <add extension=".gif" policy="DisableCache" kernelCachePolicy="DisableCache" />
        <add extension=".js" policy="DisableCache" kernelCachePolicy="DisableCache" />
        <add extension=".css" policy="DisableCache" kernelCachePolicy="DisableCache" />
      </profiles>
    </caching>
    <staticContent>
      <clientCache cacheControlMode="NoControl" />
    </staticContent>
  </system.webServer>
</configuration>

Aynı sorunu yaşıyorum ve çok meşgul bir web sunucusunda çok fazla soruna neden oluyor. İstemcinin kaynağın henüz bir kopyası olmasa da, IIS bir 304 döndürür.
Philippe Leybaert

@Philippe, henüz bir çözüm buldunuz mu? Aksi takdirde, geçici bir çözüm için yukarıdaki düzenlememe bakın ve aşağıdaki yeni yanıtı inceleyin.
Ola Herrdahl

@OlaHerrdahl, geçici çözümünüz mükemmel :) Ben de bu sorunu yaşadım. Teşekkürler!
Ardee Aram

Yanıtlar:


3

HTTP1.1 spesifikasyonunun 14.9 bölümüne göre no-cache, Cache-Control üstbilgisi için yönerge yalnızca kaynak sunucu tarafından alınamaz, yani IIS isteğinizdeki üstbilgiyi yok saymaktadır.

Önbellek kontrol yönergeleri aşağıdaki genel kategorilere ayrılabilir:

  - Restrictions on what are cacheable; these may only be imposed

kaynak sunucu tarafından.

Bölüm 14.9.1 tanımlar public, privateve no-cachesadece sunucu tarafından empoze edilebilir cacheable ne kısıtlayan direktifler gibi.

.Js dosyanızın önbelleğe alınmasını istemiyorsanız no-cache, uygulamada yönerge ayarlamanız (yani ASP.NET kodu) veya yönerge Cache-Controlkullanma isteğindeki üstbilgiyi değiştirmeniz gerekir no-storeyerine no-cache.

DÜZENLEME:
Yorumunuza dayanarak - evet dosyanın önbelleğe alınmasını istemediğinizi varsaydım. 304, dosyanın IIS iç önbelleklerinden birinde olması nedeniyle geliyor olabilir. Bunlara bir göz atın:


Sanırım burada sorunumu yanlış anladın. Dosya henüz önbelleğimde bulunmuyor. Ama yine de sunucu bir 304 ile cevap veriyor ... Bu, tüm büyük tarayıcılarda siteye göz atarken rastgele oluyor gibi görünüyor.
Ola Herrdahl

@Ola Herrdahl: Düzenlememe bir bak.
squillman

IIS'de de önbelleğe almayı devre dışı bırakmayı denedim ve hiçbir şey fark
etmiyor

1

Bir süredir aynı sorunu yaşıyorum ve tüm önbelleğe alma özelliğini kapattım ... Ancak, IIS7 için Sıkıştırma modülünü varsayılan olarak varolan sitelerimdeki statik dosyaların sıkıştırılmasını etkinleştiren bir noktada kurdum. Etkilenen siteler için tüm sıkıştırmayı kapattım ve şimdi ince dokunmatik ahşap çalışıyor gibi görünüyor .


1

Biz de bu hatayı yaşıyorduk ama bir varlık yönetimi kütüphanesi (Kaset) kullanıyorduk. Bu sorunu kapsamlı bir şekilde inceledikten sonra, bu sorunun temel nedeninin ASP.NET, IIS ve Kaset birleşiminden kaynaklandığını tespit ettik. Bu olup olmadığından emin değilim senin (kullanarak sorunu Headersyerine API CacheAPI), ancak deseni aynı gibi görünüyor.

Hata # 1

Kaset Vary: Accept-Encoding, içeriği gzip / deflate ile kodlayabileceğinden, bir pakete verdiği yanıtın bir parçası olarak ayarlar :

Ancak, ASP.NET çıktı önbelleği her zaman ilk olarak önbelleğe alınan yanıtı döndürür. Örneğin, ilk istek varsa Accept-Encoding: gzipve Kaset gzip edilmiş içeriği döndürürse, ASP.NET çıktı önbelleği URL'yi önbelleğe alır Content-Encoding: gzip. Aynı URL'ye ancak farklı bir kabul edilebilir kodlamaya (ör. Accept-Encoding: deflate) Yönelik bir sonraki istek , önbelleğe alınan yanıtı döndürür Content-Encoding: gzip.

Bu hataya, HttpResponseBase.Cacheçıkış önbelleği ayarlarını ayarlamak için API'yi kullanan kaset neden olur (ör. Cache-Control: public), Ancak başlığı HttpResponseBase.Headersayarlamak için API'yi kullanır Vary: Accept-Encoding. Sorun ASP.NET olmasıdır OutputCacheModuleolduğu değil yanıt başlıkları farkında; yalnızca CacheAPI üzerinden çalışır . Yani, geliştiricinin standart HTTP yerine görünmez sıkı sıkıya bağlı bir API kullanmasını bekler.

Hata # 2

IIS 7.5 (Windows Server 2008 R2) kullanırken, hata # 1, IIS çekirdeği ve kullanıcı önbelleklerinde ayrı bir soruna neden olabilir. Örneğin, bir paket başarıyla önbelleğe alındıktan sonra, dizini Content-Encoding: gzipIIS çekirdek önbelleğinde görmek mümkündür netsh http show cachestate. 200 durum kodu ve "gzip" içerik kodlaması ile bir yanıt gösterir. Sonraki istekte farklı bir kabul edilebilir kodlama (ör. Accept-Encoding: deflate) VeIf-None-Match paketin karmasıyla eşleşen bir başlık varsa, IIS'nin çekirdeği ve kullanıcı modu önbelleklerine yönelik istek bir özledim olarak kabul edilir . Böylece, talebin 304 döndüren Cassette tarafından işlenmesine neden olur:

Ancak, IIS'nin çekirdek ve kullanıcı modları yanıtı işlediğinde, URL'nin yanıtının değiştiğini ve önbelleğin güncelleştirilmesi gerektiğini görürler. IIS çekirdek önbelleği netsh http show cachestateyeniden işaretlenirse , önbelleğe alınan 200 yanıtı 304 yanıtı ile değiştirilir. Daha sonra gelen tüm istekler, 304 yanıtından bağımsız olarak Accept-Encodingve If-None-Matchgeri dönecektir. Beklenmedik Accept-Encodingve rastgele bir istek nedeniyle tüm kullanıcılara temel komut dosyamız için bir 304 sunulduğu bu hatanın yıkıcı etkilerini gördük If-None-Match.

Sorun, IIS çekirdeği ve kullanıcı modu önbelleklerinin Accept-Encodingbaşlığa göre değişememesi gibi görünüyor . Bunun kanıtı olarak, CacheAPI'yi aşağıdaki geçici çözümle kullanarak IIS çekirdeği ve kullanıcı modu önbellekleri her zaman atlanmış gibi görünür (yalnızca ASP.NET çıkış önbelleği kullanılır). Bu, aşağıdaki çözümle netsh http show cachestateboş olup olmadığını kontrol ederek doğrulanabilir . ASP.NET, isteğe bağlı olarak IIS çekirdeği ve kullanıcı modu önbelleklerini seçerek etkinleştirmek veya devre dışı bırakmak için IIS çalışanıyla doğrudan iletişim kurar.

Bu hatayı IIS'nin yeni sürümlerinde (ör. IIS Express 10) yeniden üretemedik. Ancak, hata # 1 yine de tekrarlanabilir.

Bu hataya yönelik orijinal düzeltmemiz, IIS çekirdeği / kullanıcı modu önbelleğini yalnızca diğerleri gibi Kaset istekleri için devre dışı bırakmaktı. Bunu yaparak, web sunucularımızın önünde fazladan bir önbellek katmanı dağıtırken 1 numaralı hatayı ortaya çıkardık. Çünkü sorgu dize kesmek çalıştı nedeni OutputCacheModuleise bir önbellek kaydeder CacheAPI bağlı olarak değişebileceği için kullanılmamış QueryString ve istek bir sahipseQueryString .

Geçici çözüm

Yine de Cassette'den uzaklaşmayı planlıyoruz, bu nedenle kendi kaset çatalımızı korumak (veya bir PR birleştirmeye çalışmak) yerine, bu soruna geçici bir çözüm bulmak için bir HTTP modülü kullanmayı tercih ettik.

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()
    {

    }
}

Umarım bu birine yardımcı olur 😄!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.