I'm working on a managed HttpModule that forwards requests to other servers, using .Net 4.0 and IIS 8 (Windows Server 2012 RC).
This includes forwarding a request entity body, if the HTTP request has one. Since I want to immediately start to read the request body and forward the data to the remote server, I use HttpRequest.GetBufferlessInputStream() which returns a Stream that I can
read.
I now have two questions about that method:
1. HttpRequest.GetBufferlessInputStream() always returns a Stream, regardless of whether the HTTP request actually contains an entity body or not. Is it possible to distinguish between requests that contain a body, and ones that don't (besides the HTTP verb)?
2. Although GetBufferlessInputStream() allows to start to read the request body immediately, it seems to use a buffer of 8 KB, and the Read() method does not return until that buffer is full or EOF is reached - even when a small chunk arrives which would
be able to be processed.
e.g., I'm using such code to read from the request's stream:
Stream reqInputStream = request.GetBufferlessInputStream();
// Use 64 KiB buffer.
byte[] buf = new byte[64 * 1024];
int read;
while ((read = reqInputStream.Read(buf, 0, buf.Length)) > 0) {
// do something...
}
Now, imagine a client would make a POST request, using "Transfer-Encoding: chunked" to send a request body, and the first chunk containes 16 Bytes:
After that first 16-byte chunk arrives, reqInputStream.Read(...) does not return - it still waits until further chunks are received until the 8 KB buffer is full.
However, I would like Read() to return immediately when a chunk is available, regardless of its size. This is required by web application models like
Comet, which are using long-held requests and responses. This allows e.g. the client to send new data to the server whenever it wants, and the server can send data to the client whenever it wants, without having to establish a new HTTP request each time
(a bit like WebSockets).
However, this requires the server to be able to immediately process even small chunks sent by the client. Is this possible with HttpRequest.GetBufferlessInputStream(), or is there another way to achieve this?
Ok, I figured out the cause of 2. after looking at the source code:
HttpBufferlessInputStream.Read(...) has a loop in which it calls HttpWorkerRequest.ReadEntityBody(...) until the buffer is full or EOF is reached.
When I manaully retrieve the HttpWorkerRequest from an HttpContext (using Reflection, as the "WorkerRequest" property has "internal" visibility) and read the entity body from there, then the method returns as soon as a chunk is available, even when it is
only a few bytes.
Marked as answer by MrP19982 on Jun 21, 2012 01:06 PM
MrP19982
0 Points
5 Posts
Custom managed HttpModule - HttpRequest.GetBufferlessInputStream()
Jun 20, 2012 12:47 PM|LINK
Hi,
I'm working on a managed HttpModule that forwards requests to other servers, using .Net 4.0 and IIS 8 (Windows Server 2012 RC).
This includes forwarding a request entity body, if the HTTP request has one. Since I want to immediately start to read the request body and forward the data to the remote server, I use HttpRequest.GetBufferlessInputStream() which returns a Stream that I can read.
I now have two questions about that method:
1. HttpRequest.GetBufferlessInputStream() always returns a Stream, regardless of whether the HTTP request actually contains an entity body or not. Is it possible to distinguish between requests that contain a body, and ones that don't (besides the HTTP verb)?
2. Although GetBufferlessInputStream() allows to start to read the request body immediately, it seems to use a buffer of 8 KB, and the Read() method does not return until that buffer is full or EOF is reached - even when a small chunk arrives which would be able to be processed.
e.g., I'm using such code to read from the request's stream:
Stream reqInputStream = request.GetBufferlessInputStream(); // Use 64 KiB buffer. byte[] buf = new byte[64 * 1024]; int read; while ((read = reqInputStream.Read(buf, 0, buf.Length)) > 0) { // do something... }Now, imagine a client would make a POST request, using "Transfer-Encoding: chunked" to send a request body, and the first chunk containes 16 Bytes:
After that first 16-byte chunk arrives, reqInputStream.Read(...) does not return - it still waits until further chunks are received until the 8 KB buffer is full.
However, I would like Read() to return immediately when a chunk is available, regardless of its size. This is required by web application models like Comet, which are using long-held requests and responses. This allows e.g. the client to send new data to the server whenever it wants, and the server can send data to the client whenever it wants, without having to establish a new HTTP request each time (a bit like WebSockets).
However, this requires the server to be able to immediately process even small chunks sent by the client. Is this possible with HttpRequest.GetBufferlessInputStream(), or is there another way to achieve this?
Thank you very much!
MrP19982
0 Points
5 Posts
Re: Custom managed HttpModule - HttpRequest.GetBufferlessInputStream()
Jun 21, 2012 01:05 PM|LINK
Ok, I figured out the cause of 2. after looking at the source code:
HttpBufferlessInputStream.Read(...) has a loop in which it calls HttpWorkerRequest.ReadEntityBody(...) until the buffer is full or EOF is reached.
When I manaully retrieve the HttpWorkerRequest from an HttpContext (using Reflection, as the "WorkerRequest" property has "internal" visibility) and read the entity body from there, then the method returns as soon as a chunk is available, even when it is only a few bytes.