-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBaseHttpHandler.cs
More file actions
203 lines (187 loc) · 6.74 KB
/
Copy pathBaseHttpHandler.cs
File metadata and controls
203 lines (187 loc) · 6.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
using System;
using System.Globalization;
using System.Net;
using System.Web;
namespace Bitdiff.Utils
{
/// <summary>
/// An abstract base Http Handler for all your
/// <see cref="IHttpHandler"/> needs.
/// </summary>
/// <remarks>
/// <p>
/// For the most part, classes that inherit from this
/// class do not need to override <see cref="ProcessRequest"/>.
/// Instead implement the abstract methods and
/// properties and put the main business logic
/// in the <see cref="HandleRequest"/>.
/// </p>
/// <p>
/// HandleRequest should respond with a StatusCode of
/// 200 if everything goes well, otherwise use one of
/// the various "Respond" methods to generate an appropriate
/// response code. Or use the HttpStatusCode enumeration
/// if none of these apply.
/// </p>
/// </remarks>
public abstract class BaseHttpHandler : IHttpHandler
{
/// <summary>
/// Processs the incoming HTTP request.
/// </summary>
/// <param name="context">Context.</param>
public void ProcessRequest(HttpContext context)
{
SetResponseCachePolicy(context.Response.Cache);
if (!ValidateParameters(context))
{
RespondInternalError(context);
return;
}
if (RequiresAuthentication
&& !context.User.Identity.IsAuthenticated)
{
RespondForbidden(context);
return;
}
HandleRequest(context);
}
/// <summary>
/// Indicates whether or not this handler can be
/// reused between successive requests.
/// </summary>
/// <remarks>
/// Return true if this handler does not maintain
/// any state (generally a good practice). Otherwise
/// returns false.
/// </remarks>
public bool IsReusable
{
get
{
return true;
}
}
/// <summary>
/// Handles the request. This is where you put your
/// business logic.
/// </summary>
/// <remarks>
/// <p>This method should result in a call to one
/// (or more) of the following methods:</p>
/// <p><code>context.Response.BinaryWrite();</code></p>
/// <p><code>context.Response.Write();</code></p>
/// <p><code>context.Response.WriteFile();</code></p>
/// <p>
/// <code>
/// someStream.Save(context.Response.OutputStream);
/// </code>
/// </p>
/// <p>etc...</p>
/// <p>
/// If you want a download box to show up with a
/// pre-populated filename, add this call here
/// (supplying a real filename).
/// </p>
/// <p>
/// <code>Response.AddHeader("Content-Disposition"
/// , "attachment; filename=\"" + Filename + "\"");</code>
/// </p>
/// </remarks>
/// <param name="context">Context.</param>
public abstract void HandleRequest(HttpContext context);
/// <summary>
/// Validates the parameters. Inheriting classes must
/// implement this and return true if the parameters are
/// valid, otherwise false.
/// </summary>
/// <param name="context">Context.</param>
/// <returns><c>true</c> if the parameters are valid,
/// otherwise <c>false</c></returns>
public abstract bool ValidateParameters(HttpContext context);
/// <summary>
/// Gets a value indicating whether this handler
/// requires users to be authenticated.
/// </summary>
/// <value>
/// <c>true</c> if authentication is required
/// otherwise, <c>false</c>.
/// </value>
public abstract bool RequiresAuthentication { get; }
/// <summary>
/// Sets the cache policy. Unless a handler overrides
/// this method, handlers will not allow a respons to be
/// cached.
/// </summary>
/// <param name="cache">Cache.</param>
public virtual void SetResponseCachePolicy
(HttpCachePolicy cache)
{
cache.SetCacheability(HttpCacheability.NoCache);
cache.SetNoStore();
cache.SetExpires(DateTime.MinValue);
}
protected virtual bool DetectAndSetNotModified(HttpContext context, TimeSpan maxAge)
{
if (context.Request.Headers["If-Modified-Since"].HasValue())
{
DateTime modified;
bool isModifiedValid =
DateTime.TryParseExact(
context.Request.Headers["If-Modified-Since"],
"r",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out modified);
if (isModifiedValid && modified < DateTime.UtcNow.Add(maxAge))
{
SetNotModified(context);
return true;
}
}
return false;
}
private void SetNotModified(HttpContext context)
{
context.Response.StatusCode = 304;
context.Response.StatusDescription = "Not Modified";
context.Response.AddHeader("Content-Length", "0");
}
/// <summary>
/// Helper method used to Respond to the request
/// that the file was not found.
/// </summary>
/// <param name="context">Context.</param>
protected void RespondFileNotFound(HttpContext context)
{
context.Response.StatusCode
= (int)HttpStatusCode.NotFound;
context.Response.End();
}
/// <summary>
/// Helper method used to Respond to the request
/// that an error occurred in processing the request.
/// </summary>
/// <param name="context">Context.</param>
protected void RespondInternalError(HttpContext context)
{
// It's really too bad that StatusCode property
// is not of type HttpStatusCode.
context.Response.StatusCode =
(int)HttpStatusCode.InternalServerError;
context.Response.End();
}
/// <summary>
/// Helper method used to Respond to the request
/// that the request in attempting to access a resource
/// that the user does not have access to.
/// </summary>
/// <param name="context">Context.</param>
protected void RespondForbidden(HttpContext context)
{
context.Response.StatusCode
= (int)HttpStatusCode.Forbidden;
context.Response.End();
}
}
}