1

I have a WCF REST service running in streaming (unbuffered) mode that is receiving a file upload as raw bytes in the body of an HTTP request. Before reading the incoming stream (a MessageBodyStream), I check the request headers and make sure that the Content-Length is the right size for that particular operation.

If the Content-Length is larger than the allowed size, I'd like to immediate return an error response (by throwing a WebFaultException) without waiting for the rest of the request to be transferred.

However, it seems that WCF tries to read the stream to the end even after the exception is thrown -- if the client is sending a 50 MB file, all 50 MB will be transferred before a response is sent.

Is there any way to avoid this, and to interrupt receiving the HTTP request?

Related question: Why is WCF reading input stream to EOF on Close()?

EDIT: Added code excerpt

The OperationContract and the upload helper method:

[OperationContract]
[WebInvoke(UriTemplate = /* ... */, Method = "POST",
    ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
public void UploadMyFile(string guid, Stream fileStream)
{
    string targetPath = /* targetPath */;
    UploadFile(fileStream, targetPath, /* targetFileName */);
}


private bool UploadFile(Stream stream, string targetDirectory, 
    string targetFileName = null, int maximumSize = 1024 * 500, 
    Func<string, bool> tempFileValidator = null)
{
    int size = 0;
    int.TryParse(IncomingRequest.Headers[HttpRequestHeader.ContentLength], out size);
    if (size == 0)
    {
        ThrowJsonException(HttpStatusCode.LengthRequired, "Valid Content-Length required");
    }
    else if (size > maximumSize)
    {
        ThrowJsonException(HttpStatusCode.RequestEntityTooLarge, "File is too big");
    }

    if (!FileSystem.SaveFileFromStream(stream, targetDirectory, targetFileName, tempFileValidator))
    {
        ThrowJsonException(HttpStatusCode.InternalServerError, "Saving file failed");
    }

    return true;
}
Community
  • 1
  • 1
kpozin
  • 25,691
  • 19
  • 57
  • 76
  • Show us some code. `I check the request headers` where do you do this? Where do you read the stream? – Aliostad Jan 26 '12 at 16:41
  • @Aliostad, I posted an excerpt. – kpozin Jan 26 '12 at 16:55
  • What is the client? How does the client send the stream? That is the important question. – Aliostad Jan 26 '12 at 17:10
  • In this case the client is a .NET library wrapped in an MSTEST runner, using `System.Net.HttpWebRequest` and writing directly to the request stream. However, it could be anything else in the future -- an `XMLHttpRequest` object in a browser, a Python client, etc. The server must behave correctly regardless of what the client tries to do. – kpozin Jan 26 '12 at 17:42

2 Answers2

1

You can probably write the message inspector component which can intercept the body and context of the request.

You can then throw exception (if you like) after inspecting the message/context.

HTH

Suneet Nangia
  • 1,670
  • 1
  • 11
  • 7
0

HttpWebRequest and generally HTTP Request does not support streaming which underneath is implemented by chunked encoding which is a server side concept.

I just answered this question too which is related: IIS7 refuses chunked-encoded file upload

When you are writing to request stream, it is being buffered locally until sent since it has to pupate the content-length header. You can verify this in fiddler.

Community
  • 1
  • 1
Aliostad
  • 80,612
  • 21
  • 160
  • 208
  • I'm not really concerned about what the client is doing (in this case, I actually manually populate the Content-Length header on the client side before writing to the request stream). I just want the *server* to be able to abort *receiving the request*. I know that this is technically possible because WCF can cut off requests when they exceed the configured maximum message size. I'd like to do this from within my own server code, when my operation doesn't like something about the request. – kpozin Jan 26 '12 at 17:57