UnityWebRequest POST over HTTPS bug and workaround

I’m not sure if this is a bug or intended behaviour, so thought I’d post this here to get some feedback.

I am working on a project implementing Microsoft’s Face API, which requires me to POST over HTTPS. I had some legacy code doing this using WWW, but recently converted this to use UnityWebRequest instead.

Strangely, this didn’t seem to work. After debugging with Fiddler, I realized the request was never finishing properly: it connected to the host fine, but never actually sent the POST data.

So this is where I suspect there may be a bug in UnityWebRequest (correct me if I’m wrong), particularly in the Send method; according to the documentation this method is supposed to only finish (and yes I am using it in a coroutine) when the request is done. However, after the initial SSL handshake, it continues right away, and since I am disposing of the request, the data I want to POST is never sent.

The solution is to wait until IsDone is true; which seems to defeat the purpose of Send (again, correct me if I’m wrong).

Code (including fix):

using (var request = UnityWebRequest.Put(url, image))
{
    request.method = UnityWebRequest.kHttpVerbPOST;
    request.SetRequestHeader("Ocp-Apim-Subscription-Key", API_KEY);

    yield return request.Send();
    while (!request.isDone)
        yield return new WaitForEndOfFrame();

    if (request.isHttpError || request.isNetworkError)
        Debug.LogError(request.error);
    else
    {
        json = request.downloadHandler.text;
        Debug.Log(json);
    }
}

I’ve only used the UWR a little bit but I think this might be intentional. With UWR you can supply your own handlers for downloaded and uploaded data, which allows you to operate in multiple smaller slices, whereas the old WWW object (if I understand it) was a single yield, which got you all your data at once.

Right that would make sense if true - however that does mean the documentation is very misleading and really should be fixed:

Description

This method returns an AsyncOperation object. Yielding the AsyncOperation inside a coroutine will cause the coroutine to pause until the UnityWebRequest encounters a system error or finishes communicating.

If you yield return the async operation, the coroutine will be paused until request is complete. Have you really verified that isDone returns false after yield return?
Also note, that there is UnityWebRequest.Post(), you don’t need to use Put() and then change method to POST (although does give you the same result).
The only reason I see for it not sending the post data is when it fails early.