locked
Custom managed HttpModule - HttpRequest.GetBufferlessInputStream() RRS feed

  • Question

  • User-748801471 posted

    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:

    POST /TestCometUsecase HTTP/1.1
    Host: localhost
    Connection: keep-alive
    Transfer-Encoding: chunked
    
    10
    abcdefggihjkmnop
    


    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!

    Wednesday, June 20, 2012 8:47 AM

Answers

  • User-748801471 posted

    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 Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, June 21, 2012 9:05 AM