소스 검색

Merge pull request #4462 from TechnoPorg/master

Add C# code examples for HTTPClient and HTTPRequest
Rémi Verschelde 4 년 전
부모
커밋
2d710ef15e
2개의 변경된 파일185개의 추가작업 그리고 30개의 파일을 삭제
  1. 118 7
      tutorials/networking/http_client_class.rst
  2. 67 23
      tutorials/networking/http_request_class.rst

+ 118 - 7
tutorials/networking/http_client_class.rst

@@ -10,13 +10,21 @@ which has a tutorial available :ref:`here <doc_http_request_class>`.
 Here's an example of using the :ref:`HTTPClient <class_HTTPClient>`
 Here's an example of using the :ref:`HTTPClient <class_HTTPClient>`
 class. It's just a script, so it can be run by executing:
 class. It's just a script, so it can be run by executing:
 
 
-.. code-block:: console
+.. tabs::
+
+ .. code-tab:: console GDScript
 
 
     c:\godot> godot -s http_test.gd
     c:\godot> godot -s http_test.gd
 
 
+ .. code-tab:: console C#
+
+    c:\godot> godot -s HTTPTest.cs
+
 It will connect and fetch a website.
 It will connect and fetch a website.
 
 
-::
+.. tabs::
+
+ .. code-tab:: gdscript GDScript
 
 
     extends SceneTree
     extends SceneTree
 
 
@@ -28,7 +36,7 @@ It will connect and fetch a website.
         var http = HTTPClient.new() # Create the Client.
         var http = HTTPClient.new() # Create the Client.
 
 
         err = http.connect_to_host("www.php.net", 80) # Connect to host/port.
         err = http.connect_to_host("www.php.net", 80) # Connect to host/port.
-        assert(err == OK) # Make sure connection was OK.
+        assert(err == OK) # Make sure connection is OK.
 
 
         # Wait until resolved and connected.
         # Wait until resolved and connected.
         while http.get_status() == HTTPClient.STATUS_CONNECTING or http.get_status() == HTTPClient.STATUS_RESOLVING:
         while http.get_status() == HTTPClient.STATUS_CONNECTING or http.get_status() == HTTPClient.STATUS_RESOLVING:
@@ -39,7 +47,7 @@ It will connect and fetch a website.
             else:
             else:
                 yield(Engine.get_main_loop(), "idle_frame")
                 yield(Engine.get_main_loop(), "idle_frame")
 
 
