Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copying Http Request InputStream

I'm implementing a proxy action method that forwards the incoming web request and forwards it to another web page, adding a few headers. The action method works file for GET requests, but I'm still struggling with forwarding the incoming POST request.

The problem is that I don't know how to properly write the request body to the outgoing HTTP request stream.

Here's a shortened version of what I've got so far:

//the incoming request stream
var requestStream=HttpContext.Current.Request.InputStream;
//the outgoing web request
var webRequest = (HttpWebRequest)WebRequest.Create(url);
...

//copy incoming request body to outgoing request
if (requestStream != null && requestStream.Length>0)
            {
                long length = requestStream.Length;
                webRequest.ContentLength = length;
                requestStream.CopyTo(webRequest.GetRequestStream())                    
            }

//THE NEXT LINE THROWS A ProtocolViolationException
 using (HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse())
                {
                    ...
                }

As soon as I call GetResponse on the outgoing http request, I get the following exception:

ProtocolViolationException: You must write ContentLength bytes to the request stream before calling [Begin]GetResponse.

I don't understand why this is happening, since requestStream.CopyTo should have taken care of writing the right amount of bytes.

Any suggestions would be greatly appreciated.

Thanks,

Adrian

like image 631
Adrian Grigore Avatar asked Aug 10 '10 09:08

Adrian Grigore


2 Answers

Yes, .Net is very finicky about this. The way to solve the problem is to both flush and close the stream. In other words:

Stream webStream = null;

try
{
    //copy incoming request body to outgoing request
    if (requestStream != null && requestStream.Length>0)
    {
        long length = requestStream.Length;
        webRequest.ContentLength = length;
        webStream = webRequest.GetRequestStream();
        requestStream.CopyTo(webStream);
    }
}
finally
{
    if (null != webStream)
    {
        webStream.Flush();
        webStream.Close();    // might need additional exception handling here
    }
}

// No more ProtocolViolationException!
using (HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse())
{
    ...
}
like image 177
Brian Avatar answered Oct 02 '22 17:10

Brian


The answer @brian works, however, I found that once requestStream.CopyTo(stream) was called, it would fire off my HttpWebResponse. This was an issue since I wasn't quite ready to send the request. So if anyone is having an issue with not all of the request headers or other data being sent, it is because CopyTo is firing your request.

like image 28
Seth Avatar answered Oct 02 '22 17:10

Seth