2 // System.Web.Caching.OutputCacheModule
5 // Jackson Harper (jackson@ximian.com)
7 // (C) 2003 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Web.Util;
34 using System.Collections;
36 namespace System.Web.Caching {
38 internal sealed class OutputCacheModule : IHttpModule {
40 private CacheItemRemovedCallback response_removed;
42 public OutputCacheModule ()
46 public void Dispose ()
50 public void Init (HttpApplication app)
52 app.AddOnResolveRequestCacheAsync (
53 new BeginEventHandler (OnBeginRequestCache),
54 new EndEventHandler (OnEndRequestCache));
56 app.AddOnUpdateRequestCacheAsync (
57 new BeginEventHandler (OnBeginUpdateCache),
58 new EndEventHandler (OnEndUpdateCache));
60 response_removed = new CacheItemRemovedCallback (OnRawResponseRemoved);
63 IAsyncResult OnBeginRequestCache (object o, EventArgs args, AsyncCallback cb, object data)
65 HttpApplication app = (HttpApplication) o;
66 HttpContext context = app.Context;
68 string vary_key = context.Request.FilePath;
69 CachedVaryBy varyby = context.Cache [vary_key] as CachedVaryBy;
76 key = varyby.CreateKey (vary_key, context);
77 c = context.Cache [key] as CachedRawResponse;
81 context.Response.ClearContent ();
82 context.Response.BinaryWrite (c.GetData (), 0, c.ContentLength);
84 context.Response.ClearHeaders ();
85 c.DateHeader.Value = TimeUtil.ToUtcTimeString (DateTime.Now);
86 context.Response.SetCachedHeaders (c.Headers);
88 context.Response.StatusCode = c.StatusCode;
89 context.Response.StatusDescription = c.StatusDescription;
91 app.CompleteRequest ();
95 HttpAsyncResult result = new HttpAsyncResult (cb,this);
96 result.Complete (true, o, null);
101 void OnEndRequestCache (IAsyncResult result)
105 IAsyncResult OnBeginUpdateCache (object o, EventArgs args, AsyncCallback cb, object data)
107 HttpApplication app = (HttpApplication) o;
108 HttpContext context = app.Context;
109 HttpAsyncResult result;
111 if (context.Response.IsCached && context.Response.StatusCode == 200 &&
112 !context.Trace.IsEnabled)
113 DoCacheInsert (context);
115 result = new HttpAsyncResult (cb, this);
116 result.Complete (true, o, null);
120 void OnEndUpdateCache (IAsyncResult result)
124 private void DoCacheInsert (HttpContext context)
126 string vary_key = context.Request.FilePath;
128 CachedVaryBy varyby = context.Cache [vary_key] as CachedVaryBy;
129 CachedRawResponse prev = null;
132 if (varyby == null) {
133 string path = context.Request.MapPath (vary_key);
134 string [] files = new string [] { path };
135 string [] keys = new string [0];
136 varyby = new CachedVaryBy (context.Response.Cache, vary_key);
137 context.Cache.InsertPrivate (vary_key, varyby,
138 new CacheDependency (files, keys),
139 Cache.NoAbsoluteExpiration,
140 Cache.NoSlidingExpiration,
141 CacheItemPriority.Normal, null);
145 key = varyby.CreateKey (vary_key, context);
148 prev = context.Cache [key] as CachedRawResponse;
151 CachedRawResponse c = context.Response.GetCachedResponse ();
152 string [] files = new string [] { };
153 string [] keys = new string [] { vary_key };
154 bool sliding = context.Response.Cache.Sliding;
156 context.Cache.InsertPrivate (key, c, new CacheDependency (files, keys),
157 (sliding ? Cache.NoAbsoluteExpiration :
158 context.Response.Cache.Expires),
159 (sliding ? TimeSpan.FromSeconds (
160 context.Response.Cache.Duration) :
161 Cache.NoSlidingExpiration),
162 CacheItemPriority.Normal, response_removed);
164 varyby.ItemList.Add (key);
168 private void OnRawResponseRemoved (string key, object value, CacheItemRemovedReason reason)
170 CachedRawResponse c = (CachedRawResponse) value;
172 c.VaryBy.ItemList.Remove (key);
173 if (c.VaryBy.ItemList.Count != 0)
176 Cache cache = HttpRuntime.Cache;
177 cache.Remove (c.VaryBy.Key);