e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
130 lines
5.6 KiB
C#
130 lines
5.6 KiB
C#
//------------------------------------------------------------------------------
|
|
// <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);
|
|
}
|
|
}
|
|
}
|