一部のサーバーのAPI関数を使用しようとしていたところ、突然このエラーが発生しました。コードサンプルの後で説明します。
public IEnumerator Post(Dictionary<string, string> data)
{
var request = UnityWebRequest.Post(Url, data);
request.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded");
yield return request.Send();
if (request.isError)
UpdateNetworkLog("Network error has occured: " + request.error);
else
// Some code after success
}
ご覧のとおり、POSTリクエスト ここ を考慮して、ほとんどがUnityマニュアルから取得しました。しかし、1つの問題があります-リクエストが正しく完了しなかったため、常にエラー(UpdateNetworkLog関数を使用して表示されます):リクエストの応答コードが0のときの「一般的な/不明なHTTPエラー」。また、このマニュアルのレガシーメソッドとWWWクラスを使用して同じ結果を得ようとしました。
Unityが応答を取得する方法に問題があると思います。Wiresharkを介してパケットを確認しました。POST要求とサーバーの応答はどちらも問題なく、エラーやミスはありません。
もう1つの重要な問題は、私がWebGLを使用していて、Editorですべてが正常であるということです。プログラムは適切な応答を受け取り、正しく動作します。ブラウザでゲームをビルドして実行した後にのみエラーが表示されます(ChromeおよびSafariでテスト済み)。また、Unity WebGL PlayerではなくXAMPPを使用してゲームを起動してみました:同じです。
Googleはそれについて何も知らないので、今後のすべての対応に感謝します。
WebGLでのUnityWebRequest
の使用について nityのドキュメント から:
WWWおよびUnityWebRequestクラスはWebGLでサポートされています。これらは、JavaScriptのXMLHttpRequestクラスを使用して実装され、ブラウザーを使用してWWW要求を処理します。これは、クロスドメインリソースへのアクセスにいくつかのセキュリティ制限を課します。基本的に、WebGLコンテンツをホストしているサーバーとは異なるサーバーへのWWW要求は、アクセスしようとしているサーバーによって承認される必要があります。 WebGLでクロスドメインWWWリソースにアクセスするには、アクセスしようとしているサーバーがCORSを使用してこれを承認する必要があります。
私の推測では、アクセスしようとしているこのサーバーにはCORSが正しくセットアップまたは構成されていません。コードがブラウザーで実行されている場合、ブラウザー自体が要求を処理し、その結果、コードをそのブラウザーのセキュリティ制限に準拠させます。プログラムとサーバーが同じドメイン上になく、ブラウザーがそれを好まない。
これがあなたの問題である場合、それ以上の情報がなければ、私が解決策を提案することは困難です。あなたの投稿から、あなたはコーディング(または少なくともHTTP関連コーディング)に比較的新しいかもしれないようです、そしてあなたの問題に私が見つけることができる最良の解決策は、 JavaScriptを使用するUnityWebRequest
の代わりに。
もちろん、実際の問題は、代わりに周囲のコード、またはアクセスしようとしているサーバーにある可能性もあります。 Post()
を呼び出す関数のコードは何ですか?コードがブラウザーで実行されている場合にのみ表示されるイベントの順序に問題がある可能性があります(JavaScriptがPOST要求を処理している場合)。
余談ですが、アクセスしようとしているサーバーにAPIのドキュメントがある場合、問題はサーバーのどこかで解決されている可能性があります。
最初に指摘することは、UnityWebRequestが実際に応答を返すことです
request.downloadHandler.text
一般的なエラー情報のみを返す一方で
request.error
今、あなたのケースが私のようなもので、Unityをアップグレードしてすべてのネットワークコードを中断させた場合、表示される可能性のあるエラーはContent-Lengthに関連しています。
これは、WWWクラスとUnityWebRequestクラスの両方にデフォルトでchunkedTransferがオンが含まれているためです。これは、コンテンツの長さがどのように送信されるかを混乱させ、エラーの原因となるようです。
現在、chunkedTransferはUnityWebRequestに対して無効にすることができますが、これを書いている時点ではWWWクラスに対して無効にすることはできません。私にとってこれは、代わりにUnityWebRequestを使用するようにすべての古いネットワークコードを書き換えて設定することを意味しました
myUnityWebRequest.chunkedTransfer = false;
注:UnityWebRequestは現在、データのないPOSTをサポートしていません。これには引き続きWWWクラスを使用する必要があります。
この問題は非常に一般的です。 Rest APIを使用したことがあれば、物事は非常に簡単に理解できます。
python flaskを使用してREST APIを作成しました。これはHerokuでホストされていました。Herokuの利点は、デフォルトでCORSをサポートしていて、現在、アプリをホストする最大サーバー、特にpythonは同じ機能を備えています。したがって、CORS関連の問題がある場合、最初にCROSを有効にする必要があります。
PostmanでAPIをテストする必要があります。アプリがCORSをサポートしていない場合でも、Postmanで機能します。したがって、postmanで作業しても、それがUnityで実行されることは保証されません。次に考慮すべき重要なことは、郵便配達で使用しているヘッダーです。
例:{"Key": "Content-Type"、 "value": "application/json"}
ユニティwwwヘッダーでも渡す必要があるためです。
次に観察する必要があるのは、あなたが身体に何を渡しているか、そしてあなたがそれをどのように渡しているかです。通常、PostmanではJSON(application/json)として送信します。
お気に入り:
`{
"username":"Mukesh",
"password":"admin@1234",
"email_id":"[email protected]",
"us_dollar":"2000000000",
"device_id":"123456789"
}`
CORS対応のAPIがPostmanで正常に動作している場合は、リラックスするだけで、Unityでも動作します。
まず、Jsonに変換するクラスを作成する必要があります。
[Serializable]
public class UserRegistration
{
//CAUTION:
//NOTE:
//DO NOT ALTER THE NAME OF PARAMETERS .
//THE JSON key WILL FAIL THEN .Properties will be the key of JSON .
/// <summary>
/// User name .
/// </summary>
public string username;
/// <summary>
/// Password .
/// </summary>
public string password;
/// <summary>
/// Emil id.
/// </summary>
public string email_id;
/// <summary>
/// JoeGames Doller .
/// </summary>
public string us_dollar;
/// <summary>
/// Device id .
/// </summary>
public string device_id;
/// <summary>
/// Constructor .
/// </summary>
/// <param name="username"></param>
/// <param name="password"></param>
/// <param name="email_id"></param>
/// <param name="us_dollar"></param>
/// <param name="device_id"></param>
public UserRegistration(string username, string password, string email_id, string us_dollar, string device_id)
{
this.username = username;
this.password = password;
this.email_id = email_id;
this.us_dollar = us_dollar;
this.device_id = device_id;
}
}
次に、jsonでオブジェクトを変換する必要があります。
//var create json.
var userregistration = new UserRegistration(
username: username,
password: password,
email_id: emailid,
us_dollar: joeGamesDollar.ToString(),
device_id: deviceid);
//convert to json.
var json = JsonUtility.ToJson(userregistration);
//debug.
Debug.Log("Print json"+json);
//update json.
json = json.Replace("'", "\"");
次に、jsonをバイトに変換し、ヘッダー付きの投稿を作成します。
//Encode the JSON string into a bytes
var postData = System.Text.Encoding.UTF8.GetBytes(json);
//create headers.
//Add keys an values .
var headers = new Dictionary<string, string> {{"Content-Type", "application/json"}};
//Now call a new WWW request
var www = new WWW(url,postData,headers);
//Yield return www .
yield return www;
Debug.Log("Error" + www.error.ToString());
Debug.Log("Data" + www.text);
Debug.Log(www.responseHeaders+"Done"+www.isDone);
//dispose.
www.Dispose();
列挙子でそれを書くことを忘れないでください。何かを使うなら
お気に入り:
IEnumerator Upload()
{
WWWForm form = new WWWForm();
form.AddField("username", "Mukesh");
form.AddField("password", "admin@1234");
form.AddField("email_id", "[email protected]");
form.AddField("us_dollar", "2000000");
form.AddField("device_id", device_id);
using (UnityWebRequest www = UnityWebRequest.Post(url, form))
{
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
Debug.Log("Form upload complete!");
}
}
}
Unity Webリクエストはこの状況で必要なAPIとして投稿したり、データを送信したりできないため、一般的な/不明なエラーが発生します。
注:いつか400 Badリクエストが単一の不明な汎用/不明HTTPエラーとして処理されます。そのため、バックエンドのコードをチェックして、APIに例外が発生していないことを確認することを忘れないでください。