Ian Kaney - 9 - Feb 11, 2015

Currently attempting to integrate a reverse proxy into a ServiceStack project by adding a RawHttpHandler. I’ve managed to successfully get this working apart from POST data which acts bizarrely. When the POST’ed data is of application/x-www-form-urlencoded data, I cannot access the InputStream to retrieve the original data. However, if I upload a binary file, it works fine when I set it to use a buffered stream. Is it linked to this issue perhaps?

https://github.com/ServiceStack/Issues/issues/175

Thanks for your time.

A RawHttpHandler short-circuits ServiceStack and lets you execute your own HttpHandler so there shouldn’t be anything getting in the way. If you try to access req.FormData anywhere it will force loading the Request Stream.

I’ve just tried it writing out the Request InputStream for a x-www-form-urlencoded Request back out to the Response OutputStream and it’s working without issue:

this.RawHttpHandlers.Add(httpReq => 
    httpReq.ContentType == MimeTypes.FormUrlEncoded 
        ? new CustomActionHandler((req, res) => {
                var bytes = req.InputStream.ReadFully();
                res.OutputStream.Write(bytes, 0, bytes.Length);
            })
        : null);

Ian Kaney:

I’m attempting to do this in VB.Net, I have converted the code you gave and ran a test through it and I still have the same issue. InputStream is there but it’s empty. Form and FormData have been populated with the data which seems to suggest that ServiceStack has parsed the data already.

Here is the code I’m using (it’s in the Configure sub)

MyBase.RawHttpHandlers.Add(Function(httpReq) If(httpReq.PathInfo.StartsWith("/proxy/"), New CustomActionHandler(Function(req, res)
Dim bytes = req.InputStream.ReadFully()
res.OutputStream.Write(bytes, 0, bytes.Length)
End Function), Nothing))

Any ideas?

ServiceStack doesn’t have an opportunity to touch FormData when using RawHttpHandler, (note just by checking FormData will force the RequestStream to load - you shouldn’t touch it). 

Is this an ASP.NET/MVC App? If so, my guess is that one of ASP.NET’s built-in/pre-configured features/handlers might be doing loading it before it reaches ServiceStack.

You could try disabling compression since it forces requests to be buffered, some info on how to do that are at:
https://github.com/ServiceStack/ServiceStack/wiki/Server-Events#response-buffering-delaying-events

Otherwise can you send me a link to a small, stand-alone example (e.g. gist/github repo) and I can try repo it locally.

Ian Kaney:

It’s a standalone hosted app (windows service). I’ll try and knock together an example for you. Thanks for your time.

Ian Kaney:

Ok, I managed to get some time and setup a new C# project using the ServiceStack template "ServiceStack Self Host Empty"

I added the system.web reference and the rawhttphandler code and ran the code.

I then used curl with the following parameters to send the data:

curl --data “param1=value1&param2=value2” http://localhost:8088/test

Unfortunately, exactly the same end result as in my code in VB, I don’t get anything echo’ed back to the client and when I check the InputStream when I break it’s empty.

Any ideas, or have I missed something obvious?

Ian Kaney:

I’ve also ran the code in release mode in both VB and C#, just in case debug mode was causing the IDE to read data it shouldn’t be.

Yeah I’m debugging the issue now, it’s due to GetAttributes() benig called when setting up the Request/Response objects, it looks at FormData to determine whether or not to Override the HTTP Method with POST’ed X-Http-Method-Override. 

Looking at ways around it since we can’t change the default behavior, it will probably require opt-in configuration to disable.

Ian Kaney:

Glad you’ve found it and it’s not me going mad! Thanks for your time.

Hi Ian, I’ve added a new Config option to skip looking at FormData when creating a request, in this commit: https://github.com/ServiceStack/ServiceStack/commit/ff2c234c7cf46d5abcf3a6ad78eb64e177fdf798

You can configure it with:

SetConfig(new HostConfig {
    SkipFormDataInCreatingRequest = true,
});

This will now let you access an untouched Request InputStream and write it to the Response with:

RawHttpHandlers.Add(_ => new CustomActionHandler((req, res) => {
    var bytes = req.InputStream.ReadFully();
    res.OutputStream.Write(bytes, 0, bytes.Length);
}));

Which you can test using ServiceStack’s built-in HTTP Utils, e.g:

url.PostToUrl(new { a = “foo”, b = “bar” }).Print();

This change is now available on MyGet: https://github.com/ServiceStack/ServiceStack/wiki/MyGet

Ian Kaney:

Just to let you know that I’ve downloaded the version from MyGet and it works brilliantly. Thanks so much for your time and the fantastic support!

Sweet, glad it’s now working :slight_smile: