UnityWebRequest.Put fails on iOS

I am trying to upload a file to a vanilla Apache Webserver (v2.4.18) using UnityWebRequest and its Put(uri, bodyData)-Method. The server uses HTTPS and an authentication via username and password.
Here’s the code I use:

string url = "https://" + username + ":" + password + "@" + serverUrl + "/" + filename;
byte[] myData = Encoding.UTF8.GetBytes(csvString);
UnityWebRequest www = UnityWebRequest.Put(url, myData);
yield return www.Send();
// and some debugging errors etc. after that

In the editor and on Android this works just fine and the file is uploaded correctly, but on iOS it just doesn’t work.
What’s weird is that both in the editor and on iOS the yield seems to never finish, so I don’t get to the debugging code on either platform. When i put the debugging into the Update-Method www.isError is false, but the response stays empty.

A colleague reported that he got NSURLConnection error code -1002, which is a NSURLErrorUnsupportedURL error. Because of this I tried to percent escape the password and filename, because they include characters like : and =, but to no avail.
I also tried setting NSAppTransportSecurity → NSAllowsArbitraryLoads to true in the Info.plist, but this doesn’t help either.

Do I need to configure the app or the server somehow? Why does this work in the editor but not on iOS?

EDIT: The file upload also works on Android, so it’s most certainly an iOS exclusive issue.

URL encoding of basic authentication information has been deprecated a long time ago for security reasons. You have to use the proper basic authentitation header. Every browser which still supports the URL encoding of authentication information actually strips that information from the URL and creates an authentication header with the information.

The WWW class documentation page actually has now an example how to create the basic authentication header

You can use a helper class like this:

using UnityEngine;
using UnityEngine.Networking;
public static class WWWHeaders
{
    public static string CreateAuthorization(string aUserName, string aPassword)
    {
        return "Basic " + System.Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(aUserName + ":" + aPassword));
    }

    public static Hashtable AddAuthorizationHeader(this Hashtable aHeaders, string aUserName, string aPassword)
    {
        aHeaders.Add("Authorization", CreateAuthorization(aUserName, aPassword));
        return aHeaders;
    }
    public static UnityWebRequest AddAuthorizationHeader(this UnityWebRequest aRequest, string aUserName, string aPassword)
    {
        aRequest.SetRequestHeader("Authorization", CreateAuthorization(aUserName, aPassword));
        return aRequest;
    }
}

With this extension class you can simply do:

string url = "https://" + serverUrl + "/" + filename;
byte[] myData = Encoding.UTF8.GetBytes(csvString);
UnityWebRequest www = UnityWebRequest.Put(url, myData);
www.AddAuthorizationHeader(username, password);
yield return www.Send();

Hello, I also met, your similar problem, code: -1002, using UnityWebRequest, I don’t quite understand what you mean “the reason for the endless yield of the www.Send();”

You can paste it, you solve the code,