FSharp.Data icon indicating copy to clipboard operation
FSharp.Data copied to clipboard

How to extract the status code from a WebException generated by XmlProvider<...>.Load ?

Open dgellow opened this issue 9 years ago • 4 comments

Hi,

I'm using XmlProvider to fetch and parse RSS feeds. I want to handle HTTP Errors but I cannot find a way to get the status code of a webexception.Response. The C# approach is to cast the WebResponse to HttpWebResponse, that doesn't seem to work with the response from MyXml.Load.

To be more explicit, look at the code below. downcastWebResponse tries to downcast the WebResponse from the exception into an HttpWebResponse. Unfortunately it fails thus returns None. Without the guard, if I do something like let resp = e.Response :?> HttpWebResponse I get the error Unhandled Exception: System.InvalidCastException: Specified cast is not valid..

So, my question is: How can I get the status code from the exception response? And if I have to cast to HttpWebResponse, how can I do it?

open System
open System.Net
open FSharp.Data

type Rss = XmlProvider<sampleRssFile>
let feedWith404 = "http://feeds.reuters.com/reuters/blogs/the-human-impact"

let downcastWebResponse (wr: WebResponse) =
    match wr with
    | :? HttpWebResponse as hwr -> Some(hwr.StatusCode)
    | _ -> None

let loadRssIndex (url: string) : Choice<Rss.Rss, RssException> =
    try
        Choice1Of2 (Rss.Load(url))
    with
    | :? WebException as e ->
        match e.Status with
        | WebExceptionStatus.ProtocolError ->
            let statusCode = downcastWebResponse e.Response // <== try to downcast
            match statusCode with
            | Some status ->
                match status with
                | HttpStatusCode.NotFound ->
                    Choice2Of2 (RssException.IndexNotFound e)
                | _ -> reraise()
            | None -> reraise() // <== downcast failed
        | _ -> reraise()

// Run
loadRssIndex feedWith404

dgellow avatar Oct 29 '16 10:10 dgellow

The HttpWebResponse is sitting on e.Response.res, a private member of Response on WebException. It's not only private, it's protected or internal, so we can't expose it in a subclass. Would love to have access to it, as mapping a WebResponse to an HttpWebResponseusing the public members is error-prone at best.

vdehaven avatar Sep 24 '17 23:09 vdehaven

This issue should remain open. So far as I can tell, there is still no convenient way to retrieve the HTTP status code of a WebException. The least-worst way is to extract it from e.Message, which is a string.

This is a major pitfall. If you Google for C# solutions, they'll tell you to downcast to HttpWebResponse, which does not work for FSharp.Data's WebResponse.

YoRyan avatar Jan 27 '24 15:01 YoRyan

Not sure why it was closed, I don’t remember closing it? Pretty I didn’t interact with this issue since I opened it in 2016. Anyway, it’s reopened.

dgellow avatar Feb 01 '24 02:02 dgellow