Skip to content

Instantly share code, notes, and snippets.

@heri3x
Created April 4, 2017 15:25
Show Gist options
  • Select an option

  • Save heri3x/fe86ae2ca9544d383c85a7dce6611f13 to your computer and use it in GitHub Desktop.

Select an option

Save heri3x/fe86ae2ca9544d383c85a7dce6611f13 to your computer and use it in GitHub Desktop.

Revisions

  1. heri3x created this gist Apr 4, 2017.
    604 changes: 604 additions & 0 deletions UnityWebApiExample.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,604 @@
    // This code is released as public domain, or under the zlib license.
    // このコードはパブリックドメインかzlibライセンス、お好きな方で利用してください。
    using UnityEngine;
    using System;
    using System.IO;
    using System.Collections;
    using System.Collections.Generic;
    using System.Net.Security;
    using System.Security.Cryptography.X509Certificates;

    //
    // Unity でWEBサーバーと通信するサンプル
    //
    // 動作確認した環境:
    // Unity 5.5.0f3 (Windows版)
    //
    // 動作確認の手順:
    // (1)MiniJSONライブラリのスクリプト(下記)をプロジェクトに追加します
    // https://github.com/Jackyjjc/MiniJSON.cs
    // (2)このスクリプトを GameObject にアタッチします
    // (3)ゲームを実行します
    // (4)Start()メソッドが呼び出されて、テスト結果がログに出力されるのを確認します
    //
    public class UnityWebApiExample : MonoBehaviour
    {
    void Start()
    {
    // テスト実行
    StartCoroutine(CoHttpRequestTest());
    }

    //
    // 通信テスト用コルーチン
    //
    // 下記のサイトを利用してJSON APIとの通信をおこないます。
    // http://www.jsontest.com/
    //
    // 処理内容:
    // 1. UnityWebRequestを使ってGETメソッドでJSON文字列を受け取る
    // 2. UnityWebRequestを使ってPOSTメソッドでJSON文字列を受け取る
    // 3. HttpWebRequestを使ってGETメソッドでJSON文字列を受け取る
    // 4. HttpWebRequestを使ってPOSTメソッドでJSON文字列を受け取る
    //
    IEnumerator CoHttpRequestTest()
    {
    // UnityWebRequestでGETメソッド
    {
    var web = new UwrWebHandler();
    web.SetUrl(@"http://validate.jsontest.com/?json={""key"":""value""}");
    web.SetMethodGet();
    //web.SetBasicAuthorization("username", "password"); //BASIC認証の設定

    // 送信開始し、結果の受け取り完了を待つ
    yield return web.CoSendRequest();

    // 結果をログ出力
    Log(web.GetResponseCode(), web.GetResponseHeader(),
    web.GetResponseContentType(), web.GetResponseText());
    }

    // UnityWebRequestでPOSTメソッド
    {
    var web = new UwrWebHandler();
    web.SetUrl(@"http://validate.jsontest.com/");
    web.SetMethodPost(@"json={""key"":""value""}", "application/x-www-form-urlencoded");
    //web.SetBasicAuthorization("username", "password"); //BASIC認証の設定

    // 送信開始し、結果の受け取り完了を待つ
    yield return web.CoSendRequest();

    // 結果をログ出力
    Log(web.GetResponseCode(), web.GetResponseHeader(),
    web.GetResponseContentType(), web.GetResponseText());
    }

    // HttpWebRequestでGETメソッド
    {
    var web = new HwrWebHandler();
    web.SetUrl(@"http://validate.jsontest.com/?json={""key"":""value""}");
    web.SetMethodGet();
    //web.SetAllowSelfSignedCertificate(true); //自己署名証明書を許可
    //web.SetBasicAuthorization("username", "password"); //BASIC認証の設定

    // 送信開始し、結果の受け取り完了を待つ
    yield return web.CoSendRequest();

    // 結果をログ出力
    Log(web.GetResponseCode(), web.GetResponseHeader(),
    web.GetResponseContentType(), web.GetResponseText());
    }

    // HttpWebRequestでPOSTメソッド
    {
    var web = new HwrWebHandler();
    web.SetUrl(@"http://validate.jsontest.com/");
    web.SetMethodPost(@"json={""key"":""value""}", "application/x-www-form-urlencoded");
    //web.SetAllowSelfSignedCertificate(true); //自己署名証明書を許可
    //web.SetBasicAuthorization("username", "password"); //BASIC認証の設定

    // 送信開始し、結果の受け取り完了を待つ
    yield return web.CoSendRequest();

    // 結果をログ出力
    Log(web.GetResponseCode(), web.GetResponseHeader(),
    web.GetResponseContentType(), web.GetResponseText());
    }
    }

    // 結果をログ出力
    void Log(long code, string header, string contentType, string text)
    {
    Debug.Log("Response Code: " + code);
    Debug.Log("Response Header: \n" + header);
    Debug.Log("Response Content-Type: \n" + contentType);
    Debug.Log("Response Text: \n" + text);

    // 受け取ったJSON文字列の内容を解釈して validateフィールドの内容を出力
    try
    {
    var jsonData = MiniJSON.Json.Deserialize(text);
    var root = jsonData as Dictionary<string, object>;
    var validate = (root != null) ? root["validate"] as bool? : null;
    Debug.Log("validate: " + validate);
    }
    catch (KeyNotFoundException ex)
    {
    Debug.Log("KeyNotFoundException\n" + ex);
    }
    }
    }

    //
    // Webアクセス処理クラス(UnityWebRequest版)
    //
    // Unity 5.4以降で利用できる UnityWebRequestクラスを使ってWebサーバーと通信します。
    //
    // できること:
    // ・HTTPまたはHTTPSのURLを指定して、GET/POSTアクセスができる
    // ・結果を文字列として受信できる
    // ・POST時は任意の文字列を送信できる
    // ・BASIC認証を利用できる
    // ・JavaScript環境(Unity WebGL)で使用できる
    //
    // できないこと:
    // ・SSL自己署名証明書を使うサーバーへのHTTPSアクセスはできない(※UnityWebRequestの制限)
    //
    public class UwrWebHandler
    {
    // 送信データ
    private string m_url;
    private string m_method;
    private string m_authorization;
    private string m_postString;
    private string m_postContentType;

    // 受信データ
    private int m_responseCode;
    private string m_responseHeader;
    private string m_responseContentType;
    private string m_responseText;


    // 結果を受け取り:HTTPレスポンスコード
    public int GetResponseCode()
    {
    return m_responseCode;
    }

    // 結果を受け取り:HTTPレスポンスヘッダ
    public string GetResponseHeader()
    {
    return m_responseHeader;
    }

    // 結果を受け取り:レスポンスコンテントタイプ
    public string GetResponseContentType()
    {
    return m_responseContentType;
    }

    // 結果を受け取り:レスポンス文字列
    public string GetResponseText()
    {
    return m_responseText;
    }

    // 呼び出し前の設定:URL
    public void SetUrl(string url)
    {
    m_url = url;
    }

    // 呼び出し前の設定:BASIC認証
    public void SetBasicAuthorization(string username, string password)
    {
    m_authorization = username + ":" + password;
    m_authorization = System.Convert.ToBase64String(
    System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(m_authorization));
    m_authorization = "Basic " + m_authorization;
    }

    // 呼び出し前の設定:BASIC認証
    public void ClearBasicAuthorization()
    {
    m_authorization = null;
    }

    // 呼び出し前の設定:GETメソッド時
    public void SetMethodGet()
    {
    m_method = "GET";
    m_postString = "";
    m_postContentType = "";
    }

    // 呼び出し前の設定:POSTメソッド時
    public void SetMethodPost(string postString, string postContentType)
    {
    m_method = "POST";
    m_postString = postString;
    m_postContentType = postContentType;
    }

    // リクエスト送信
    public IEnumerator CoSendRequest()
    {
    Debug.Log(
    "UwrWebHandler.CoSendRequest() - \"" + m_url + "\"\n" +
    " method: " + m_method + "\"\n"
    );
    m_responseCode = 0;
    m_responseContentType = null;
    m_responseText = null;

    // UnityWebRequest作成
    var request = new UnityEngine.Networking.UnityWebRequest(m_url, m_method);
    request.downloadHandler =
    (UnityEngine.Networking.DownloadHandler)new UnityEngine.Networking.DownloadHandlerBuffer();

    // BASIC認証の設定
    if (!string.IsNullOrEmpty(m_authorization))
    {
    request.SetRequestHeader("AUTHORIZATION", m_authorization);
    }

    // POSTメソッドの場合の設定
    if (m_method == "POST")
    {
    Debug.Log(" postString:\n" + m_postString);
    byte[] postDataRaw = System.Text.Encoding.UTF8.GetBytes(m_postString);
    request.uploadHandler =
    (UnityEngine.Networking.UploadHandler)new UnityEngine.Networking.UploadHandlerRaw(postDataRaw);
    request.SetRequestHeader("Content-Type", m_postContentType);
    }

    // リクエストを送信し、結果の受け取り完了を待つ
    yield return request.Send();

    // レスポンスコード取得
    m_responseCode = (int)request.responseCode;

    // レスポンスヘッダ取得
    m_responseHeader = "";
    Dictionary<string, string> responseHeaders = request.GetResponseHeaders();
    responseHeaders = responseHeaders ?? new Dictionary<string, string>();
    foreach (KeyValuePair<string, string> pair in responseHeaders)
    {
    string text;
    if (pair.Key == null)
    {
    text = pair.Value;
    }
    else
    {
    text = pair.Key + ":" + pair.Value;
    switch (pair.Key.ToLower())
    {
    case "content-type":
    string[] types = pair.Value.Split(';', ' ');
    if (types.Length != 0)
    {
    m_responseContentType = types[0];
    }
    break;
    }
    }
    m_responseHeader += text + "\n";
    }

    // レスポンス文字列を取得
    if (!request.isError)
    {
    m_responseText = request.downloadHandler.text;
    }
    }
    }

    //
    // Webアクセス処理クラス(HttpWebRequest版)
    //
    // .NET Framework 3.5 の HttpWebRequestクラスを使ってWebサーバーと通信します。
    //
    // できること:
    // ・HTTPまたはHTTPSのURLを指定して、GET/POSTアクセスができる
    // ・結果を文字列として受信できる
    // ・POST時は任意の文字列を送信できる
    // ・BASIC認証を利用できる
    // ・SSL自己署名証明書を使うサーバーへHTTPSアクセスできる
    //
    // できないこと:
    // ・Unity WebGL では使用できない(※HttpWebRequestとスレッド機能の制限)
    //
    // その他:
    // ・通信のタイムアウト処理に未対応
    //
    public class HwrWebHandler
    {
    // 同期用
    private object m_responceLock = new object();
    private volatile bool m_isFinishedAsyncProcess;

    // 送信データ
    private string m_url;
    private string m_method;
    private bool m_isAllowSelfSignedCertificate = false;
    private string m_authorization;
    private string m_postString;
    private string m_postContentType;
    private byte[] m_postDataRaw;

    // 受信データ
    private int m_responseCode;
    private string m_responseHeader;
    private string m_responseContentType;
    private string m_responseText;


    // 結果を受け取り:HTTPレスポンスコード
    public int GetResponseCode()
    {
    lock (m_responceLock)
    {
    return m_responseCode;
    }
    }

    // 結果を受け取り:HTTPレスポンスヘッダ
    public string GetResponseHeader()
    {
    lock (m_responceLock)
    {
    return m_responseHeader;
    }
    }

    // 結果を受け取り:レスポンスコンテントタイプ
    public string GetResponseContentType()
    {
    lock (m_responceLock)
    {
    return m_responseContentType;
    }
    }

    // 結果を受け取り:レスポンス文字列
    public string GetResponseText()
    {
    lock (m_responceLock)
    {
    return m_responseText;
    }
    }

    // 呼び出し前の設定:URL
    public void SetUrl(string url)
    {
    m_url = url;
    }

    // 呼び出し前の設定:自己署名証明書を許可するか
    public void SetAllowSelfSignedCertificate(bool v)
    {
    m_isAllowSelfSignedCertificate = v;
    }

    // 呼び出し前の設定:BASIC認証
    public void SetBasicAuthorization(string username, string password)
    {
    m_authorization = username + ":" + password;
    m_authorization = System.Convert.ToBase64String(
    System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(m_authorization));
    m_authorization = "Basic " + m_authorization;
    }

    // 呼び出し前の設定:BASIC認証
    public void ClearBasicAuthorization()
    {
    m_authorization = null;
    }

    // 呼び出し前の設定:GETメソッド時
    public void SetMethodGet()
    {
    m_method = "GET";
    m_postString = "";
    m_postContentType = "";
    }

    // 呼び出し前の設定:POSTメソッド時
    public void SetMethodPost(string postString, string postContentType)
    {
    m_method = "POST";
    m_postString = postString;
    m_postContentType = postContentType;
    }

    // 証明書の検証処理(なんでも許可する)
    public static bool ValidateAnyServerCertificate(
    object sender,
    System.Security.Cryptography.X509Certificates.X509Certificate certificate,
    X509Chain chain,
    System.Net.Security.SslPolicyErrors sslPolicyErrors)
    {
    return true;
    }

    // このメソッドは非同期処理が完了した際に別スレッドから呼び出されます
    void OnFinishGetRequestStream(IAsyncResult result)
    {
    System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)result.AsyncState;

    try
    {
    // ストリーム取得処理を終了
    Stream reqStream = request.EndGetRequestStream(result);

    // ストリーム出力
    reqStream.Write(m_postDataRaw, 0, m_postDataRaw.Length);
    reqStream.EndWrite(result);
    reqStream.Close();
    m_postDataRaw = null;
    }
    catch (Exception ex)
    {
    Debug.Log("Exception\n" + ex);
    }

    // 非同期処理の完了フラグをセット
    m_isFinishedAsyncProcess = true;
    }

    // このメソッドは非同期処理が完了した際に呼び出されます
    void OnFinishtGetResponse(IAsyncResult result)
    {
    System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)result.AsyncState;

    try
    {
    // レスポンス取得処理を終了
    System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.EndGetResponse(result);

    lock (m_responceLock)
    {
    // レスポンスコード取得
    m_responseCode = (int)response.StatusCode;

    // レスポンスヘッダ取得
    m_responseHeader = "";
    for (int i = 0; i < response.Headers.Count; ++i)
    {
    string key = response.Headers.GetKey(i);
    foreach (string value in response.Headers.GetValues(i))
    {
    string text;
    if (key == null)
    {
    text = value;
    }
    else
    {
    text = key + ":" + value;
    switch (key.ToLower())
    {
    case "content-type":
    string[] types = value.Split(';', ' ');
    if (types.Length != 0)
    {
    m_responseContentType = types[0];
    }
    break;
    }
    }
    m_responseHeader += text + "\n";
    }
    }

    // レスポンス文字列を取得
    Stream stream = response.GetResponseStream();
    m_responseText = new StreamReader(stream).ReadToEnd();
    }
    }
    catch (Exception ex)
    {
    Debug.Log("Exception\n" + ex);
    }

    // 非同期処理の完了フラグをセット
    m_isFinishedAsyncProcess = true;
    }

    // リクエスト送信
    public IEnumerator CoSendRequest()
    {
    Debug.Log(
    "HwrWebHandler.CoSendRequest() - \"" + m_url + "\"\n" +
    " method: " + m_method + "\"\n"
    );
    lock (m_responceLock)
    {
    m_responseCode = 0;
    m_responseContentType = null;
    m_responseText = null;
    }

    System.Net.HttpWebRequest request;
    try
    {
    // 証明書の検証処理を設定
    if (m_isAllowSelfSignedCertificate)
    {
    // 自己署名証明書を許可する
    System.Net.ServicePointManager.ServerCertificateValidationCallback =
    new System.Net.Security.RemoteCertificateValidationCallback(ValidateAnyServerCertificate);
    }
    else
    {
    // システムのデフォルト値に戻す
    System.Net.ServicePointManager.ServerCertificateValidationCallback = null;
    }

    // HttpWebRequest作成
    request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(m_url);

    // BASIC認証の設定
    if (!string.IsNullOrEmpty(m_authorization))
    {
    request.Headers.Add("AUTHORIZATION", m_authorization);
    }
    }
    catch (System.Net.WebException webException)
    {
    Debug.Log("webException\n" + webException);
    yield break;
    }

    // POSTメソッドの場合の設定
    if (m_method == "POST")
    {
    Debug.Log(" postString:\n" + m_postString);
    m_isFinishedAsyncProcess = false;

    // 非同期でデータ送信処理を開始
    try
    {
    // POSTデータ作成
    request.Method = "POST";
    m_postDataRaw = System.Text.Encoding.UTF8.GetBytes(m_postString);
    request.ContentType = m_postContentType;
    request.ContentLength = m_postDataRaw.Length;

    request.BeginGetRequestStream(new AsyncCallback(this.OnFinishGetRequestStream), request);
    }
    catch (System.Net.WebException webException)
    {
    Debug.Log("webException\n" + webException);
    yield break;
    }

    // 非同期処理の完了待ち
    while (!m_isFinishedAsyncProcess)
    {
    yield return null;
    }
    }

    // 非同期で受信処理を開始
    m_isFinishedAsyncProcess = false;
    try
    {
    request.BeginGetResponse(new AsyncCallback(this.OnFinishtGetResponse), request);
    }
    catch (System.Net.WebException webException)
    {
    Debug.Log("webException\n" + webException);
    yield break;
    }

    // 非同期処理の完了待ち
    while (!m_isFinishedAsyncProcess)
    {
    yield return null;
    }
    }
    }