http_client_class.rst 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. :article_outdated: True
  2. .. _doc_http_client_class:
  3. HTTP client class
  4. =================
  5. :ref:`HTTPClient <class_HTTPClient>` provides low-level access to HTTP communication.
  6. For a higher-level interface, you may want to take a look at :ref:`HTTPRequest <class_HTTPRequest>` first,
  7. which has a tutorial available :ref:`here <doc_http_request_class>`.
  8. .. warning::
  9. When exporting to Android, make sure to enable the ``INTERNET``
  10. permission in the Android export preset before exporting the project or
  11. using one-click deploy. Otherwise, network communication of any kind will be
  12. blocked by Android.
  13. Here's an example of using the :ref:`HTTPClient <class_HTTPClient>`
  14. class. It's just a script, so it can be run by executing:
  15. .. tabs::
  16. .. code-tab:: console GDScript
  17. c:\godot> godot -s http_test.gd
  18. .. code-tab:: console C#
  19. c:\godot> godot -s HTTPTest.cs
  20. It will connect and fetch a website.
  21. .. tabs::
  22. .. code-tab:: gdscript GDScript
  23. extends SceneTree
  24. # HTTPClient demo
  25. # This simple class can do HTTP requests; it will not block, but it needs to be polled.
  26. func _init():
  27. var err = 0
  28. var http = HTTPClient.new() # Create the Client.
  29. err = http.connect_to_host("www.php.net", 80) # Connect to host/port.
  30. assert(err == OK) # Make sure connection is OK.
  31. # Wait until resolved and connected.
  32. while http.get_status() == HTTPClient.STATUS_CONNECTING or http.get_status() == HTTPClient.STATUS_RESOLVING:
  33. http.poll()
  34. print("Connecting...")
  35. if not OS.has_feature("web"):
  36. OS.delay_msec(500)
  37. else:
  38. yield(Engine.get_main_loop(), "idle_frame")
  39. assert(http.get_status() == HTTPClient.STATUS_CONNECTED) # Check if the connection was made successfully.
  40. # Some headers
  41. var headers = [
  42. "User-Agent: Pirulo/1.0 (Godot)",
  43. "Accept: */*"
  44. ]
  45. err = http.request(HTTPClient.METHOD_GET, "/ChangeLog-5.php", headers) # Request a page from the site (this one was chunked..)
  46. assert(err == OK) # Make sure all is OK.
  47. while http.get_status() == HTTPClient.STATUS_REQUESTING:
  48. # Keep polling for as long as the request is being processed.
  49. http.poll()
  50. print("Requesting...")
  51. if OS.has_feature("web"):
  52. # Synchronous HTTP requests are not supported on the web,
  53. # so wait for the next main loop iteration.
  54. yield(Engine.get_main_loop(), "idle_frame")
  55. else:
  56. OS.delay_msec(500)
  57. assert(http.get_status() == HTTPClient.STATUS_BODY or http.get_status() == HTTPClient.STATUS_CONNECTED) # Make sure request finished well.
  58. print("response? ", http.has_response()) # Site might not have a response.
  59. if http.has_response():
  60. # If there is a response...
  61. headers = http.get_response_headers_as_dictionary() # Get response headers.
  62. print("code: ", http.get_response_code()) # Show response code.
  63. print("**headers:\\n", headers) # Show headers.
  64. # Getting the HTTP Body
  65. if http.is_response_chunked():
  66. # Does it use chunks?
  67. print("Response is Chunked!")
  68. else:
  69. # Or just plain Content-Length
  70. var bl = http.get_response_body_length()
  71. print("Response Length: ", bl)
  72. # This method works for both anyway
  73. var rb = PackedByteArray() # Array that will hold the data.
  74. while http.get_status() == HTTPClient.STATUS_BODY:
  75. # While there is body left to be read
  76. http.poll()
  77. # Get a chunk.
  78. var chunk = http.read_response_body_chunk()
  79. if chunk.size() == 0:
  80. if not OS.has_feature("web"):
  81. # Got nothing, wait for buffers to fill a bit.
  82. OS.delay_usec(1000)
  83. else:
  84. yield(Engine.get_main_loop(), "idle_frame")
  85. else:
  86. rb = rb + chunk # Append to read buffer.
  87. # Done!
  88. print("bytes got: ", rb.size())
  89. var text = rb.get_string_from_ascii()
  90. print("Text: ", text)
  91. quit()
  92. .. code-tab:: csharp
  93. using Godot;
  94. public partial class HTTPTest : SceneTree
  95. {
  96. // HTTPClient demo.
  97. // This simple class can make HTTP requests; it will not block, but it needs to be polled.
  98. public override async void _Initialize()
  99. {
  100. Error err;
  101. HTTPClient http = new HTTPClient(); // Create the client.
  102. err = http.ConnectToHost("www.php.net", 80); // Connect to host/port.
  103. Debug.Assert(err == Error.Ok); // Make sure the connection is OK.
  104. // Wait until resolved and connected.
  105. while (http.GetStatus() == HTTPClient.Status.Connecting || http.GetStatus() == HTTPClient.Status.Resolving)
  106. {
  107. http.Poll();
  108. GD.Print("Connecting...");
  109. OS.DelayMsec(500);
  110. }
  111. Debug.Assert(http.GetStatus() == HTTPClient.Status.Connected); // Check if the connection was made successfully.
  112. // Some headers.
  113. string[] headers = { "User-Agent: Pirulo/1.0 (Godot)", "Accept: */*" };
  114. err = http.Request(HTTPClient.Method.Get, "/ChangeLog-5.php", headers); // Request a page from the site.
  115. Debug.Assert(err == Error.Ok); // Make sure all is OK.
  116. // Keep polling for as long as the request is being processed.
  117. while (http.GetStatus() == HTTPClient.Status.Requesting)
  118. {
  119. http.Poll();
  120. GD.Print("Requesting...");
  121. if (OS.HasFeature("web"))
  122. {
  123. // Synchronous HTTP requests are not supported on the web,
  124. // so wait for the next main loop iteration.
  125. await ToSignal(Engine.GetMainLoop(), "idle_frame");
  126. }
  127. else
  128. {
  129. OS.DelayMsec(500);
  130. }
  131. }
  132. Debug.Assert(http.GetStatus() == HTTPClient.Status.Body || http.GetStatus() == HTTPClient.Status.Connected); // Make sure the request finished well.
  133. GD.Print("Response? ", http.HasResponse()); // The site might not have a response.
  134. // If there is a response...
  135. if (http.HasResponse())
  136. {
  137. headers = http.GetResponseHeaders(); // Get response headers.
  138. GD.Print("Code: ", http.GetResponseCode()); // Show response code.
  139. GD.Print("Headers:");
  140. foreach (string header in headers)
  141. {
  142. // Show headers.
  143. GD.Print(header);
  144. }
  145. if (http.IsResponseChunked())
  146. {
  147. // Does it use chunks?
  148. GD.Print("Response is Chunked!");
  149. }
  150. else
  151. {
  152. // Or just Content-Length.
  153. GD.Print("Response Length: ", http.GetResponseBodyLength());
  154. }
  155. // This method works for both anyways.
  156. List<byte> rb = new List<byte>(); // List that will hold the data.
  157. // While there is data left to be read...
  158. while (http.GetStatus() == HTTPClient.Status.Body)
  159. {
  160. http.Poll();
  161. byte[] chunk = http.ReadResponseBodyChunk(); // Read a chunk.
  162. if (chunk.Length == 0)
  163. {
  164. // If nothing was read, wait for the buffer to fill.
  165. OS.DelayMsec(500);
  166. }
  167. else
  168. {
  169. // Append the chunk to the read buffer.
  170. rb.AddRange(chunk);
  171. }
  172. }
  173. // Done!
  174. GD.Print("Bytes Downloaded: ", rb.Count);
  175. string text = Encoding.ASCII.GetString(rb.ToArray());
  176. GD.Print(text);
  177. }
  178. Quit();
  179. }
  180. }