http_client_class.rst 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. await get_tree().process_frame
  36. assert(http.get_status() == HTTPClient.STATUS_CONNECTED) # Check if the connection was made successfully.
  37. # Some headers
  38. var headers = [
  39. "User-Agent: Pirulo/1.0 (Godot)",
  40. "Accept: */*"
  41. ]
  42. err = http.request(HTTPClient.METHOD_GET, "/ChangeLog-5.php", headers) # Request a page from the site (this one was chunked..)
  43. assert(err == OK) # Make sure all is OK.
  44. while http.get_status() == HTTPClient.STATUS_REQUESTING:
  45. # Keep polling for as long as the request is being processed.
  46. http.poll()
  47. print("Requesting...")
  48. await get_tree().process_frame
  49. assert(http.get_status() == HTTPClient.STATUS_BODY or http.get_status() == HTTPClient.STATUS_CONNECTED) # Make sure request finished well.
  50. print("response? ", http.has_response()) # Site might not have a response.
  51. if http.has_response():
  52. # If there is a response...
  53. headers = http.get_response_headers_as_dictionary() # Get response headers.
  54. print("code: ", http.get_response_code()) # Show response code.
  55. print("**headers:\\n", headers) # Show headers.
  56. # Getting the HTTP Body
  57. if http.is_response_chunked():
  58. # Does it use chunks?
  59. print("Response is Chunked!")
  60. else:
  61. # Or just plain Content-Length
  62. var bl = http.get_response_body_length()
  63. print("Response Length: ", bl)
  64. # This method works for both anyway
  65. var rb = PackedByteArray() # Array that will hold the data.
  66. while http.get_status() == HTTPClient.STATUS_BODY:
  67. # While there is body left to be read
  68. http.poll()
  69. # Get a chunk.
  70. var chunk = http.read_response_body_chunk()
  71. if chunk.size() == 0:
  72. await get_tree().process_frame
  73. else:
  74. rb = rb + chunk # Append to read buffer.
  75. # Done!
  76. print("bytes got: ", rb.size())
  77. var text = rb.get_string_from_ascii()
  78. print("Text: ", text)
  79. quit()
  80. .. code-tab:: csharp
  81. using Godot;
  82. public partial class HTTPTest : SceneTree
  83. {
  84. // HTTPClient demo.
  85. // This simple class can make HTTP requests; it will not block, but it needs to be polled.
  86. public override async void _Initialize()
  87. {
  88. Error err;
  89. HTTPClient http = new HTTPClient(); // Create the client.
  90. err = http.ConnectToHost("www.php.net", 80); // Connect to host/port.
  91. Debug.Assert(err == Error.Ok); // Make sure the connection is OK.
  92. // Wait until resolved and connected.
  93. while (http.GetStatus() == HTTPClient.Status.Connecting || http.GetStatus() == HTTPClient.Status.Resolving)
  94. {
  95. http.Poll();
  96. GD.Print("Connecting...");
  97. OS.DelayMsec(500);
  98. }
  99. Debug.Assert(http.GetStatus() == HTTPClient.Status.Connected); // Check if the connection was made successfully.
  100. // Some headers.
  101. string[] headers = { "User-Agent: Pirulo/1.0 (Godot)", "Accept: */*" };
  102. err = http.Request(HTTPClient.Method.Get, "/ChangeLog-5.php", headers); // Request a page from the site.
  103. Debug.Assert(err == Error.Ok); // Make sure all is OK.
  104. // Keep polling for as long as the request is being processed.
  105. while (http.GetStatus() == HTTPClient.Status.Requesting)
  106. {
  107. http.Poll();
  108. GD.Print("Requesting...");
  109. if (OS.HasFeature("web"))
  110. {
  111. // Synchronous HTTP requests are not supported on the web,
  112. // so wait for the next main loop iteration.
  113. await ToSignal(Engine.GetMainLoop(), "idle_frame");
  114. }
  115. else
  116. {
  117. OS.DelayMsec(500);
  118. }
  119. }
  120. Debug.Assert(http.GetStatus() == HTTPClient.Status.Body || http.GetStatus() == HTTPClient.Status.Connected); // Make sure the request finished well.
  121. GD.Print("Response? ", http.HasResponse()); // The site might not have a response.
  122. // If there is a response...
  123. if (http.HasResponse())
  124. {
  125. headers = http.GetResponseHeaders(); // Get response headers.
  126. GD.Print("Code: ", http.GetResponseCode()); // Show response code.
  127. GD.Print("Headers:");
  128. foreach (string header in headers)
  129. {
  130. // Show headers.
  131. GD.Print(header);
  132. }
  133. if (http.IsResponseChunked())
  134. {
  135. // Does it use chunks?
  136. GD.Print("Response is Chunked!");
  137. }
  138. else
  139. {
  140. // Or just Content-Length.
  141. GD.Print("Response Length: ", http.GetResponseBodyLength());
  142. }
  143. // This method works for both anyways.
  144. List<byte> rb = new List<byte>(); // List that will hold the data.
  145. // While there is data left to be read...
  146. while (http.GetStatus() == HTTPClient.Status.Body)
  147. {
  148. http.Poll();
  149. byte[] chunk = http.ReadResponseBodyChunk(); // Read a chunk.
  150. if (chunk.Length == 0)
  151. {
  152. // If nothing was read, wait for the buffer to fill.
  153. OS.DelayMsec(500);
  154. }
  155. else
  156. {
  157. // Append the chunk to the read buffer.
  158. rb.AddRange(chunk);
  159. }
  160. }
  161. // Done!
  162. GD.Print("Bytes Downloaded: ", rb.Count);
  163. string text = Encoding.ASCII.GetString(rb.ToArray());
  164. GD.Print(text);
  165. }
  166. Quit();
  167. }
  168. }