Search Unity

Best HTTP Released

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

  1. MadByteLabs

    MadByteLabs

    Joined:
    May 29, 2011
    Posts:
    18
    It doesn't work in editor mode. I send http request and not become response.
     
  2. BestHTTP

    BestHTTP

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

    When the request is aborted the the plugin will close the tcp connection and various errors will arise. These will be caught by the plugin, but some logging still occur however. All, in all these are harmless if you abort the request and you can ignore them.

    IsKeepAlive: Open connections will consume server resources, but the plugin will close them quite quickly (20 sec) if there's no new request to send out. There's no direct way to close these open connections, however you can lower the default 20 sec to your needs:
    Code (CSharp):
    1. HTTPManager.MaxConnectionIdleTime = TimeSpan.FromSeconds(5);
     
    mcmorry likes this.
  3. BestHTTP

    BestHTTP

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

    Can you share what you tried and what was you Unity version?
    This code just worked right now with Unity 2017.2:
    Code (CSharp):
    1. using System;
    2.  
    3. using UnityEngine;
    4. using UnityEditor;
    5.  
    6. using BestHTTP;
    7.  
    8. public class EditorTest : EditorWindow {
    9.     [MenuItem("Window/Editor Test")]
    10.     public static void Init() {
    11.         EditorWindow.GetWindow(typeof(EditorTest));
    12.     }
    13.  
    14.     void OnGUI() {
    15.         if (GUILayout.Button("Send Request"))
    16.             new HTTPRequest(new Uri("http://httpbin.org/get"), (req, resp) => Debug.Log(resp.DataAsText)).Send();
    17.     }
    18. }
     
  4. MadByteLabs

    MadByteLabs

    Joined:
    May 29, 2011
    Posts:
    18
    @BestHTTP
    Thank, it's ok. This was my mistake.
     
  5. OlivierPons

    OlivierPons

    Joined:
    Sep 20, 2014
    Posts:
    28
    Hi, you have a way to add a cookie, but is there a way to remove a cookie that I dont want to send anymore?
    This "add cookie" code is working:

    Code (CSharp):
    1. var request = new HTTPRequest(new Uri(address), OnFinished);
    2. request.Cookies.Add(new Cookie("Name", "Value"));
    3. request.Send();
    This "remove cookie" code is not working (c is always null whereas the cookie "csrftoken" is still sent):

    Code (CSharp):
    1. HTTPRequest r = new HTTPRequest(new Uri(Url),
    2.     HTTPMethods.Get, /* HTTPMethods methodType */
    3.     true, true,  /* bool isKeepAlive, bool disableCache */
    4.     GetFinished);
    5. Cookie c = r.Cookies.Find(e => e.Name == "csrftoken");
    6. if (c != null) {
    7.     r.Cookies.Remove(c);
    8. }
    9. r.Send();
    I've looked at your code, and you can't modify MaxAge (public long MaxAge { get; private set; })
    To remove a cookie we could set its MaxAge to 0 (see here)

    Maybe you have another solution that could suit me: add a custom filter to SetCookie that ignores specific cookies...
     
    Last edited: Dec 20, 2017
  6. OlivierPons

    OlivierPons

    Joined:
    Sep 20, 2014
    Posts:
    28
    I've been struggling with this problem for 16 hours now, and it drives me nuts.
    I've made a Unity client that uses Best HTTP Pro, for my Django Web application.
    I've generated the .exe file. When I double click to launch the program, many times to try:
    - the first client, let's call it "client A", fetches an URL / GET method, and in that URL, Django sends back "Set cookie" with sessionid = (value1)
    - then the client A fetches an URL / POST method + user and password to login, Django says it's ok
    - the second client, let's call it "client B", fetches an URL / GET method, and... there the cookie of the session of the first client!

    I thought that the first "GET" call of the client B should not know have any cookies and should not send any cookie, right? This is the first "GET". But Wireshark showed me that the client B did already have the cookie of the client A! What am I missing here? Is there memory sharing between the two executables running, or whatever in Windows?
     
  7. BestHTTP

    BestHTTP

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

    Cookies: The response's cookies contains the cookies that came from the server, but it's just a list of them. There a CookieJar that manages all of the cookies. If you want to delete a cookie to do not send back to the server, you have to delete it from the CookieJar.

    You can use the Remove function to remove one cookie:
    Code (CSharp):
    1. BestHTTP.Cookies.CookieJar.Remove(uri, "cookie_key");
    You can clear all stored cookies:
    Code (CSharp):
    1. BestHTTP.Cookies.CookieJar.Clear();
    Or all cookies for a given domain:
    Code (CSharp):
    1. BestHTTP.Cookies.CookieJar.Clear("example.com");
    On your second problem: It's quite expected. The plugin stores the cookies in the folder return by the Application.persistentDataPath. It constructs the path using the CompanyName + Product Name of your app. Because you built one app and executed (at least) two instances, they read from and saved to the very same file.

    So, client A received sessionId from the server and saved cookies to the \CompanyName\ProductName\Cookies folder. Client B will load the CookiJar from the very same \CompanyName\ProductName\Cookies folder that contains the sessionId from client A, so when you initiate a request to the server it will load up the sessionId that client A received.
     
    OlivierPons likes this.
  8. OlivierPons

    OlivierPons

    Joined:
    Sep 20, 2014
    Posts:
    28
    Thank you very much for your good and professional answer! You could copy / paste your nice previous answer to a FAQ addedum in your documentation :)

    So my solution: to launch + test many times the same program, when the user logs in I set the cookie folder as "Cookies/[username]":

    Code (CSharp):
    1.         string p = Path.Combine(Application.persistentDataPath, "Cookies/");
    2.         HTTPManager.RootCacheFolderProvider =
    3.             () => Path.Combine(p, login);
    Do you think it's ok, or there's a better suggestion/practice?
     
    Last edited: Dec 20, 2017
  9. BestHTTP

    BestHTTP

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

    You can define your custom folder provider, so with a clever algorithm, you can generate different paths for each application instance.

    The following is a quite simple example, it will assign a random path for each run (untested). Its drawback is that persistent caching became meaningless, as the next run it will generate a new path. Although it might give you a good headstart.
    Code (CSharp):
    1. BestHTTP.HTTPManager.RootCacheFolderProvider = () => System.IO.Path.Combine(Application.persistentDataPath, UnityEngine.Random.Range(0, int.MaxValue).ToString());
    A better solution would be to be able to configure from the command line, or an ingame console, etc.

    You should set the RootCacheFolderProvider in your startup code before any interaction with the plugin (eg. sending out requests, or starting other protocols).
     
  10. BestHTTP

    BestHTTP

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

    As I see while I wrote my answer you already found the RootCacheProvider. :)

    The problem with your solution is that folders are cached by the various subsystems (cache and cookie jar), so even if you change what path it returns, it will have no effect.

    You have one option that i can see, that you have to generate a unique path when your app starts.
     
  11. w4der

    w4der

    Joined:
    Sep 17, 2011
    Posts:
    17
    Hi,
    I have problem with my Best HTTP basic edition.

    Code (CSharp):
    1. void Start() {
    2.         SocketOptions options = new SocketOptions();
    3.         options.AutoConnect = false;
    4.         socketManager = new SocketManager(new Uri("http://192.168.0.129:3000/socket.io/"), options);
    5.  
    6.         socket = socketManager.Socket;
    7.         socketManager.Socket.On(ResponseEventEnum.ERROR, OnError);
    8.         socketManager.Socket.On(ResponseEventEnum.REGISTER_COMPLETED, OnRegisterCompleted);
    9.         socketManager.Socket.On(ResponseEventEnum.LOGIN_SUCCESSFUL, OnLoginSuccessful);
    10.         socketManager.Socket.On(ResponseEventEnum.ENTERED_TO_WORLD, OnEnteredToWorld);
    11.         socketManager.Socket.On(ResponseEventEnum.USER_CONNECTED, OnUserConnected);
    12.         socketManager.Socket.On(ResponseEventEnum.PLAYER_DISCONNECTED, OnPlayerDisconnecteda);
    13. }

    And event after button clicked:
    Code (CSharp):
    1. void MainMenuView_OnStartGameButtonClicked(MainMenuView mainMenuView) {
    2.         socketManager.Open();
    3.         mainMenuView.Hide();
    4.        
    5.     }

    I receive following errors when I click the StartButton.



    and


    Version of Unity: 2017.3.0f3
    Version of Best HTTP: 1.10.3


    and
     
  12. w4der

    w4der

    Joined:
    Sep 17, 2011
    Posts:
    17
    I don't know why but I can't add those two screens. So I wrote second post.

    Maybe it has some connection with the following settings?
    After first import I had another error message that tells
    So I changed the settings as follow (screenshots).
     

    Attached Files:

  13. BestHTTP

    BestHTTP

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

    You should try to restart Unity.

    No kidding, when Unity 2017.3 released it did the same to me, but restarting Unity solved it.

    Anyway, your import settings are good now.
     
  14. w4der

    w4der

    Joined:
    Sep 17, 2011
    Posts:
    17
    Hi,
    I still have those two errors (I wrote about them 2 posts ago, I think you didin't see it).
    Do you have any idea what is going wrong?
    Above you can find the code.

    and

     
  15. BestHTTP

    BestHTTP

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

    As I wrote this was the same to me too. For some unknown reason, Unity couldn't recognize the HTTPUpdateDelegator class as a derived class of MonoBehaviour. I can reproduce this easily by deleting my project's Library folder, then opening it in Unity 2017.3. But, closing Unity then opening the project again it works correctly...

    After deleting Library folder:
    upload_2017-12-21_22-43-35.png

    Just closed Unity and opened again the very same project:
    upload_2017-12-21_22-44-59.png
     
  16. w4der

    w4der

    Joined:
    Sep 17, 2011
    Posts:
    17
    Thank you for your reply! Problem solved <3

    I have second question.
    Is the communication between client -> server somehow encrypted / protected against other?

    If no... could you please tell any good solution that you recommend?

    i.e. I have
    Code (CSharp):
    1. // Send a custom event to the server with two parameters
    2. manager.Socket.Emit("LOGIN", "userName", "password");
     
  17. BestHTTP

    BestHTTP

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

    Communication isn't encrypted, but you can and should choose HTTPS to encrypt the whole communication.
     
  18. keomanla

    keomanla

    Joined:
    Jan 30, 2012
    Posts:
    26
    Hi @BestHTTP , I'm wondering how can I implement the bypass cloudflare anti ddos just like this package in nodejs https://www.npmjs.com/package/cloudscraper
    My full scenario is:
    1/ Open httprequest to server
    2/ Server then return a cloudflare anti ddos page
    3/ By pass this page just like what cloudscraper does
    4/ Then access to the main page and open websocket or signalR connection to the server.

    For now I get stuck at step 3, would be great if you can suggest any solution for this.
    Thanks.
     
    Last edited: Dec 28, 2017
  19. BestHTTP

    BestHTTP

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

    If you check out the source of cloudscraper, you can see that it intercepts the responses and if it contains a 'challange' it tries to solve it and will send back the answer. If it gave the right answers, it's able to initiate a request to the original address now.

    It can be done with the plugin, the real challenge is the challenge itself.
     
  20. melefans

    melefans

    Joined:
    Aug 1, 2016
    Posts:
    36
    @BestHTTP
    Hi, How to force close websocket on webgl platform?
    Other platforms I can call “Implementation.InternalRequest.Abort ()”:)
     
  21. BestHTTP

    BestHTTP

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

    Under WebGL you can use the regular websocket's Close() function only.
     
  22. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    @BestHTTP I'm having an issue getting a JSON array back as HTTPRequest only returns the first element of the array.

    When I plug the URL+args into the Unity WWW class it returns all elements of the array which is what I expected.

    Can you think why this might be at all?

    thanks

    Nalin
     
  23. BestHTTP

    BestHTTP

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

    It's usually when the server doesn't send a Content-Length header so the plugin can't know how much data it has to download. It will try as much as it can, but there's a high chance that it will not read all of them.
    You can use a proxy or you can set the plugin's log level to All so it will log out all received headers so you can search for a Content-Length header. If there's no such header (or a Transfer-Encoding), you might want to set up the server to send it.
     
  24. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    @BestHTTP

    "It's usually when the server doesn't send a Content-Length header so the plugin can't know how much data it has to download."

    So what does the Unity WWW class do then?

    It would be great if BestHTTP had an option that replicated the Unity WWW class functionality, otherwise it feels like bug.
     
  25. BestHTTP

    BestHTTP

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

    The HTTPRequest has an EnableSafeReadOnUnknownContentLength flag that you can set to false for a different read mechanism. The default one is a read bytes one by one, the other let's the underlying Socket implementation fill the provided buffer.
    Unfortunately I see no other ways to read back the response for an unknown length of data and both mechanism will fail here and there. This is why I usually suggest to fix the problem on server side, as that's the best solution in this case.
     
  26. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    hmmm - still don't know why the behaviour is different from the WWW class, as I would expect identical behaviour?
     
  27. BestHTTP

    BestHTTP

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

    Until Unity isn't releases the sources, we will not find out. I guess different receive buffer size can play a role here too.
    Also, even with Unity's implementation the behavior can be different on different platforms. My guess is that on standalone platforms they are using cURL, while on mobile they use the platform's own implementation.
     
  28. melefans

    melefans

    Joined:
    Aug 1, 2016
    Posts:
    36
    @BestHTTP
    Hello , I have one very strange issue.

    "HeartbeatManager.Update" may not be running, If i refresh the current game page, unless the browser cache is cleared, will never execute OnHeartbeatUpdate,websocket is working..
    "HeartbeatManager.LastUpdate " always output "01/01/0001 00:00:00"
    "HeartbeatManager.Heartbeats" Count = 3.
    WebGL Platform & All browser
    BestHttp version : 1.10.3
    i can send you a video..
     
    Last edited: Jan 7, 2018
  29. BestHTTP

    BestHTTP

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

    Is there a chance that you are using the Experimental runtime?
     
  30. melefans

    melefans

    Joined:
    Aug 1, 2016
    Posts:
    36
    Sorry, I just saw your reply, I have modified my description of the issue..
    If I refresh the browser, it will trigger this case。
     
  31. BestHTTP

    BestHTTP

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

    I would be happy if you can send any video and/or repro project!
     
  32. melefans

    melefans

    Joined:
    Aug 1, 2016
    Posts:
    36
    Hello, I have already sent two emails to besthttp@gmail.com,one email is the video, the other one is the test project。
    Yesterday I created an test project, unity editor and standalone platform can excute OnHeartbeatUpdate, but not excute in webgl, other platforms I have not tested..
    Please check email as soon as possible:)
     
    Last edited: Jan 7, 2018
  33. w4der

    w4der

    Joined:
    Sep 17, 2011
    Posts:
    17
    Hi,
    The problem came back ;(
    I tried following:
    - restart Unity as you said - thousand times
    - remove library folder
    - re-import plugin
    - install other version of Unity (current 2017.3.0 released on 19 dec 2017 and Patch version 2017.3.0p1 released on 22 dec 2017).

    any ideas?
     
  34. BestHTTP

    BestHTTP

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

    Sorry, but i'm out of any idea.
    Your best chance is to upload a repro project to Unity, so they can investigate it. It's still possible that something with the plugin itself, but at least they can let us know what's the problem, why it is failing.
     
  35. gschemmel

    gschemmel

    Joined:
    Mar 11, 2015
    Posts:
    4
    Are there any plans to support http/2?
     
  36. BestHTTP

    BestHTTP

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

    I have plans for http/2, but it's a little low on my todo list currently.
     
  37. LPro

    LPro

    Joined:
    Mar 13, 2017
    Posts:
    1
    Edit: Please ignore this. For Unity 5.4.5f1I had to use the Windows SDK Version 10.0.14393
    Now the compile errors disappeared.

    Hey, when I build for Windows 10 Universal Platform I get a bunch of compile errors with Unity 5.4.5f1 and BestHTTP version 1.10.2.
    I have set Use Net Core for Compilation Overrides

    Is there a specific Windows 10 SDK version I have to use or some special Visual Studio version?

    Thank you in advance for your time


    Here are some of the Error messages:

    Assets\Best HTTP (Pro)\BestHTTP\PlatformSupport\IO\Directory.cs(16,24): error CS0246: The type or namespace name 'StorageFolder' could not be found (are you missing a using directive or an assembly reference?)

    Assets\Best HTTP (Pro)\BestHTTP\PlatformSupport\IO\File.cs(181,85): error CS0731: The type forwarder for type 'Windows.Storage.FileAttributes' in assembly 'Windows' causes a cycle

    Assets\Best HTTP (Pro)\BestHTTP\PlatformSupport\IO\File.cs(181,85): error CS1069: The type name 'FileAttributes' could not be found in the namespace 'Windows.Storage'. This type has been forwarded to assembly 'Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime' Consider adding a reference to that assembly.

    Assets\Best HTTP (Pro)\BestHTTP\PlatformSupport\IO\File.cs(414,24): error CS0246: The type or namespace name 'StorageFile' could not be found (are you missing a using directive or an assembly reference?)

    Assets\Best HTTP (Pro)\BestHTTP\PlatformSupport\IO\FileHelper.cs(115,51): error CS0246: The type or namespace name 'StorageFile' could not be found (are you missing a using directive or an assembly reference?)

    Assets\Best HTTP (Pro)\BestHTTP\PlatformSupport\IO\FileHelper.cs(51,25): error CS0246: The type or namespace name 'StorageFolder' could not be found (are you missing a using directive or an assembly reference?)

    Assets\Best HTTP (Pro)\BestHTTP\PlatformSupport\IO\FileHelper.cs(99,25): error CS0246: The type or namespace name 'StorageFolder' could not be found (are you missing a using directive or an assembly reference?)

    Assets\Best HTTP (Pro)\BestHTTP\PlatformSupport\IO\FileHelper.cs(108,25): error CS0246: The type or namespace name 'StorageFile' could not be found (are you missing a using directive or an assembly reference?)

    Assets\Best HTTP (Pro)\BestHTTP\PlatformSupport\IO\FileHelper.cs(125,47): error CS0246: The type or namespace name 'StorageFile' could not be found (are you missing a using directive or an assembly reference?)

    Assets\Best HTTP (Pro)\BestHTTP\PlatformSupport\IO\FileStream.cs(146,24): error CS0246: The type or namespace name 'StorageFile' could not be found (are you missing a using directive or an assembly reference?)

    Assets\Best HTTP (Pro)\BestHTTP\PlatformSupport\IO\FileStream.cs(151,24): error CS0246: The type or namespace name 'StorageFile' could not be found (are you missing a using directive or an assembly reference?)

    Assets\Best HTTP (Pro)\BestHTTP\PlatformSupport\IO\FileStream.cs(304,24): error CS0246: The type or namespace name 'CreationCollisionOption' could not be found (are you missing a using directive or an assembly reference?)

    Assets\Best HTTP (Pro)\BestHTTP\PlatformSupport\IO\FileStream.cs(325,24): error CS0246: The type or namespace name 'FileAccessMode' could not be found (are you missing a using directive or an assembly reference?)

    Assets\Best HTTP (Pro)\BestHTTP\PlatformSupport\IO\FileStream.cs(21,17): error CS0246: The type or namespace name 'FileRandomAccessStream' could not be found (are you missing a using directive or an assembly reference?)

    And some more like this, can post all if required.
     
    Last edited: Jan 15, 2018
  38. scauclair

    scauclair

    Joined:
    Oct 1, 2015
    Posts:
    2
    Hi!

    I've got a problem with the OnInternalRequestUpgraded method after trying to create a web socket by upgrading an http request. The server accept the upgrade command and return a code 101, but the response won't cast in a WebSocketResponse and the code will handle this as an error. I can create a new WebSocketResponse from the HTTPResponse by using the constructor, but I have the feeling the cast should work. Any idea on what is going on?

    Code (CSharp):
    1. private void OnInternalRequestUpgraded(HTTPRequest req, HTTPResponse resp)
    2.         {
    3.             webSocket = resp as WebSocketResponse;
    4.             if (webSocket == null)
    5.             {
    6.                 if (OnError != null)
    7.                     OnError(this, req.Exception);
    8.                 if (OnErrorDesc != null)
    9.                 {
    10.                     string reason = string.Empty;
    11.                     if (req.Exception != null)
    12.                         reason = req.Exception.Message + " " + req.Exception.StackTrace;
    13.                     OnErrorDesc(this, reason);
    14.                 }
    15.                 return;
    16.             }
     
  39. BestHTTP

    BestHTTP

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

    I guess the url you want to connect starts with http:// or https://, in these cases the resp object isn't a WebSocketResponse and will fail. If you change it to ws:// or wss:// it shouldn't fail.

    In the upcoming update this behavior will be improved and if you want i can send an updated package.
     
  40. scauclair

    scauclair

    Joined:
    Oct 1, 2015
    Posts:
    2
    @BestHTTP

    Urg, yup this is it. Thanks for the help!
     
  41. Packedbox

    Packedbox

    Joined:
    Jun 20, 2013
    Posts:
    20
    Hi I'm trying to use BestHttp to Upload file to an Amazon S3 bucket, so far no luck I always receive this error response from S3:

    <Error><Code>InvalidRequest</Code><Message>The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.</Message><RequestId>D98BFF79DAE42A</RequestId><HostId>GBjFttgkEfsRUog4o0Iwf6HROwox0pkMtJseKylWMVUrB7h9t3atDvFM7Wy4D2/B9ItK8=</HostId></Error>

    I cannot use the AWS SDK because it's not working with WebGL ( I had good results using TransferUtility in the Editor )

    I use the following code to execute the request :

    Code (CSharp):
    1.  
    2.  
    3. using System;
    4. using System.IO;
    5. using UnityEngine;
    6. using System.Collections;
    7. using System.Collections.Generic;
    8. using UnityEngine.Networking;
    9. using System.Text;
    10. using System.Security.Cryptography;
    11.  
    12.  
    13. using BestHTTP;
    14.  
    15. class S3Upload : Monobehaviour
    16. {
    17.  
    18.     const string sBucketName = "myBucket";
    19.  
    20.     const string sS3PostUrl = "http://s3.eu-west-2.amazonaws.com/" + sBucketName;
    21.  
    22.     const string sAppAccessKeyID = "XXXXXXXXXXXX";
    23.  
    24.     const string sAppSecretAccessKey = "YYYYYYYYYYY";
    25.  
    26.     public void UploadData(byte[] data, string fileName)
    27.     {
    28.  
    29.         HTTPRequest request = new HTTPRequest(new Uri(sS3PostUrl), HTTPMethods.Post, (req, resp) =>
    30.          {
    31.              switch (req.State)
    32.              {
    33.                  // The request finished without any problem.
    34.                  case HTTPRequestStates.Finished:
    35.                      Debug.Log("Request Finished Successfully!\n" + resp.DataAsText);
    36.                      break;
    37.                  // The request finished with an unexpected error.
    38.                  // The request's Exception property may contain more information about the error.
    39.                  case HTTPRequestStates.Error:
    40.                      Debug.LogError("Request Finished with Error! " +
    41.                                  (req.Exception != null ?
    42.                                          (req.Exception.Message + "\n" +
    43.                                  req.Exception.StackTrace) :
    44.                                          "No Exception"));
    45.                      break;
    46.                  // The request aborted, initiated by the user.
    47.                  case HTTPRequestStates.Aborted:
    48.                      Debug.LogWarning("Request Aborted!");
    49.                      break;
    50.                  // Ceonnecting to the server timed out.
    51.                  case HTTPRequestStates.ConnectionTimedOut:
    52.                      Debug.LogError("Connection Timed Out!");
    53.                      break;
    54.                  // The request didn't finished in the given time.
    55.                  case HTTPRequestStates.TimedOut:
    56.                      Debug.LogError("Processing the request Timed Out!");
    57.                      break;
    58.              }
    59.          });
    60.  
    61.         var fb = new AWSRequestBuilder();
    62.         fb.BuildUploadRequest(request, sAppAccessKeyID, sAppSecretAccessKey, sBucketName, fileName, data);
    63.         request.Send();
    64.  
    65.     }
    66.  
    67. }
    68.  
    69. public class AWSRequestBuilder
    70. {
    71.  
    72.     const double requestValidForSeconds = 60.0f;
    73.  
    74.     public void BuildUploadRequest(HTTPRequest req, string appAccessKeyID, string appSecretAccessKey, string bucket, string fileName, byte[] data)
    75.     {
    76.         // as described here : https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-authentication-HTTPPOST.html      
    77.  
    78.         DateTime currentTime = DateTime.UtcNow;
    79.         DateTime requestExpiryTime = currentTime.AddSeconds(requestValidForSeconds);
    80.  
    81.         string iso8601ExpiryTime = requestExpiryTime.ToString("s", System.Globalization.CultureInfo.InvariantCulture);
    82.         string iso8601CurrentTime = currentTime.ToString("s", System.Globalization.CultureInfo.InvariantCulture);
    83.  
    84.         string policy = "{ \"expiration\": \"" + iso8601ExpiryTime + "\"," +
    85.                             " \"conditions\": [" +
    86.                             " {\"X-Amz-date\": \"" + iso8601CurrentTime + "\" }" +
    87.                             " {\"bucket\": \"" + bucket + "\" }," +
    88.                             " [\"starts-with\", \"$key\", \"uploads/\"]," +
    89.                             " [\"starts-with\", \"$Content-Type\", \"\"]," +
    90.                             " [\"content-length-range\", 1, 1024000], " +
    91.                             " {\"X-Amz-credential\": \"" + currentTime.ToString("yyyyMMdd") + "/" + iso8601CurrentTime + "/eu-west-2/s3/aws4_request\"}," +
    92.                             " {\"X-Amz-algorithm\": \"AWS4-HMAC-SHA256\"}," +
    93.                             " {\"acl\": \"public-read\" }, " +
    94.                             "]}";
    95.  
    96.  
    97.         policy = Convert.ToBase64String(Encoding.UTF8.GetBytes(policy));
    98.  
    99.         byte[] sk = GetSigningKey(currentTime, appSecretAccessKey);
    100.  
    101.         byte[] hma = HmacSHA256(sk, policy);
    102.  
    103.         string signature = Convert.ToBase64String(hma);
    104.  
    105.         req.AddField("X-Amz-algorithm", "AWS4-HMAC-SHA256");
    106.         req.AddField("X-Amz-credential", appAccessKeyID + "/" + currentTime.ToString("yyyyMMdd") + "/eu-west-2/s3/aws4_request");
    107.         req.AddField("X-Amz-date", iso8601CurrentTime);
    108.         req.AddField("X-Amz-server-side-encryption", "AES256");
    109.         req.AddField("X-Amz-Expires", "86400");
    110.         req.AddField("policy", policy);
    111.         req.AddField("signature", signature);
    112.         req.AddField("AWSAccessKeyId", appAccessKeyID);
    113.         req.AddField("key", "Test.png");
    114.         req.AddField("acl", "public-read");
    115.         req.AddField("Content-Type", "image/png");
    116.         req.AddBinaryData("file", data, fileName, "image/png");
    117.  
    118.         req.MethodType = HTTPMethods.Post;
    119.  
    120.  
    121.     }
    122.  
    123.     private byte[] GetSigningKey(DateTime requestDate, string appSecretAccessKey)
    124.     {
    125.         // as described here : https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
    126.  
    127.         byte[] kSecret = Encoding.UTF8.GetBytes(("AWS4" + appSecretAccessKey).ToCharArray());
    128.         byte[] kDate = HmacSHA256(kSecret, requestDate.ToString("yyyyMMdd"));
    129.         byte[] kRegion = HmacSHA256(kDate, "eu-west-2");
    130.         byte[] kService = HmacSHA256(kRegion, "s3");
    131.         byte[] kSigning = HmacSHA256(kService, "aws4_request");
    132.         return kSigning;
    133.     }
    134.  
    135.     static byte[] HmacSHA256(byte[] key, String data)
    136.     {
    137.         String algorithm = "HmacSHA256";
    138.         KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create(algorithm);
    139.         kha.Key = key;
    140.         return kha.ComputeHash(Encoding.UTF8.GetBytes(data));
    141.     }
    142.  
    143. }
    144.  
    145. }
    Any Ideas what could be wrong with my code ?
     
    Last edited: Jan 16, 2018
  42. BestHTTP

    BestHTTP

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

    It looks good to me, but it's enough to make a little mistake to fail the request.
    Is it works in the editor? Or is it fails only under WebGL?
     
  43. Packedbox

    Packedbox

    Joined:
    Jun 20, 2013
    Posts:
    20
    Hi it fails also in the editor not even tried in WebGL yet.
     
  44. BestHTTP

    BestHTTP

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

    There's an example page where they have a sample input and signing output. You should try to sign the sample input with your functions to see whether you are receiving the very same output as they have on that page.

    There's also an Examples of Signature Calculations Using C# (AWS Signature Version 4) secion where they even provide a downloadable zip file where there are complete classes for signing.

    I would also try out the header based authorization too.
     
  45. TFG

    TFG

    Joined:
    Jan 17, 2017
    Posts:
    3
    Hi, when I switching network from 3g to wifi (not disabling 3g, just turning on wifi) socket is closing. Is it possible to somehow prevent its closure?
     
  46. BestHTTP

    BestHTTP

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

    Unfortunately, this is done by the underlying system, and the plugin has no control over it.
     
  47. carsanlop

    carsanlop

    Joined:
    Dec 12, 2017
    Posts:
    11
    Hello, first of all thanks for your plugin. I could not get a SignalR connection to work on mobile, and your plugin made it easy and "just working".

    However, I have been experiencing a problem. I had a working system to make HTTP requests using .NET 4.6 Experimental and WebRequests. Those requests used HTTPS, and went against an Amazon Beanstalk application running IIS with a self-signed certificate. After some fiddling with certificate validation, I made it work. The application also worked when queries from tools like Postman.

    Recently, for various reasons, I decided to do a downgrade to .NET 3.5, in order to avoid issues with other areas of my game. And, given that i was already using BestHTTP, I switched the HTTP requests to the plugin. But, then, the requests against my self-signed server stopped working. They work at HTTPS in my local machine, they work against the server without HTTPS, and they work against test URLs like https://google.com, they just don't work against my custom server.

    Getting technical, my code for performing a simple GET request is as follows:

    Code (CSharp):
    1.  
    2.             // Create the request and set the headers.
    3.             var request = new HTTPRequest(new Uri(uri + queryParams), HTTPMethods.Get);
    4.             request.Callback = OnRequestFinished;
    5.  
    6.             // Configure the certificate validation.
    7.             request.UseAlternateSSL = true;
    8.             request.CustomCertificateVerifyer = new CustomVerifier();
    9.  
    10.             // Send the request.
    11.             request.Send();
    The custom verifier is taken straight from documentation, with a method that always returns true.

    Code (CSharp):
    1.     class CustomVerifier : ICertificateVerifyer
    2.     {
    3.         public bool IsValid(Uri serverUri, X509CertificateStructure[] certs)
    4.         {
    5.             UnityEngine.Debug.Log("IsValid called");
    6.             return true;
    7.         }
    8.     }
    When I perform a test request to, for example, https://google.es, the request works as intended. The debug line "IsValid called" shows up in the console.

    But when I perform a request to my own server, everything goes awry. The callback method gets invoked with a null response object. The debug line in the IsValid method never shows (seems like the validation method is never called). And the request object passed to the callback contains the following error:

    Code (CSharp):
    1. "System.IO.IOException: Internal TLS error, this could be an attack
    2. at Org.BouncyCastle.Crypto.Tls.TlsProtocol.FailWithError (Byte alertLevel, Byte alertDescription, System.String message, System.Exception cause) [0x00000] in <filename unknown>:0
    3. at Org.BouncyCastle.Crypto.Tls.TlsProtocol.SafeReadRecord () [0x00000] in <filename unknown>:0
    4. at Org.BouncyCastle.Crypto.Tls.TlsProtocol.BlockForHandshake () [0x00000] in <filename unknown>:0
    5. at Org.BouncyCastle.Crypto.Tls.TlsClientProtocol.Connect (TlsClient tlsClient) [0x00000] in <filename unknown>:0
    6. at BestHTTP.HTTPConnection.Connect () [0x00000] in <filename unknown>:0
    7. at BestHTTP.HTTPConnection.ThreadFunc (System.Object param) [0x00000] in <filename unknown>:0 "


    The fields UserAlternateSSL and CustomVerifier are correctly set, as is the URL. Any help would be appreciated. Thanks in advance.
     
  48. BestHTTP

    BestHTTP

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

    Could you send me a non-working url to my email address (besthttp@gmail.com). It can be an error page, or something else, just to be able to reproduce this error.
     
  49. exoter

    exoter

    Joined:
    Apr 25, 2015
    Posts:
    10
    I have the same issue but with SocketIO.
    I am using Unity 2017.3 and the latest BestHTTP version.
    When I stop the editor the code continues trying to reconnect.

    Also If I stop my game while connected, the Unity editor crashes which is really frustrating.
    (The only change we have is switching from standart socket client to BestHTTP so its not crashing from our code)]

    Edit: The crashing happens if the callback attached to socket "error" event throws exception -> I guess it enters cycle. Anyway the first issue still exists
     
    Last edited: Jan 23, 2018
  50. BestHTTP

    BestHTTP

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

    Couldn't reproduce it yet. Can you confirm that you are using the v1.10.3 version of the plugin? You can find the version number in the \Assets\Best HTTP (Pro)\ReleaseNotes.txt.