Search Unity

Best HTTP Released

Discussion in 'Assets and Asset Store' started by BestHTTP, Sep 11, 2013.

  1. xpxilom

    xpxilom

    Joined:
    Aug 28, 2014
    Posts:
    30
    Why can't I login here:
    http://kingdomlikes.com/


    I'm doing the post completely. But for some reason, it gives me an error.
    Code (CSharp):
    1.   string token;
    2.     public void Login01()
    3.         {
    4.  
    5.  
    6.         string login1 = "http://kingdomlikes.com/";
    7.         string login = "http://kingdomlikes.com/login";
    8.         HTTPRequest request3 = new HTTPRequest(new Uri(login1), HTTPMethods.Get, (req3, resp3) =>
    9.             {
    10.                 string a2 = resp3.DataAsText;
    11.  
    12.                 token = getBetween(a2, "_token\" value=\"", "\">");
    13.  
    14.                 HTTPRequest request = new HTTPRequest(new Uri(login), HTTPMethods.Post, (req, resp) =>
    15.                 {
    16.  
    17.                     Debug.Log(resp.DataAsText);
    18.                
    19.                 });
    20.  
    21.  
    22.                 request.RawData = Encoding.UTF8.GetBytes("email=" + "xpxilom@gmail.com"+ "&password=" + GameObject.Find("contraseña").GetComponent<InputField>().text + "&_token=" + token);        
    23.                 request.Send();          
    24.  
    25.             });
    26.  
    27.      
    28.             // Force the plugin to use the multipart/form-data encoding
    29.             request3.Send();
    30.         }
    I don't know what to do anymore, I'm frustrated because of it... I's very simple according to Fiddle Web and firefox debugger.
     
  2. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @xpxilom

    What error are you receiving?
    Also, you may want to use the AddField function of the request setting form values instead of the RawData approach here as it should be url escaped that you are doesn't do here.
     
  3. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @xpxilom

    Here is my complete, working solution. You have to call KingdomLikeLoginTest(); and it will do the following requests:
    1. One GET request to the main site to grab the _token
    2. One POST request to login
    3. One automatic GET request to the /free_points page because of a redirection on a successful login.

    You can disable the redirection by returning false in the Request_OnBeforeRedirection event.

    Some notes:
    • You have to fill the email and password fields, as i removed my credentials
    • You should use the HTTPS version of the site

    Code (CSharp):
    1. void KingdomLikeLoginTest()
    2. {
    3.     Uri mainUri = new Uri("http://kingdomlikes.com/");
    4.     new HTTPRequest(mainUri, OnMainFinished)
    5.         .Send();
    6. }
    7.  
    8. private void OnMainFinished(HTTPRequest req, HTTPResponse resp)
    9. {
    10.     switch (req.State)
    11.     {
    12.         // The request finished without any problem.
    13.         case HTTPRequestStates.Finished:
    14.             if (resp.IsSuccess)
    15.             {
    16.                 Debug.Log("Request Finished Successfully! Response: " + resp.DataAsText);
    17.  
    18.                 string token = getBetween(resp.DataAsText, "_token\" value=\"", "\">");
    19.                 LoginWith(token);
    20.             }
    21.             else // Internal server error?
    22.                 Debug.LogWarning(string.Format("Request Finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
    23.                                                 resp.StatusCode,
    24.                                                 resp.Message,
    25.                                                 resp.DataAsText));
    26.             break;
    27.  
    28.         // The request finished with an unexpected error. The request's Exception property may contain more info about the error.
    29.         case HTTPRequestStates.Error:
    30.             Debug.LogWarning("Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"));
    31.             break;
    32.  
    33.         // The request aborted, initiated by the user.
    34.         case HTTPRequestStates.Aborted:
    35.             Debug.LogWarning("Request Aborted!");
    36.             break;
    37.  
    38.         // Ceonnecting to the server is timed out.
    39.         case HTTPRequestStates.ConnectionTimedOut:
    40.             Debug.LogError("Connection Timed Out!");
    41.             break;
    42.  
    43.         // The request didn't finished in the given time.
    44.         case HTTPRequestStates.TimedOut:
    45.             Debug.LogError("Processing the request Timed Out!");
    46.             break;
    47.     }
    48. }
    49.  
    50. private string getBetween(string dataAsText, string v1, string v2)
    51. {
    52.     int pos = dataAsText.IndexOf(v1) + v1.Length;
    53.     int pos2 = dataAsText.IndexOf(v2, pos);
    54.  
    55.     return dataAsText.Substring(pos, pos2 - pos);
    56. }
    57.  
    58. void LoginWith(string token)
    59. {
    60.     Uri loginUri = new Uri("http://kingdomlikes.com/login");
    61.     var request = new HTTPRequest(loginUri, HTTPMethods.Post, OnLoginFinished);
    62.     request.AddField("email", "");
    63.     request.AddField("password", "");
    64.     request.AddField("remember-me", "1");
    65.     request.AddField("_token", token);
    66.  
    67.     request.OnBeforeRedirection += Request_OnBeforeRedirection;
    68.     request.Send();
    69. }
    70.  
    71. private bool Request_OnBeforeRedirection(HTTPRequest originalRequest, HTTPResponse response, Uri redirectUri)
    72. {
    73.     // The new redirection must be done with a GET request
    74.     originalRequest.MethodType = HTTPMethods.Get;
    75.  
    76.     // Do not send the form with it
    77.     originalRequest.ClearForm();
    78.  
    79.     // Return true to allow the redirection
    80.     return true;
    81. }
    82.  
    83. void OnLoginFinished(HTTPRequest req, HTTPResponse resp)
    84. {
    85.     switch (req.State)
    86.     {
    87.         // The request finished without any problem.
    88.         case HTTPRequestStates.Finished:
    89.             if (resp.IsSuccess)
    90.             {
    91.                 Debug.Log("Request Finished Successfully! Response: " + resp.DataAsText);
    92.             }
    93.             else // Internal server error?
    94.                 Debug.LogWarning(string.Format("Request Finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
    95.                                                 resp.StatusCode,
    96.                                                 resp.Message,
    97.                                                 resp.DataAsText));
    98.             break;
    99.  
    100.         // The request finished with an unexpected error. The request's Exception property may contain more info about the error.
    101.         case HTTPRequestStates.Error:
    102.             Debug.LogWarning("Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"));
    103.             break;
    104.  
    105.         // The request aborted, initiated by the user.
    106.         case HTTPRequestStates.Aborted:
    107.             Debug.LogWarning("Request Aborted!");
    108.             break;
    109.  
    110.         // Ceonnecting to the server is timed out.
    111.         case HTTPRequestStates.ConnectionTimedOut:
    112.             Debug.LogError("Connection Timed Out!");
    113.             break;
    114.  
    115.         // The request didn't finished in the given time.
    116.         case HTTPRequestStates.TimedOut:
    117.             Debug.LogError("Processing the request Timed Out!");
    118.             break;
    119.     }
    120. }
     
    xpxilom likes this.
  4. StephenZepp

    StephenZepp

    Joined:
    Feb 25, 2016
    Posts:
    13
    I wanted to give a heads up about an issue that I ran into for the last several hours setting up BestHTTP on a local dev environment with a ruby/rails server just in case someone runs into something similar. Please note that the issue isn't *really* with BestHTTP, but users with similar scenarios to mine might wind up thinking so at least initially.

    My dev environment is a Win 7 machine with IPv6 enabled network card, running Unity 5.3.2f1 and BestHTTP 1.9.9, with Rails 4.2 and Puma as my server dev environment.

    I was getting connection actively refused responses on even the most basic HTTPRequest attempts (simply get the root url), yet my browser could get a response from the exact same URL, and I flat out could not figure out what the issue was, until I happened to look at my netstat -- which showed that my web server was ONLY binding to an IPV6 address.

    I'm honestly not sure if BestHTTP is configured to handle IPv6, but if it is, it isn't working--and if it isn't, it probably should be on the roadmap as IPv6 becomes more prevalent?

    For me the solution was simple once I figured out what was going on: I forced the rails server to bind directly to an IPv4 address (rails s -b 127.0.0.1), but troubleshooting the issue was extremely difficult with my relatively low networking experience.

    Hope this helps someone in the future :)
     
  5. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @StephenZepp

    Thanks for the feedback!
    The plugin should work with IPv6 fine, as the same code works on iOS using only IPv6.
    I will try to debug it out what's the exact problem and how I can improve the plugin.

    For now I have a theory that it might be a problem that the DNS query returned with an IPv4 address and an IPv6 one, but while the plugin tries to connect to the first one it will time out. Or sometimes it receives back an IPv4 address only? I will investigate it.
     
  6. arodes

    arodes

    Joined:
    Sep 8, 2015
    Posts:
    5
    Hey BestHTTP,

    I have a little problem with my SignalR connection. It seems that the PrepareRequest method from the IAuthenticationProvider is not called before every request.

    The method is called before every connection request, but not before the hub calls as expected.
    Is this behaviour intentional or a bug?

    Btw: I'm using v1.9.9 Pro
     
  7. StephenZepp

    StephenZepp

    Joined:
    Feb 25, 2016
    Posts:
    13
    It definitely doesn't time out in the normal sense--I think based on what I saw that if it does get an IPv4 address back it attempts it, but if there is no listener it then bails out with connection actively refused. It definitely didn't wait the 20 seconds set for timeout errors if that helps.
     
  8. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @arodes

    The PrepareRequest is called on every http request. If the plugin is able to connect with WebSocket(that's only one http request!), then all hub calls made with it will not result in new PrepareRequest calls.
     
  9. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @StephenZepp

    Thanks for the additional information, it's very helpful!
     
  10. arodes

    arodes

    Joined:
    Sep 8, 2015
    Posts:
    5
    Thanks for the response.
    Seems that missunderstood a few parts in the SignalR connection. So there is no possibility to update the authentication cookie after it expired without restarting the connection?
     
  11. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @arodes

    Well, Ping requests are still sent as regular HTTP requests where you can refresh these cookies. However there were a bug that PrepareReuest doesn't called for these types of requests... Sent a new updated package in private.

    You can set the PingInterval on the connection, by default it will send out ping requests every 5 minutes.
     
  12. StephenZepp

    StephenZepp

    Joined:
    Feb 25, 2016
    Posts:
    13
    I'm trying to parse some JSON being returned from my server using the build in BestHTTP JSON parser, but I can't figure out how to parse the following:

    {"name":["can't be blank"]}

    Obviously (I think!), that should be cast as a Dictionary<string, object> ... but every time I try to cast the value side, I get a null reference. I'm just not sure how to get at the "can't be blank" portion of the error to display it as a string.

    Various JSON validators report that as valid JSON, and it seems ["can't be blank"] is a json array, but it won't seem to cast properly to any c# collection.

    Here's my current attempt:
    var data = BestHTTP.JSON.Json.Decode(mServerResponseMessage) as Dictionary<string, object>;

    foreach (KeyValuePair<string, object> entry in data)
    {
    var lineValue = entry.Value as List<string>;
    Debug.Log("Key is >" + entry.Key + "<, lineValue is >" + lineValue[0]);
    }

    Running in Unity with Visual Studio attached, the data variable casts properly, and the foreach statement works fine...and entry.Value shows as a generic object as expected.

    However, when lineValue is cast as any collection type I can think of, it results in being null. I've even tried just using entry.Value.ToString(), but that always reports:

    Key is >name<, lineValue is >System.Collections.Generic.List`1[System.Object]<

    I'm pretty new to C# so I'm probably missing something--anyone have any ideas what?
     
  13. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @StephenZepp

    You have to cast to a List of Object (List<object>) instead of List<string>. It's because an array can contain other arrays or objects, not just strings:
    Code (CSharp):
    1. var data = BestHTTP.JSON.Json.Decode(mServerResponseMessage) as Dictionary<string, object>;
    2.  
    3. foreach (KeyValuePair<string, object> entry in data)
    4. {
    5.     var lineValue = entry.Value as List<object>;
    6.     Debug.Log("Key is >" + entry.Key + "<, lineValue is >" + lineValue[0].ToString());
    7. }
     
  14. StephenZepp

    StephenZepp

    Joined:
    Feb 25, 2016
    Posts:
    13
    Sure enough, thanks! Interestingly, I didn't even need the lineValue[0].ToString()); portion, once it was cast to an object it worked perfectly!

    Thanks a bunch...rails validators have been inconsistent all across my parsing, so this will help a ton.
     
  15. li76168

    li76168

    Joined:
    Sep 7, 2014
    Posts:
    11
    Hello,

    When I build to WebGL and play, it show "An error occured running the Unity content on this page. See your browser's JavaScript console for more info. The error was:
    TypeError: socket is undefined"

    how to fix it?

    Thanks
     
  16. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @li76168 What version of the plugin are you using? WebGL support is added in v1.9.3, i think previous versions might drop this error only.
     
  17. jguibault

    jguibault

    Joined:
    Sep 20, 2012
    Posts:
    7
    Hello,

    We've just bought BESTHttp Pro for a project, and we love what we've seen so far. One issue we're having, is we can't find any information about the licensing of the product. What is it licensed under?

    Thanks
     
  18. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @jguibault

    Thank you for the compliment!

    You can find the EULA here: http://unity3d.com/legal/as_terms. Unfortunately you have to scroll down to Asset STORE End User License Agreement manually or you have to use the Quick Jump on the right. All assets are distributed under this EULA in the Asset Store.
     
  19. zhuchun

    zhuchun

    Joined:
    Aug 11, 2012
    Posts:
    433
    Hi,

    Why HTTPResponse returns statusCode=304 while DataAsText has correct data? My nodejs server actually doesn't have such a response. POSTman get 200 in the mean while.

    [Solved]
    After googleing, the problem was caused by the cache mechanism, if you don't wanna this feature or just wanna get rid of it, try below.
    HTTPRequest.DisableCache = true;
     
    Last edited: Mar 1, 2016
  20. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @zhuchun

    The server sent the response with at least one caching header(ETag and/or Last-Modified), so the plugin tried to re-validate the stored content. For this re-validation request the server answered with an Status Code 304 (Not Modified) so the plugin loaded the locally stored content and served it.

    If you want, you can enable/disable caching per-request or globally for all requests.
     
    zhuchun likes this.
  21. phuc hoang

    phuc hoang

    Joined:
    Sep 12, 2014
    Posts:
    5
    I use besthttp pro socket.io to connect to my server use socket.io version 1.4.5.. But when i tried connect, show error
    Err [HandshakeData]: Handshake request failed with error: Handshake request finished Successfully, but the server sent an error. Status Code: 400-Bad Request Message: {"code":3,"message":"Bad request"} Uri: http://localhost:4567/socket.io/?EIO=4&transport=websocket&t=832630872-7&b64=true
    UnityEngine.Debug:LogError(Object)
    BestHTTP.Logger.DefaultLogger:Error(String, String) (at Assets/Best HTTP (Pro)/BestHTTP/Logger/DefaultLogger.cs:76)
    BestHTTP.SocketIO.HandshakeData:RaiseOnError(String) (at Assets/Best HTTP (Pro)/BestHTTP/SocketIO/HandshakeData.cs:159)

    So how to solve problem?? besthttp pro not compatible with lastest socket.io ??
     
  22. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @phuc hoang

    Can you share the whole log? This error line isn't the first connection attempt, also it shouldn't use websocket as a transport in a negotiation request.

    The plugin supports the latest version (1.4.x) of Socket.IO.
     
  23. Plukers

    Plukers

    Joined:
    Jun 17, 2015
    Posts:
    1
    Hey,
    thank you for your great asset!
    We are using it in our application and we never had problems.

    But now we want to realease a Windows 10 Universal App and it seems that we cant send anything.
    According to Wireshark, the TCP connection gets established as normal.
    But as soon as we send the login data to the server via the HTTPRequest, nothing happens.

    Are there some known issues with W10 Apps? Could you give me some advice or tipps on how to find the issue? Where to look and so on?
    Thank you very much!

    EDIT:
    Some more Information and wording.
    The given response in the HTTPRequest callback method is null.
     
    Last edited: Mar 1, 2016
  24. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @Plukers

    There were an issue that might cause a problem like this. I will send you a link to an updated package.
     
    Last edited: Mar 1, 2016
  25. phuc hoang

    phuc hoang

    Joined:
    Sep 12, 2014
    Posts:
    5
    I had changed this code in HandshakeData Script
    HandshakeRequest = new HTTPRequest(new Uri(string.Format("{0}?EIO={1}&transport=websocket&t={2}-{3}{4}&b64=true",
    =>> change "transport=pooling" by "transport=websocket" because when i use transport=pooling, show error
    Err [HandshakeData]: Handshake request failed with error: Handshake request finished Successfully, but the server sent an error. Status Code: 400-Bad Request Message: {"code":0,"message":"Transport unknown"} Uri: http://localhost:4567/socket.io/?EI...O=4&transport=polling&t=832603993-20&b64=true
    UnityEngine.Debug:LogError(Object)
    BestHTTP.Logger.DefaultLogger:Error(String, String) (at Assets/Best HTTP (Pro)/BestHTTP/Logger/DefaultLogger.cs:76)

    When i change this code, show error
    Err [HandshakeData]: Handshake request failed with error: Handshake request finished Successfully, but the server sent an error. Status Code: 400-Bad Request Message: {"code":3,"message":"Bad request"} Uri: http://localhost:4567/socket.io/?EIO=4&transport=websocket&t=832607965-1&b64=true
    UnityEngine.Debug:LogError(Object)
    BestHTTP.Logger.DefaultLogger:Error(String, String) (at Assets/Best HTTP (Pro)/BestHTTP/Logger/DefaultLogger.cs:76)
    BestHTTP.SocketIO.HandshakeData:RaiseOnError(String) (at Assets/Best HTTP (Pro)/BestHTTP/SocketIO/HandshakeData.cs:159)
     
  26. phuc hoang

    phuc hoang

    Joined:
    Sep 12, 2014
    Posts:
    5
    My server cannot get any connection.., when i tried connect by socket-io client in browser, everything work fine.. But when use besthttp Pro, i cannot connect
     
  27. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @phuc hoang

    "Transport unknown" error returned only when polling transport is disabled on server side. The polling transport shouldn't be disabled as it's the base type for negotiation, and the plugin will try to upgrade to websocket anyway.

    With a fresh download of Socket.IO I'm able to connect as usual. Can you try the Socket.IO samples? Are they working fine? If so, it might be a little misconfiguration of your local server.
     
  28. phuc hoang

    phuc hoang

    Joined:
    Sep 12, 2014
    Posts:
    5
    my server works fine with browser client, I only want use websocket to connect to my server, u can send me your example Socket.io (server + unity), i use BestHttpPro 1.9.8
     
  29. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @phuc hoang

    Currently the plugin can do the handshake process only with the polling transport.
     
  30. phuc hoang

    phuc hoang

    Joined:
    Sep 12, 2014
    Posts:
    5
    so currently i cannot connect with my server by websocket transport :( please add this feature in next release .. because websocket is great and better performance
     
  31. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @phuc hoang

    Well, in normal case only one request will be made using the polling: to get the handshake data. But, If the handshake data contains the WebSocket as an enabled upgrade, the plugin will upgrade to it, and it will use the WebSocket transport to send and receive data.

    As the connection pooling is enabled by default, the websocket upgrade will be much faster then the first handshake request. So, you don't loose too much performance by doing the first request with polling...
     
  32. li76168

    li76168

    Joined:
    Sep 7, 2014
    Posts:
    11
    v1.9.9
     
  33. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @li76168 Hmm, that's strange. Can you send me a repro-project?
     
  34. m4d

    m4d

    Joined:
    Jan 25, 2012
    Posts:
    27
    Hi, i bought this asset some time ago and just recently started to use it and really like it. I use the websocket implementation to subscribe to the blockchain.info websocket api, but after a few hundred messages it stops working and while the OnMessageReceived event is still triggered i'm unable to get the message contents once it stops working. I sent you a link to a test project via PM.

    Best Regards,
    Chris
     
  35. Boslem

    Boslem

    Joined:
    Aug 15, 2012
    Posts:
    11
    Hi there,

    I had a problem with all HTTP requests returning null responses on Android when the stripping level was set to "Strip Assemblies". On IOS it works fine but Android it means my app doesn't work.

    Is there a way for me to keep strip assemblies on for both builds?

    I have to "Strip Assemblies" on IOS to reduce the app size so having to keep track of the setting between the two all the time while developing will be a nightmare.

    Besides this the plugin is brilliant and it has revolutionised the way I do my network programming :)

    Thanks!
     
  36. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @m4d

    Thank you for the repro project, it helps a lot. For a quick workaround you can disable the Per-Message Compression extension:
    Code (CSharp):
    1. webSocket = new WebSocket(new Uri("wss://ws.blockchain.info/inv"), null, null, null);
    I will check it out in detail too.
     
    m4d likes this.
  37. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @Boslem

    Please try out this link.xml:
    You have to modify the one in the \Assets\Best HTTP (Pro)\ directory.
     
  38. StephenZepp

    StephenZepp

    Joined:
    Feb 25, 2016
    Posts:
    13
    I've been using BestHTTP for a couple of weeks now, and really love the asset--it's great!

    Unfortunately, I'm new to both Unity and C# (lots of years with other languages/engines), and I'm really struggling with how to parse json results from my server queries into strongly typed classes, so I figured I'd ask here.

    I'm very open to questions about why/what I'm trying to do, but I'll try to be detailed here first.

    I'm getting the following json response from my server:
    Code (csharp):
    1.  
    2. [{"house":{"id":20,"name":"Altgard","detailTexture":null,"created_at":"2016-03-03T16:20:55.926Z","updated_at":"2016-03-03T16:20:55.926Z","primary_r":"1.0","primary_g":"1.0","primary_b":"1.0","secondary_r":"1.0","secondary_g":"0.0","secondary_b":"0.0","tertiary_r":"0.0","tertiary_g":"0.0","tertiary_b":"0.0","shieldTexture":"shield_5","blazonTexture":"cross_3","shieldClass":"shield","blazonClass":"cross","user_id":9,"cityMarkersDirty":true}},{"house":{"id":21,"name":"Valrith","detailTexture":null,"created_at":"2016-03-03T16:22:55.783Z","updated_at":"2016-03-03T16:22:55.783Z","primary_r":"0.0","primary_g":"0.0","primary_b":"0.0","secondary_r":"0.0","secondary_g":"0.9979839","secondary_b":"0.0","tertiary_r":"0.0","tertiary_g":"0.0","tertiary_b":"0.0","shieldTexture":"shield_8","blazonTexture":"cross_4","shieldClass":"shield","blazonClass":"cross","user_id":12,"cityMarkersDirty":true}}]
    3.  
    Which is valid -- it's a list of what "houses" the player is aware of. When I get this response back from the server, I want to create a new c# object of the class "house", and add it to a dictionary that indexes houses by their id:

    Code (csharp):
    1.  
    2.     public class house
    3.     {
    4.         public string id { get; set; }
    5.         public string name { get; set; }
    6.         public float primary_r { get; set; }
    7.         public float primary_g { get; set; }
    8.         public float primary_b { get; set; }
    9.         public float secondary_r { get; set; }
    10.         public float secondary_g { get; set; }
    11.         public float secondary_b { get; set; }
    12.         public float tertiary_r { get; set; }
    13.         public float tertiary_g { get; set; }
    14.         public float tertiary_b { get; set; }
    15.         public string shieldTexture { get; set; }
    16.         public string blazonTexture { get; set; }
    17.         public string shieldClass { get; set; }
    18.         public string blazonClass { get; set; }
    19.         public string user_id { get; set; }
    20.  
    21.     }
    22.    
    23.     public Dictionary<string, house> knownHouses = new Dictionary<string, house>();
    24.  
    I've tried hundreds of combinations of code examples using reflection from the web, various JSON parsing techniques, and finally remembered that BestHTTP has LitJson built in, but I still can't get the objects to map properly out of the json result. Here's my latest code (does not work):
    Code (csharp):
    1.  
    2.     public void processKnownHouses(BestHTTP.HTTPResponse resp)
    3.     {
    4.          var data = BestHTTP.JSON.Json.Decode(resp.DataAsText);
    5.         //JsonData HouseData = JsonMapper.ToObject(resp.DataAsText);
    6.         List<house> HouseData = JsonMapper.ToObject<List<house>>(resp.DataAsText);
    7.         for (var i = 0; i < HouseData.Count; i++)
    8.         {
    9.             string newHouseIndex = HouseData[i].id;
    10.             EmpireGameData.instance.knownHouses.Add(newHouseIndex, HouseData[i]);
    11.             Debug.Log("processKnownHouses, adding house >" + newHouseIndex + "<, count is >" + EmpireGameData.instance.knownHouses.Count.ToString() + "<");
    12.         }
    13.         GameObject.Find("ServerSynchDisplay").GetComponent<ServerSynchDisplay>().requestProcessed(ServerSynchDisplay.synchRequestType.KnownHouses);
    14.  
    15.     }
    16.  
    17.  
    In the code above, the List<house> HouseData gets set up properly with two elements, and each element is properly of the class "house"--but the data is missing: each class member is set to their initialized values instead of the data from the json.

    Does anyone have any idea what I'm missing here?
     
  39. m4d

    m4d

    Joined:
    Jan 25, 2012
    Posts:
    27
    Thanks for the quick reply! Seems to work really well without the compression.
     
  40. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @StephenZepp

    By prettifying your json we can spot what the problem is:
    Code (CSharp):
    1. string json = @"[
    2.                    {
    3.                        ""house"": {
    4.                            ""id"": 20,
    5.                            ""name"": ""Altgard"",
    6.                            ""detailTexture"": null,
    7.                            ""created_at"": ""2016-03-03T16:20:55.926Z"",
    8.                            ""updated_at"": ""2016-03-03T16:20:55.926Z"",
    9.                            ""primary_r"": ""1.0"",
    10.                            ""primary_g"": ""1.0"",
    11.                            ""primary_b"": ""1.0"",
    12.                            ""secondary_r"": ""1.0"",
    13.                            ""secondary_g"": ""0.0"",
    14.                            ""secondary_b"": ""0.0"",
    15.                            ""tertiary_r"": ""0.0"",
    16.                            ""tertiary_g"": ""0.0"",
    17.                            ""tertiary_b"": ""0.0"",
    18.                            ""shieldTexture"": ""shield_5"",
    19.                            ""blazonTexture"": ""cross_3"",
    20.                            ""shieldClass"": ""shield"",
    21.                            ""blazonClass"": ""cross"",
    22.                            ""user_id"": 9,
    23.                            ""cityMarkersDirty"": true
    24.                        }
    25.                    },
    26.                    {
    27.                        ""house"": {
    28.                            ""id"": 21,
    29.                            ""name"": ""Valrith"",
    30.                            ""detailTexture"": null,
    31.                            ""created_at"": ""2016-03-03T16:22:55.783Z"",
    32.                            ""updated_at"": ""2016-03-03T16:22:55.783Z"",
    33.                            ""primary_r"": ""0.0"",
    34.                            ""primary_g"": ""0.0"",
    35.                            ""primary_b"": ""0.0"",
    36.                            ""secondary_r"": ""0.0"",
    37.                            ""secondary_g"": ""0.9979839"",
    38.                            ""secondary_b"": ""0.0"",
    39.                            ""tertiary_r"": ""0.0"",
    40.                            ""tertiary_g"": ""0.0"",
    41.                            ""tertiary_b"": ""0.0"",
    42.                            ""shieldTexture"": ""shield_8"",
    43.                            ""blazonTexture"": ""cross_4"",
    44.                            ""shieldClass"": ""shield"",
    45.                            ""blazonClass"": ""cross"",
    46.                            ""user_id"": 12,
    47.                            ""cityMarkersDirty"": true
    48.                        }
    49.                    }
    50.                ]";
    It's a list of objects that contain one dictionary with only one object, a house object.
    Another problem is the types of the properties. "Id" and "user_id" comes as an integer, while others that you declared as float are sent as strings.

    Made some changes to your code, and this looks fine now:
    Code (CSharp):
    1. public class house
    2. {
    3.     public int id { get; set; }
    4.     public string name { get; set; }
    5.     public string primary_r { get; set; }
    6.     public string primary_g { get; set; }
    7.     public string primary_b { get; set; }
    8.     public string secondary_r { get; set; }
    9.     public string secondary_g { get; set; }
    10.     public string secondary_b { get; set; }
    11.     public string tertiary_r { get; set; }
    12.     public string tertiary_g { get; set; }
    13.     public string tertiary_b { get; set; }
    14.     public string shieldTexture { get; set; }
    15.     public string blazonTexture { get; set; }
    16.     public string shieldClass { get; set; }
    17.     public string blazonClass { get; set; }
    18.     public int user_id { get; set; }
    19.     public bool cityMarkersDirty { get; set; }
    20.  
    21. }
    22.  
    23. public class HouseHolder
    24. {
    25.     public house house;
    26. }
    27.  
    28. public Dictionary<int, house> knownHouses = new Dictionary<int, house>();
    29.  
    30. void House_JSonParseTest()
    31. {
    32.     string json = @"[
    33.                        {
    34.                            ""house"": {
    35.                                ""id"": 20,
    36.                                ""name"": ""Altgard"",
    37.                                ""detailTexture"": null,
    38.                                ""created_at"": ""2016-03-03T16:20:55.926Z"",
    39.                                ""updated_at"": ""2016-03-03T16:20:55.926Z"",
    40.                                ""primary_r"": ""1.0"",
    41.                                ""primary_g"": ""1.0"",
    42.                                ""primary_b"": ""1.0"",
    43.                                ""secondary_r"": ""1.0"",
    44.                                ""secondary_g"": ""0.0"",
    45.                                ""secondary_b"": ""0.0"",
    46.                                ""tertiary_r"": ""0.0"",
    47.                                ""tertiary_g"": ""0.0"",
    48.                                ""tertiary_b"": ""0.0"",
    49.                                ""shieldTexture"": ""shield_5"",
    50.                                ""blazonTexture"": ""cross_3"",
    51.                                ""shieldClass"": ""shield"",
    52.                                ""blazonClass"": ""cross"",
    53.                                ""user_id"": 9,
    54.                                ""cityMarkersDirty"": true
    55.                            }
    56.                        },
    57.                        {
    58.                            ""house"": {
    59.                                ""id"": 21,
    60.                                ""name"": ""Valrith"",
    61.                                ""detailTexture"": null,
    62.                                ""created_at"": ""2016-03-03T16:22:55.783Z"",
    63.                                ""updated_at"": ""2016-03-03T16:22:55.783Z"",
    64.                                ""primary_r"": ""0.0"",
    65.                                ""primary_g"": ""0.0"",
    66.                                ""primary_b"": ""0.0"",
    67.                                ""secondary_r"": ""0.0"",
    68.                                ""secondary_g"": ""0.9979839"",
    69.                                ""secondary_b"": ""0.0"",
    70.                                ""tertiary_r"": ""0.0"",
    71.                                ""tertiary_g"": ""0.0"",
    72.                                ""tertiary_b"": ""0.0"",
    73.                                ""shieldTexture"": ""shield_8"",
    74.                                ""blazonTexture"": ""cross_4"",
    75.                                ""shieldClass"": ""shield"",
    76.                                ""blazonClass"": ""cross"",
    77.                                ""user_id"": 12,
    78.                                ""cityMarkersDirty"": true
    79.                            }
    80.                        }
    81.                    ]";
    82.  
    83.     List<HouseHolder> HouseData = JsonMapper.ToObject<List<HouseHolder>>(json);
    84.     for (var i = 0; i < HouseData.Count; i++)
    85.     {
    86.         int newHouseIndex = HouseData[i].house.id;
    87.         knownHouses.Add(newHouseIndex, HouseData[i].house);
    88.     }
    89. }
    You can use the resp.DataAsText instead of the json field of course.
     
  41. StephenZepp

    StephenZepp

    Joined:
    Feb 25, 2016
    Posts:
    13
    Great catches--I would have *never* figured out the HouseHolder class that was needed! Works as advertised.

    Working on a solution now to get those pesky rails "stringfloats" working.

    Thanks again!
     
    Last edited: Mar 4, 2016
  42. GuyTidhar

    GuyTidhar

    Joined:
    Jun 24, 2009
    Posts:
    320
    @BestHTTP

    What about WebGL? this is unavailable in WebGL.
     
  43. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @GuyTidhar

    On WebGL the plugin will use the underlying browser's XHR requests. This is why you can't use the alternate one in this build, but in return most probably they can handle HTTPS very well.
     
  44. GuyTidhar

    GuyTidhar

    Joined:
    Jun 24, 2009
    Posts:
    320
    I see. Thanks.
     
  45. rarebyte

    rarebyte

    Joined:
    Sep 26, 2015
    Posts:
    11
    Hey there. How would I download and decompress a file that's stored as gzipped binary data? The manual said gzip would work behind the scenes, but currently I get incorrect data when doing it like this:

    HTTPRequest request = new HTTPRequest(new Uri(url)); //url points to a binary file that was compressed using gzip.
    request.Send();
    yield return StartCoroutine(request);
    responseData = request.Response.Data;

    Note that the file I'm downloading ends with .bytes. Should I change that to .gz and that'd do the trick? Or is there something else to it? Thanks.

    Edit: Simply naming the files .gz didn't do the trick for me
     
  46. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @rarebyte The pluign will decompress downloaded data if it's sent with a "Content-Encoding: gzip" header. It's usually transparent for the user, as usually this compression is done by the web server.
    On the other hand, if you download a file that contains compressed data, the plugin can't guess that it is compressed, and will not try to decompress. It's also possible that what it downloads are double-compressed (the content itself compressed, and the web-server compress it again and sends it with gzip Content-Encoding). But in this case, the plugin will decompress it only once, you will get the original - compressed - data.

    All in all, you have to decompress your downloaded data manually.
     
  47. Xorxor

    Xorxor

    Joined:
    Oct 15, 2014
    Posts:
    24
    Hi. Is there a simple way to determine how long a request took? Something like:
    Debug.Log(response.timeSinceRequest) // Fake code :D

    Thanks!
     
  48. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @Xorxor

    There are no direct support, but you can add it easily. The HTTPRequest object has a Tag property that you can use to 'store' anything in it:
    Code (CSharp):
    1. Uri uri = new Uri("http://httpbin.org");
    2.  
    3. HTTPRequest request = new HTTPRequest(uri, (req, resp) =>
    4. {
    5.     switch (req.State)
    6.     {
    7.         // The request finished without any problem.
    8.         case HTTPRequestStates.Finished:
    9.             if (resp.IsSuccess)
    10.             {
    11.                 Debug.Log("Request Finished Successfully! Response: " + resp.DataAsText);
    12.  
    13.                 DateTime sentTime = (DateTime)req.Tag;
    14.                 TimeSpan requestTime = DateTime.UtcNow - sentTime;
    15.                 Debug.Log("Request time (ms): " + requestTime.TotalMilliseconds.ToString());
    16.             }
    17.             else // Internal server error?
    18.                 Debug.LogWarning(string.Format("Request Finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}",
    19.                                                 resp.StatusCode,
    20.                                                 resp.Message,
    21.                                                 resp.DataAsText));
    22.             break;
    23.  
    24.         // The request finished with an unexpected error. The request's Exception property may contain more info about the error.
    25.         case HTTPRequestStates.Error:
    26.             Debug.LogWarning("Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"));
    27.             break;
    28.  
    29.         // The request aborted, initiated by the user.
    30.         case HTTPRequestStates.Aborted:
    31.             Debug.LogWarning("Request Aborted!");
    32.             break;
    33.  
    34.         // Ceonnecting to the server is timed out.
    35.         case HTTPRequestStates.ConnectionTimedOut:
    36.             Debug.LogError("Connection Timed Out!");
    37.             break;
    38.  
    39.         // The request didn't finished in the given time.
    40.         case HTTPRequestStates.TimedOut:
    41.             Debug.LogError("Processing the request Timed Out!");
    42.             break;
    43.     }
    44. });
    45.  
    46. request.Tag = DateTime.UtcNow;
    47. request.Send();
     
  49. GuyTidhar

    GuyTidhar

    Joined:
    Jun 24, 2009
    Posts:
    320
    @BestHTTP
    Hi again,

    How do I avoid the release version from logging massive amounts of logs?
    At least in WebGL, the release version seems to be bombarding the console with logs.
    These are mostly logs that start with "XHR_", which seem to be extern functions.

    NOTE: this: " HTTPManager.Logger.Level = BestHTTP.Logger.Loglevels.Error;" - does not stop it. I keep getting non error logs from BestHttp.

    There should really be a way to set these to not log.
     
    Last edited: Mar 8, 2016
  50. BestHTTP

    BestHTTP

    Joined:
    Sep 11, 2013
    Posts:
    1,664
    @GuyTidhar For a quick fix, you can remove the console.log lines in the \Assets\Best HTTP (Pro)\Plugins\WebGL\BestHTTP_WebRequest.jslib file.

    I will remove them or they will depend on the loglevel of the logger too in the next release.