bool lazyQueryStringValidation;
bool inputValidationEnabled;
RequestContext requestContext;
+ BufferlessInputStream bufferlessInputStream;
static bool validateRequestNewMode;
internal static bool ValidateRequestNewMode {
}
}
- //
- // TODO:
- // * I no longer remember what worker_request = null meant.
- // * Hook up the Filter?
- //
- Stream MakeBufferlessInputStream ()
+ public Stream GetBufferlessInputStream ()
{
- int content_length = ContentLength;
- int content_length_kb = content_length / 1024;
- HttpRuntimeSection config = HttpRuntime.Section;
- if (content_length_kb > config.MaxRequestLength)
- throw HttpException.NewWithCode (400, "Upload size exceeds httpRuntime limit.", WebEventCodes.RuntimeErrorPostTooLarge);
+ if (bufferlessInputStream == null) {
+ if (input_stream != null)
+ throw new HttpException ("Input stream has already been created");
- int total = 0;
- byte [] buffer;
- buffer = worker_request.GetPreloadedEntityBody ();
- // we check the instance field 'content_length' here, not the local var.
- if (this.content_length <= 0 || worker_request.IsEntireEntityBodyIsPreloaded ()) {
- if (buffer == null || content_length == 0) {
- input_stream = new MemoryStream (new byte [0], 0, 0, false, true);
- } else {
- input_stream = new MemoryStream (buffer, 0, buffer.Length, false, true);
- }
- DoFilter (new byte [1024]);
- return input_stream;
+ // we don't need to hook up the filter here, because the raw stream should be returned
+ bufferlessInputStream = new BufferlessInputStream (this);
}
- if (buffer != null)
- total = buffer.Length;
-
- return new BufferlessInputStream (this, buffer);
- }
-
-
- public Stream GetBufferlessInputStream ()
- {
- if (input_stream != null)
- throw new HttpException ("Input stream has already been created");
- input_stream = MakeBufferlessInputStream ();
- if (input_filter != null){
- input_filter.BaseStream = input_stream;
- return input_filter;
- }
- return input_stream;
+ return bufferlessInputStream;
}
//
//
class BufferlessInputStream : Stream {
HttpRequest request;
-
// cached, the request content-length
int content_length;
- // the buffer that we read from
+ // buffer that holds preloaded data
byte [] preloadedBuffer;
- // number of valid bytes in buffer.
- int bytes_in_buffer;
+ // indicates if we already served the whole preloaded buffer
+ bool preloaded_served;
- // how many bytes we have returned so far
- int total;
+ // indicates if we already checked the request content-length against httpRuntime limit
+ bool checked_maxRequestLength;
// our stream position
long position;
- int buffer_start;
//
// @request: the containing request that created us, used to find out content length
- // @buffer: the byte buffer that we start serving (may be null).
- // @total: number of valid bytes in buffer.
- public BufferlessInputStream (HttpRequest request, byte [] preloadedBuffer)
+ public BufferlessInputStream (HttpRequest request)
{
this.request = request;
- this.preloadedBuffer = preloadedBuffer;
- bytes_in_buffer = preloadedBuffer == null ? 0 : preloadedBuffer.Length;
content_length = request.ContentLength;
}
{
if (buffer == null)
throw new ArgumentNullException ("buffer");
-
+
if (offset < 0 || count < 0)
throw new ArgumentOutOfRangeException ("offset or count less than zero.");
-
+
if (buffer.Length - offset < count )
throw new ArgumentException ("offset+count",
"The size of the buffer is less than offset + count.");
+ if (count == 0 || request.worker_request == null)
+ return 0;
+
+ if (!checked_maxRequestLength) {
+ int content_length_kb = content_length / 1024;
+ HttpRuntimeSection config = HttpRuntime.Section;
+ if (content_length_kb > config.MaxRequestLength)
+ throw HttpException.NewWithCode (400, "Upload size exceeds httpRuntime limit.", WebEventCodes.RuntimeErrorPostTooLarge);
+ else
+ checked_maxRequestLength = true;
+ }
+
// Serve the bytes we might have preloaded already.
- if (preloadedBuffer != null){
- int bytes_left = bytes_in_buffer-buffer_start;
- if (bytes_left != 0){
- int n = Math.Min (count, bytes_left);
- Array.Copy (preloadedBuffer, buffer_start, buffer, offset, n);
- buffer_start += n;
- if (buffer_start == bytes_in_buffer)
- preloadedBuffer = null;
+ if (!preloaded_served) {
+ if (preloadedBuffer == null)
+ preloadedBuffer = request.worker_request.GetPreloadedEntityBody ();
+
+ if (preloadedBuffer != null) {
+ long bytes_left = preloadedBuffer.Length-position;
+ int n = (int) Math.Min (count, bytes_left);
+ Array.Copy (preloadedBuffer, position, buffer, offset, n);
+ position += n;
+
+ if (n == bytes_left)
+ preloaded_served = true;
+
return n;
}
+ else
+ preloaded_served = true;
+ }
+
+ // serve bytes from worker request if available
+ if (position < content_length) {
+ long bytes_left = content_length-position;
+ int n = count;
+
+ if (bytes_left < count)
+ n = (int) bytes_left;
+
+ int bytes_read = request.worker_request.ReadEntityBody (buffer, offset, n);
+ position += bytes_read;
+ return bytes_read;
}
- return request.worker_request.ReadEntityBody (buffer, offset, count);
+ return 0;
}
public override long Seek (long offset, SeekOrigin origin)