-        assert(http.get_status() == HTTPClient.STATUS_CONNECTED) # Could not connect
+        assert(http.get_status() == HTTPClient.STATUS_CONNECTED) # Check if the connection was made successfully.
 
 
         # Some headers
         # Some headers
         var headers = [
         var headers = [
@@ -54,12 +62,12 @@ It will connect and fetch a website.
             # Keep polling for as long as the request is being processed.
             # Keep polling for as long as the request is being processed.
             http.poll()
             http.poll()
             print("Requesting...")
             print("Requesting...")
-            if not OS.has_feature("web"):
-                OS.delay_msec(500)
-            else:
+            if OS.has_feature("web"):
                 # Synchronous HTTP requests are not supported on the web,
                 # Synchronous HTTP requests are not supported on the web,
                 # so wait for the next main loop iteration.
                 # so wait for the next main loop iteration.
                 yield(Engine.get_main_loop(), "idle_frame")
                 yield(Engine.get_main_loop(), "idle_frame")
+            else:
+                OS.delay_msec(500)
 
 
         assert(http.get_status() == HTTPClient.STATUS_BODY or http.get_status() == HTTPClient.STATUS_CONNECTED) # Make sure request finished well.
         assert(http.get_status() == HTTPClient.STATUS_BODY or http.get_status() == HTTPClient.STATUS_CONNECTED) # Make sure request finished well.
 
 
@@ -106,3 +114,106 @@ It will connect and fetch a website.
             print("Text: ", text)
             print("Text: ", text)
 
 
         quit()
         quit()
+
+ .. code-tab:: csharp
+
+    class HTTPTest : SceneTree
+    {
+        // HTTPClient demo.
+        // This simple class can make HTTP requests; it will not block, but it needs to be polled.
+        public override async void _Initialize()
+        {
+            Error err;
+            HTTPClient http = new HTTPClient(); // Create the client.
+
+            err = http.ConnectToHost("www.php.net", 80); // Connect to host/port.
+            Debug.Assert(err == Error.Ok); // Make sure the connection is OK.
+
+            // Wait until resolved and connected.
+            while (http.GetStatus() == HTTPClient.Status.Connecting || http.GetStatus() == HTTPClient.Status.Resolving)
+            {
+                http.Poll();
+                GD.Print("Connecting...");
+                OS.DelayMsec(500);
+            }
+
+            Debug.Assert(http.GetStatus() == HTTPClient.Status.Connected); // Check if the connection was made successfully.
+
+            // Some headers.
+            string[] headers = { "User-Agent: Pirulo/1.0 (Godot)", "Accept: */*" };
+
+            err = http.Request(HTTPClient.Method.Get, "/ChangeLog-5.php", headers); // Request a page from the site.
+            Debug.Assert(err == Error.Ok); // Make sure all is OK.
+
+            // Keep polling for as long as the request is being processed.
+            while (http.GetStatus() == HTTPClient.Status.Requesting)
+            {
+                http.Poll();
+                GD.Print("Requesting...");
+                if (OS.HasFeature("web"))
+                {
+                    // Synchronous HTTP requests are not supported on the web,
+                    // so wait for the next main loop iteration.
+                    await ToSignal(Engine.GetMainLoop(), "idle_frame");
+                }
+                else
+                {
+                    OS.DelayMsec(500);
+                }
+            }
+
+            Debug.Assert(http.GetStatus() == HTTPClient.Status.Body || http.GetStatus() == HTTPClient.Status.Connected); // Make sure the request finished well.
+
+            GD.Print("Response? ", http.HasResponse()); // The site might not have a response.
+
+            // If there is a response...
+            if (http.HasResponse())
+            {
+                headers = http.GetResponseHeaders(); // Get response headers.
+                GD.Print("Code: ", http.GetResponseCode()); // Show response code.
+                GD.Print("Headers:");
+                foreach (string header in headers)
+                {
+                    // Show headers.
+                    GD.Print(header);
+                }
+
+                if (http.IsResponseChunked())
+                {
+                    // Does it use chunks?
+                    GD.Print("Response is Chunked!");
+                }
+                else
+                {
+                    // Or just Content-Length.
+                    GD.Print("Response Length: ", http.GetResponseBodyLength());
+                }
+
+                // This method works for both anyways.
+                List<byte> rb = new List<byte>(); // List that will hold the data.
+
+                // While there is data left to be read...
+                while (http.GetStatus() == HTTPClient.Status.Body)
+                {
+                    http.Poll();
+                    byte[] chunk = http.ReadResponseBodyChunk(); // Read a chunk.
+                    if (chunk.Length == 0)
+                    {
+                        // If nothing was read, wait for the buffer to fill.
+                        OS.DelayMsec(500);
+                    }
+                    else
+                    {
+                        // Append the chunk to the read buffer.
+                        rb.AddRange(chunk);
+                    }
+                }
+
+                // Done!
+                GD.Print("Bytes Downloaded: ", rb.Count);
+                string text = Encoding.ASCII.GetString(rb.ToArray());
+                GD.Print(text);
+            }
+            Quit();
+        }
+    }

+ 67 - 23
tutorials/networking/http_request_class.rst

@@ -23,19 +23,44 @@ Scripting
 
 
 Below is all the code we need to make it work. The URL points to an online API mocker; it returns a pre-defined JSON string, which we will then parse to get access to the data.
 Below is all the code we need to make it work. The URL points to an online API mocker; it returns a pre-defined JSON string, which we will then parse to get access to the data.
 
 
-::
-
-    extends CanvasLayer
-
-    func _ready():
-        $HTTPRequest.connect("request_completed", self, "_on_request_completed")
-
-    func _on_Button_pressed():
-        $HTTPRequest.request("http://www.mocky.io/v2/5185415ba171ea3a00704eed")
-
-    func _on_request_completed(result, response_code, headers, body):
-        var json = JSON.parse(body.get_string_from_utf8())
-        print(json.result)
+.. tabs::
+
+    .. code-tab:: gdscript GDScript
+    
+        extends CanvasLayer
+
+        func _ready():
+            $HTTPRequest.connect("request_completed", self, "_on_request_completed")
+
+        func _on_Button_pressed():
+            $HTTPRequest.request("http://www.mocky.io/v2/5185415ba171ea3a00704eed")
+
+        func _on_request_completed(result, response_code, headers, body):
+            var json = JSON.parse(body.get_string_from_utf8())
+            print(json.result)
+    
+    .. code-tab:: csharp
+    
+        class HTTPRequestDemo : CanvasLayer
+        {
+            public override void _Ready()
+            {
+                GetNode("HTTPRequest").Connect("request_completed", this, "OnRequestCompleted");
+                GetNode("Button").Connect("pressed", this, "OnButtonPressed");
+            }
+            
+            public void OnButtonPressed()
+            {
+                HTTPRequest httpRequest = GetNode<HTTPRequest>("HTTPRequest");
+                httpRequest.Request("http://www.mocky.io/v2/5185415ba171ea3a00704eed");
+            }
+            
+            public void OnRequestCompleted(int result, int response_code, string[] headers, byte[] body)
+            {
+                JSONParseResult json = JSON.Parse(Encoding.UTF8.GetString(body));
+                GD.Print(json.Result);
+            }
+        }
 
 
 With this, you should see ``(hello:world)`` printed on the console; hello being a key, and world being a value, both of them strings.
 With this, you should see ``(hello:world)`` printed on the console; hello being a key, and world being a value, both of them strings.
 
 
@@ -46,9 +71,16 @@ Note that you may want to check whether the ``result`` equals ``RESULT_SUCCESS``
 Of course, you can also set custom HTTP headers. These are given as a string array, with each string containing a header in the format ``"header: value"``.
 Of course, you can also set custom HTTP headers. These are given as a string array, with each string containing a header in the format ``"header: value"``.
 For example, to set a custom user agent (the HTTP ``user-agent`` header) you could use the following:
 For example, to set a custom user agent (the HTTP ``user-agent`` header) you could use the following:
 
 
-::
+..  tabs::
 
 
-    $HTTPRequest.request("http://www.mocky.io/v2/5185415ba171ea3a00704eed", ["user-agent: YourCustomUserAgent"])
+    .. code-tab:: gdscript GDScript
+    
+        $HTTPRequest.request("http://www.mocky.io/v2/5185415ba171ea3a00704eed", ["user-agent: YourCustomUserAgent"])
+    
+    .. code-tab:: csharp
+    
+        HTTPRequest httpRequest = GetNode<HTTPRequest>("HTTPRequest");
+        httpRequest.Request("http://www.mocky.io/v2/5185415ba171ea3a00704eed", new string[] { "user-agent: YourCustomUserAgent" });
 
 
 Please note that, for SSL/TLS encryption and thus HTTPS URLs to work, you may need to take some steps as described :ref:`here <doc_ssl_certificates>`.
 Please note that, for SSL/TLS encryption and thus HTTPS URLs to work, you may need to take some steps as described :ref:`here <doc_ssl_certificates>`.
 
 
@@ -60,14 +92,26 @@ Sending data to server
 
 
 Until now, we have limited ourselves to requesting data from a server. But what if you need to send data to the server? Here is a common way of doing it:
 Until now, we have limited ourselves to requesting data from a server. But what if you need to send data to the server? Here is a common way of doing it:
 
 
-::
-
-    func _make_post_request(url, data_to_send, use_ssl):
-        # Convert data to json string:
-        var query = JSON.print(data_to_send)
-        # Add 'Content-Type' header:
-        var headers = ["Content-Type: application/json"]
-        $HTTPRequest.request(url, headers, use_ssl, HTTPClient.METHOD_POST, query)
+.. tabs::
+
+    .. code-tab:: gdscript GDScript
+    
+        func _make_post_request(url, data_to_send, use_ssl):
+            # Convert data to json string:
+            var query = JSON.print(data_to_send)
+            # Add 'Content-Type' header:
+            var headers = ["Content-Type: application/json"]
+            $HTTPRequest.request(url, headers, use_ssl, HTTPClient.METHOD_POST, query)
+    
+    .. code-tab:: csharp
+    
+            public void MakePostRequest(string url, object data_to_send, bool use_ssl)
+            {
+                string query = JSON.Print(data_to_send);
+                HTTPRequest httpRequest = GetNode<HTTPRequest>("HTTPRequest");
+                string[] headers = new string[] { "Content-Type: application/json" };
+                httpRequest.Request(url, headers, use_ssl, HTTPClient.Method.Post, query);
+            }
 
 
 Keep in mind that you have to wait for a request to finish before sending another one. Making multiple request at once requires you to have one node per request.
 Keep in mind that you have to wait for a request to finish before sending another one. Making multiple request at once requires you to have one node per request.
 A common strategy is to create and delete HTTPRequest nodes at runtime as necessary.
 A common strategy is to create and delete HTTPRequest nodes at runtime as necessary.