Assert with request in http_client_impl.h on iOS

Jun 10, 2015 at 6:09 PM
Edited Jun 10, 2015 at 6:21 PM
I am attempting to use the SDK in iOS 8, and it is failing an assert in http_client_impl.h upon the second attempt to connect.
I create a, http_client as a class member, and use it to issue a single request per class instance. The second time I create an instance of this class and issue a request, the assertion fails. Below is the assertion:
Assertion failed: ((bool)instream), function _get_readbuffer, file /path/to/casablanca/Release/include/cpprest/details/http_client_impl.h, line 172.
virtual concurrency::streams::streambuf<uint8_t> _get_readbuffer()
    {
        auto instream = m_request.body();

        _ASSERTE((bool)instream);
        return instream.streambuf();
    }
Here is an example of the code making the request:
using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace std;


pplx::task<http_response>
Request::connect()
{

    //Should be set to GET, POST, PUT, or DELETE
    if (HTTPMethod.length() == 0)
    {
        HTTPMethod = methods::GET;
    }
    
    http_request req(HTTPMethod);
    
    if (HTTPBody.length() > 0)
    {
        std::string val;
        formatString(val, "%zd",HTTPBody.length());
        req.headers().add(header_names::content_length,val);
    }
    
    map<string,string>::const_iterator it;
    for (it = HTTPHeaders.begin(); it != HTTPHeaders.end(); it++) {
        const std::string header = (*it).first;
        const std::string value = (*it).second;
        req.headers().add(header,value);
    }

    //client is set with the URI
    req.set_request_uri("");
    return client.request(req);
    
}


void
Request::connectSync(Response& response)
{

    logInfo("connectSync: url (%s)", URL.c_str());

    try {
    
        http_response resp;
        
        connect().then([&](pplx::task<http_response> prevTask)
        {
        
            auto res = prevTask.get();
            logInfo("Result (%s) Requested URL (%s)", res.reason_phrase().c_str(), URL.c_str());
            resp = res;

        }).wait();
        
        response.body = resp.extract_string().get().c_str();
        response.httpCode = resp.status_code();

    } catch (http_exception &e) {
    
        logError("Error (%s) Requested URL (%s)", e.what(), URL.c_str());
        throw e;

    }
    
}
I am new to this, but based on the examples and documentation I have read, this should work. Any ideas??
Jun 10, 2015 at 9:15 PM
This is solved. I found out my issue-- I was setting the Content-Length for a POST but not setting the body for the request. For reference here are the updated lines:
    if (HTTPBody.length() > 0)
    {
        std::string val;
        formatString(val, "%zd",HTTPBody.length());
        req.headers().add(header_names::content_length,val);
        if (contentType.length() > 0)
            req.set_body(HTTPBody,contentType);
        else
            req.set_body(HTTPBody);
    }
Marked as answer by navysparks on 6/10/2015 at 1:15 PM
Jun 11, 2015 at 12:32 AM
Hi navysparks,

Glad you figured it out. Yes that assert was checking to see if the stream body was valid.

I can't quite tell exactly what type HTTPBody is, but you shouldn't need to explicitly sent the content length header here with calling set_body(...) it will automatically be take care of. You could collapse all those lines into:
req.set_body(HTTPBody);
Steve