exception "Error in IXMLHttpRequest2Callback" when doing a http_request using https uri

Sep 26, 2014 at 4:12 PM
Edited Sep 26, 2014 at 4:42 PM
Hi,

I have built casablanca for xbox one as suggested in some post on xbox one forums but i face the following issue.
I was trying to send a POST request for an https uri with some custom headers using http_request.

When i execute the following code, i get an exception mentioned in the subject line ("Error in IXMLHttpRequest2Callback").

return client.request(request).then([this](task<http_response> responseTask)
{
    http_response response;
    try
    {
        // Get the response out of the response task.
        // This will throw an exception if an error occurred,            
                    response = responseTask.get();
         this->setStatusCode(response.status_code());
    } catch(const http_exception &e){

        // inspect message and error code here and handle error
        return;
    }
 }
I am not sure what i am doing wrong.
Sep 26, 2014 at 5:23 PM
Hi dvgopal,

Take a look at the std::error_code field on the http_exception class. In particular look at the value and message. It might tell you more information. Here is the reference documentation.

Steve
Sep 26, 2014 at 8:42 PM
Thanks Steve! I am getting "specified resource download failed". may be because of cross domain issue. Do you know if casablanca can help in by passing cross domain issue? is there any work around?
Sep 26, 2014 at 8:56 PM
I don't really understand what the underlying problem is so it is hard to say. Can you show any more of your code? Are you using HTTPS? Quickly searching for the error message with IXmlHttpRequest2 (the API we build on top of for Windows Store/Phone) mentions something about certificates that might be worth taking a look.

Steve
Sep 26, 2014 at 9:38 PM
Steve,

Yes i am using HTTPS. I am using http_request to add custom headers and body before sending the request as shown below. I tried with other https url and it returned a 200 OK. but only when i use with our server it is throwing an exception. Probably a CORS (Cross Origin Resource Sharing) issue. Is there a way to get around this problem?
        http_client client(U("https://site.oncue.com:1344"));
    http_request request(methods::POST);
    request.headers().add(U("Authorization"),U("Basic SU9TLVBLXYxOjAxMjM0NS0wMTIzLTAxMjMtMDEyMy0wMTIzNDU2Nzg5MDE="));
    request.headers().add(U("Content-Type"),U("application/json"));
    request.set_request_uri(L"/authorize");
    
    web::json::value body;
       body[L"deviceId"] = web::json::value::string(L"24d1a64aba1c050f488f5f92");
       body[L"friendlyName"] = web::json::value::string(L"Test1407185284206");

       request.set_body(body);
 

    // Make an HTTP POST request and asynchronously process the response
    return client.request(request).then([&code](task<http_response> responseTask)
    {
        http_response response;
        try
        {
            // Get the response out of the response task.
            // This will throw an exception if an error occurred, for example if the connection was 
            code =  responseTask.get().status_code();

        } catch(const http_exception &e){
            std::error_code error = e.error_code();
            std::string m = error.message();
            auto msg = e.what();
            // inspect message and error code here and handle error
            
        }
    });
--Venu
Sep 26, 2014 at 9:50 PM
Edited Sep 26, 2014 at 9:50 PM
Hi Venu,

Ah I bet it has something to do with your Authorization header. I think IXMLHttpRequest2 is fussy and might now want you to NOT explicitly specify the header. Instead of formulating the header yourself can you try passing in the credentials using the http_client_config class? I bet it will work then.

Steve
Sep 29, 2014 at 4:49 PM
Steve,

I tried with http_client_config class by setting credentials. still i get the same error "download of resource failed". I am using http_request in order to set some custom headers. but i don't see a way to set headers using http_client_config. are you aware of any work around?

Thanks!
Venu
Sep 29, 2014 at 11:38 PM
Hi Venu,

You don't set headers on the http_client_config class, you should only need to specify the credentials on the http_client_config class and not on the on the http_request class as well. Is this a public server that I can reach and make requests to? If so perhaps you can provide a small repro.

Steve
Sep 30, 2014 at 5:04 PM
Steve,

Unfortunately this is a private server. I will contact the server admins to check if they are allowing cross domain requests. If not i may have to find a way to relay the request.

Thanks for your inputs.

-_Venu
Sep 30, 2014 at 11:02 PM
Hi dvgopal,

I noticed you may be having some issues with CORS, so I'd like to link in another thread discussing it. In that thread, the situation is using Casablanca as the listener and using JavaScript as a client, but it has links you may find useful.

https://casablanca.codeplex.com/discussions/564796

Sincerely,
roschuma
Oct 1, 2014 at 5:56 PM
Hi Roschuma,

Thanks for the link! As i mentioned above, i was getting CORS issue because our private webserver is not allowing cross domain requests. So, we used Fiddler(a utility to modify request/responses) to modify response headers to accept localhost, making it believe that request is coming from a localhost. can we do the same in casablanca?

Is there a way to have a proxy server kind of thing in casablanca? When i send the request, i am getting an exception instead of 400 or 404. I am assuming that it is reaching the server but am not sure why the exception is thrown instead of response.


Thanks!
Venu
Oct 3, 2014 at 3:42 PM
Hi Steve/Roschuma,

I installed fiddler to get around this problem of certificate for now. but i think eventually server has to be updated to allow requests from other domains.

I observed that if the service is not available (HTTP 503) or Unauthorized (401), i get an exception instead of getting the response code in the http_response. Is this normal?

Thanks!
Oct 7, 2014 at 5:40 PM
Hi Venu,

No that doesn't sound correct, I've never seen this happen. The only time an http_exception will be thrown is if an error actual occurs. We don't consider status codes to be an error. An error would be something like the request timedout or the connection was broken, etc... You could be getting an exception for example if you are unable to resolve the address and connect the service. Is this what you are seeing?

Steve
Oct 8, 2014 at 5:12 PM
Hi Steve,

I think what you said is correct. I did not handle exception properly it seems. I wanted to handle all the exceptions at one place. But i am not sure how to handle exceptions for tasks that were created like a tree, ie, in one tasks response i want to create another task as mentioned below. but i want to handle all the exceptions for all the tasks at one place. can you have any suggestions?
return client.request(request).then([](http_response response){

   // extract information from response

}).then([](http_response response){
   
    http_request request = makeRequest(response); //locall method to make request
    return client.request(request).then([](http_response response){
    
     });

}).then([](task<http_response> response){

   //handle all exceptions here.
});
Oct 8, 2014 at 5:50 PM
Hi Venu,

Yes I can help you with this :)

With a task chain, like the one you have above making two http requests, if an exception occurs it will be propagated forward to the next task, until it encounters a task based continuation. The last task in your chain above is a task based continuation because the argument is a task of http_response instead of just an http_response. This means no matter what happens in the previous tasks the last one you have will execute.

To handle any exceptions simply add a try catch around a call to get or wait on the task:
}).then([](task<http_response> responseTask){

    try
    {
        http_response response = responseTask.get();
        // Use response...
    } catch(const http_exception &e)
    {
        // Inspect error and handle here....
    }
});
One additional thing to note. The task returned from the http_client::request(...) API is signaled once the headers have arrived from the server. It is possible the response body is still being received. If you are working with the response body the available methods: http_response::extract_string(), http_response::extract_json(), http_response::extract_vector(), http_response::content_ready(), and http_response::body() also could throw an exception. For example if the connection was broken before the entire response body arrived.

I recommend you take a look here on msdn for more information about how to use tasks.

Steve