* OutputCacheModule.cs: Update the date header value.
[mono.git] / mcs / class / System.Web / System.Web.Caching / OutputCacheModule.cs
1 //
2 // System.Web.Caching.OutputCacheModule
3 //
4 // Authors:
5 //  Jackson Harper (jackson@ximian.com)
6 //
7 // (C) 2003 Novell, Inc (http://www.novell.com)
8 //
9
10 using System.Web;
11 using System.Web.Util;
12
13 namespace System.Web.Caching {
14         
15         internal sealed class OutputCacheModule : IHttpModule {
16
17                 public OutputCacheModule ()
18                 {
19                 }
20
21                 public void Dispose ()
22                 {
23                 }
24
25                 public void Init (HttpApplication app)
26                 {
27                         app.AddOnResolveRequestCacheAsync (
28                                 new BeginEventHandler (OnBeginRequestCache),
29                                 new EndEventHandler (OnEndRequestCache));
30
31                         app.AddOnUpdateRequestCacheAsync (
32                                 new BeginEventHandler (OnBeginUpdateCache),
33                                 new EndEventHandler (OnEndUpdateCache));
34                 }
35
36                 IAsyncResult OnBeginRequestCache (object o, EventArgs args, AsyncCallback cb, object data)
37                 {
38                         HttpApplication app = (HttpApplication) o;
39                         HttpContext context = app.Context;
40                         
41                         string vary_key = context.Request.FilePath;
42                         CachedVaryBy varyby = context.Cache [vary_key] as CachedVaryBy;
43                         string key;
44                         CachedRawResponse c;
45
46                         if (varyby == null)
47                                 goto leave;
48
49                         key = varyby.CreateKey (vary_key, context);
50                         c = context.Cache [key] as CachedRawResponse;
51                         
52                         if (c != null && context.Timestamp < c.Policy.Expires) {
53                                 
54                                 context.Response.ClearContent ();
55                                 context.Response.BinaryWrite (c.GetData (), 0, c.ContentLength);
56
57                                 context.Response.ClearHeaders ();
58                                 c.DateHeader.Value = TimeUtil.ToUtcTimeString (DateTime.Now);
59                                 context.Response.SetCachedHeaders (c.Headers);
60
61                                 context.Response.StatusCode = c.StatusCode;
62                                 context.Response.StatusDescription = c.StatusDescription;
63                                 
64                                 app.CompleteRequest ();
65                         } else if (c != null) {
66                                 context.Cache.Remove (key);
67                         }
68
69                 leave:
70                         HttpAsyncResult result = new HttpAsyncResult (cb,this);
71                         result.Complete (true, o, null);
72                         
73                         return result;
74                 }
75
76                 void OnEndRequestCache (IAsyncResult result)
77                 {
78                 }
79
80                 IAsyncResult OnBeginUpdateCache (object o, EventArgs args, AsyncCallback cb, object data)
81                 {
82                         HttpApplication app = (HttpApplication) o;
83                         HttpContext context = app.Context;
84                         HttpAsyncResult result;
85
86                         if (context.Response.IsCached && context.Response.StatusCode == 200)
87                                 DoCacheInsert (context);
88
89                         result = new HttpAsyncResult (cb, this);
90                         result.Complete (true, o, null);
91                         return result;
92                 }
93
94                 void OnEndUpdateCache (IAsyncResult result)
95                 {
96                 }
97
98                 private void DoCacheInsert (HttpContext context)
99                 {
100                         string vary_key = context.Request.FilePath;
101                         string key;
102                         CachedVaryBy varyby = context.Cache [vary_key] as CachedVaryBy;
103                         CachedRawResponse prev = null;
104                         bool lookup = true;
105                         
106                         if (varyby == null) {
107                                 varyby = new CachedVaryBy (context.Response.Cache);
108                                 context.Cache.InsertPrivate (vary_key, varyby, null,
109                                                 Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
110                                                 CacheItemPriority.Normal, null);
111                                 lookup = false;
112                         } 
113                         
114                         key = varyby.CreateKey (vary_key, context);
115
116                         if (lookup)
117                                 prev = context.Cache [key] as CachedRawResponse;
118                         
119                         if (IsExpired (context, prev)) {
120                                 CachedRawResponse c = context.Response.GetCachedResponse ();
121                                 string [] files = new string [0];
122                                 string [] keys = new string [] { vary_key };
123
124                                 context.Cache.InsertPrivate (key, c, new CacheDependency (files, keys),
125                                                 context.Response.Cache.Expires,
126                                                 Cache.NoSlidingExpiration,
127                                                 CacheItemPriority.Normal, null);
128                         } 
129                 }
130
131                 private bool IsExpired (HttpContext context, CachedRawResponse crr)
132                 {
133                         if (crr == null || context.Timestamp > crr.Policy.Expires)
134                                 return true;
135                         return false;
136                 }
137         }
138 }
139