haf / Http.fs

A simple, functional HTTP client library for F#
322 stars 43 forks source link

Actual response content is not set when response code is an error #127

Closed bigjonroberts closed 7 years ago

bigjonroberts commented 7 years ago

The web service I'm accessing will return content that specifies the error conditions. Because of the way that WebExceptions are handled, this content is never set.

https://github.com/haf/Http.fs/blob/2c868608046333fb3b41c30f6a109381fc3b1213/HttpFs/HttpFs.fs#L812

There's some C# code on how to get the response anyway here: http://stackoverflow.com/questions/7261986/how-to-get-error-information-when-httpwebrequest-getresponse-fails

However, I'm not experienced with hopac, so I'm unsure how to inject this handling into the code.

haf commented 7 years ago

But the code already handles the exception and returns the response? In your example, all that's different is that the response stream is read, but since you get the response back, all you have to do is use the Response module's functions to read the body. Or perhaps I'm missing something?

bigjonroberts commented 7 years ago

HttpWebResponse will replace the response body with the following: {"Message":"System.Web.Http.HttpResponseException: Processing of the HTTP request resulted in an exception. Please see the HTTP response returned by the 'Response' property of this exception for details."}

That's what the code in the stackoverflow example does. It get's the actual response content rather than what is replaced.

I was able to get the HttpWebResponse object via the luggage property and the body content was the same there.

It appears this happens after the WebException is raised, so if you handle that exception, you can get the actual content.

Here's the exception handling code from the linked Stackoverflow question, where he's just writing it out to the console:

catch (WebException ex)
{
    using (var stream = ex.Response.GetResponseStream())
    using (var reader = new StreamReader(stream))
    {
        Console.WriteLine(reader.ReadToEnd());
    }
}
catch (Exception ex)
{
    // Something more serious happened
    // like for example you don't have network access
    // we cannot talk about a server exception here as
    // the server probably was never reached
}
haf commented 7 years ago

Yes, but don't we handle it? https://github.com/haf/Http.fs/blob/2c868608046333fb3b41c30f6a109381fc3b1213/HttpFs/HttpFs.fs#L820

OR: are you saying the API mutates the request object? Abhorrent, I tell you.

Well then, perhaps we should just read the body and store it in a memory stream?

bigjonroberts commented 7 years ago

Correct, it is handled. But the current implementation leaves the stubbed out response body in place.

We loose the ability to access the original body content.

If we want the original content, we have to work around a poor implementation decision (IMHO) in HttpWebResponse.

bigjonroberts commented 7 years ago

I see, you're passing out the wex.Response, so we'd expect to get the original content body. But that's not what I'm seeing happen in my environment.

haf commented 7 years ago

I'm afraid I'm not facing your issues; and I have numerous systems in production reading non-2xx/3xx response codes' bodies just fine.

Perhaps you can write me a unit test? I have samples of both Http.fs requesting a library web server – suave, so it should be fairly simple to add another test case for this.

bigjonroberts commented 7 years ago

Thanks for following up. I'll create a test to reproduce. If I'm not able to reproduce the issue in test environment, then maybe I'll discover what's wrong in my environment in the process.

bigjonroberts commented 7 years ago

I think that the response on this is generated in WebAPI on the server side. I will close this out sometime later today or tomorrow. (Sorry for the little inconvenience, @haf ).

Does anyone around here know any good tools to monitor what is actually being sent by the client?

When I cut and pasted the Json into a different tool and posted it to the server there, it went through successfully. But when I posted it from Http.fs, I was getting a 500 error. So I assume it's something in the headers or encoding. I want to find a good way to dig deeper, but learning something like wireshark seems like it may be overkill.

haf commented 7 years ago

Yes, just start nc -l 8080.

screen shot 2017-04-10 at 23 12 56

You can also use Charle's proxy on mac, or fiddler on Windows.

And of course Wireshark; it's actually not hard to learn at all; just start it on the loopback IF and filter for the HTTP protocol.