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
|
//------------------------------------------------------------------------------
// <copyright file="ImplicitAsyncPreloadModule.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
/*
* ImplicitAsyncPreloadModule preloads the request entity for form posts.
*
* Copyright (c) 2010 Microsoft Corporation
*/
namespace System.Web {
using System;
using System.IO;
using System.Web;
using System.Web.Configuration;
using System.Web.Handlers;
using System.Web.Management;
using System.Web.Util;
internal class ImplicitAsyncPreloadModule {
HttpApplication _app;
AsyncCallback _callback;
Stream _inputStream;
internal void GetEventHandlers(out BeginEventHandler beginHandler, out EndEventHandler endHandler) {
beginHandler = new BeginEventHandler(OnEnter);
endHandler = new EndEventHandler(OnLeave);
}
private void Reset() {
if (_inputStream != null) {
_inputStream.Close();
_inputStream = null;
}
}
private IAsyncResult OnEnter(Object sender, EventArgs e, AsyncCallback cb, Object state) {
Debug.Assert(_inputStream == null);
_app = (HttpApplication)sender;
HttpContext context = _app.Context;
HttpRequest request = context.Request;
HttpWorkerRequest wr = context.WorkerRequest;
HttpAsyncResult httpAsyncResult = new HttpAsyncResult(cb, state);
AsyncPreloadModeFlags asyncPreloadMode = context.AsyncPreloadMode;
int contentLength;
bool isForm = false;
bool isFormMultiPart = false;
if (asyncPreloadMode == AsyncPreloadModeFlags.None
|| request.ReadEntityBodyMode != ReadEntityBodyMode.None
|| wr == null
|| !wr.SupportsAsyncRead
|| !wr.HasEntityBody()
|| wr.IsEntireEntityBodyIsPreloaded()
|| context.Handler == null
|| context.Handler is TransferRequestHandler
|| context.Handler is DefaultHttpHandler
|| (contentLength = request.ContentLength) > RuntimeConfig.GetConfig(context).HttpRuntime.MaxRequestLengthBytes
|| ((isForm = StringUtil.StringStartsWithIgnoreCase(request.ContentType, "application/x-www-form-urlencoded"))
&& (asyncPreloadMode & AsyncPreloadModeFlags.Form) != AsyncPreloadModeFlags.Form)
|| ((isFormMultiPart = StringUtil.StringStartsWithIgnoreCase(request.ContentType, "multipart/form-data"))
&& (asyncPreloadMode & AsyncPreloadModeFlags.FormMultiPart) != AsyncPreloadModeFlags.FormMultiPart)
|| !isForm && !isFormMultiPart && (asyncPreloadMode & AsyncPreloadModeFlags.NonForm) != AsyncPreloadModeFlags.NonForm
) {
Debug.Trace("AsyncPreload", " *** AsyncPreload skipped *** ");
httpAsyncResult.Complete(true, null, null);
return httpAsyncResult;
}
Debug.Trace("AsyncPreload", " *** AsyncPreload started *** ");
try {
if (_callback == null) {
_callback = new AsyncCallback(OnAsyncCompletion);
}
_inputStream = request.GetBufferedInputStream();
byte[] buffer = _app.EntityBuffer;
int bytesRead = 0;
// loop to prevent recursive calls and potential stack overflow if/when it completes synchronously
do {
IAsyncResult readAsyncResult = _inputStream.BeginRead(buffer, 0, buffer.Length, _callback, httpAsyncResult);
if (!readAsyncResult.CompletedSynchronously) {
return httpAsyncResult;
}
bytesRead = _inputStream.EndRead(readAsyncResult);
} while (bytesRead != 0);
}
catch {
Reset();
throw;
}
httpAsyncResult.Complete(true, null, null);
return httpAsyncResult;
}
private void OnLeave(IAsyncResult httpAsyncResult) {
Reset();
Debug.Trace("AsyncPreload", " *** AsyncPreload finished *** ");
((HttpAsyncResult)httpAsyncResult).End();
}
private void OnAsyncCompletion(IAsyncResult readAsyncResult) {
if (readAsyncResult.CompletedSynchronously) {
return;
}
HttpAsyncResult httpAsyncResult = readAsyncResult.AsyncState as HttpAsyncResult;
Exception error = null;
try {
int bytesRead = _inputStream.EndRead(readAsyncResult);
byte[] buffer = _app.EntityBuffer;
// loop to prevent recursive calls and potential stack overflow when it completes synchronously
while (bytesRead != 0) {
readAsyncResult = _inputStream.BeginRead(buffer, 0, buffer.Length, _callback, httpAsyncResult);
if (!readAsyncResult.CompletedSynchronously) {
return;
}
bytesRead = _inputStream.EndRead(readAsyncResult);
}
}
catch(Exception e) {
error = e;
}
httpAsyncResult.Complete(false, null, error);
}
}
}
|