1 /** 2 A node with the ability to send HTTP(S) requests. 3 4 Copyright: 5 Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. 6 Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) 7 Copyright (c) 2017-2018 Godot-D contributors 8 9 License: $(LINK2 https://opensource.org/licenses/MIT, MIT License) 10 11 12 */ 13 module godot.httprequest; 14 import std.meta : AliasSeq, staticIndexOf; 15 import std.traits : Unqual; 16 import godot.d.traits; 17 import godot.core; 18 import godot.c; 19 import godot.d.bind; 20 import godot.d.reference; 21 import godot.globalenums; 22 import godot.object; 23 import godot.classdb; 24 import godot.node; 25 import godot.httpclient; 26 /** 27 A node with the ability to send HTTP(S) requests. 28 29 A node with the ability to send HTTP requests. Uses $(D HTTPClient) internally. 30 Can be used to make HTTP requests, i.e. download or upload files or web content via HTTP. 31 $(B Warning:) See the notes and warnings on $(D HTTPClient) for limitations, especially regarding SSL security. 32 $(B Example of contacting a REST API and printing one of its returned fields:) 33 34 35 func _ready(): 36 # Create an HTTP request node and connect its completion signal. 37 var http_request = HTTPRequest.new() 38 add_child(http_request) 39 http_request.connect("request_completed", self, "_http_request_completed") 40 41 # Perform a GET request. The URL below returns JSON as of writing. 42 var error = http_request.request("https://httpbin.org/get") 43 if error != OK: 44 push_error("An error occurred in the HTTP request.") 45 46 # Perform a POST request. The URL below returns JSON as of writing. 47 # Note: Don't make simultaneous requests using a single HTTPRequest node. 48 # The snippet below is provided for reference only. 49 var body = {"name": "Godette"} 50 error = http_request.request("https://httpbin.org/post", [], true, HTTPClient.METHOD_POST, body) 51 if error != OK: 52 push_error("An error occurred in the HTTP request.") 53 54 55 # Called when the HTTP request is completed. 56 func _http_request_completed(result, response_code, headers, body): 57 var response = parse_json(body.get_string_from_utf8()) 58 59 # Will print the user agent string used by the HTTPRequest node (as recognized by httpbin.org). 60 print(response.headers$(D "User-Agent")) 61 62 63 $(B Example of loading and displaying an image using HTTPRequest:) 64 65 66 func _ready(): 67 # Create an HTTP request node and connect its completion signal. 68 var http_request = HTTPRequest.new() 69 add_child(http_request) 70 http_request.connect("request_completed", self, "_http_request_completed") 71 72 # Perform the HTTP request. The URL below returns a PNG image as of writing. 73 var error = http_request.request("https://via.placeholder.com/512") 74 if error != OK: 75 push_error("An error occurred in the HTTP request.") 76 77 78 # Called when the HTTP request is completed. 79 func _http_request_completed(result, response_code, headers, body): 80 var image = Image.new() 81 var error = image.load_png_from_buffer(body) 82 if error != OK: 83 push_error("Couldn't load the image.") 84 85 var texture = ImageTexture.new() 86 texture.create_from_image(image) 87 88 # Display the image in a TextureRect node. 89 var texture_rect = TextureRect.new() 90 add_child(texture_rect) 91 texture_rect.texture = texture 92 93 94 */ 95 @GodotBaseClass struct HTTPRequest 96 { 97 package(godot) enum string _GODOT_internal_name = "HTTPRequest"; 98 public: 99 @nogc nothrow: 100 union { /** */ godot_object _godot_object; /** */ Node _GODOT_base; } 101 alias _GODOT_base this; 102 alias BaseClasses = AliasSeq!(typeof(_GODOT_base), typeof(_GODOT_base).BaseClasses); 103 package(godot) __gshared bool _classBindingInitialized = false; 104 package(godot) static struct GDNativeClassBinding 105 { 106 __gshared: 107 @GodotName("_redirect_request") GodotMethod!(void, String) _redirectRequest; 108 @GodotName("_request_done") GodotMethod!(void, long, long, PoolStringArray, PoolByteArray) _requestDone; 109 @GodotName("_timeout") GodotMethod!(void) _timeout; 110 @GodotName("cancel_request") GodotMethod!(void) cancelRequest; 111 @GodotName("get_body_size") GodotMethod!(long) getBodySize; 112 @GodotName("get_body_size_limit") GodotMethod!(long) getBodySizeLimit; 113 @GodotName("get_download_chunk_size") GodotMethod!(long) getDownloadChunkSize; 114 @GodotName("get_download_file") GodotMethod!(String) getDownloadFile; 115 @GodotName("get_downloaded_bytes") GodotMethod!(long) getDownloadedBytes; 116 @GodotName("get_http_client_status") GodotMethod!(HTTPClient.Status) getHttpClientStatus; 117 @GodotName("get_max_redirects") GodotMethod!(long) getMaxRedirects; 118 @GodotName("get_timeout") GodotMethod!(long) getTimeout; 119 @GodotName("is_using_threads") GodotMethod!(bool) isUsingThreads; 120 @GodotName("request") GodotMethod!(GodotError, String, PoolStringArray, bool, long, String) request; 121 @GodotName("set_body_size_limit") GodotMethod!(void, long) setBodySizeLimit; 122 @GodotName("set_download_chunk_size") GodotMethod!(void, long) setDownloadChunkSize; 123 @GodotName("set_download_file") GodotMethod!(void, String) setDownloadFile; 124 @GodotName("set_max_redirects") GodotMethod!(void, long) setMaxRedirects; 125 @GodotName("set_timeout") GodotMethod!(void, long) setTimeout; 126 @GodotName("set_use_threads") GodotMethod!(void, bool) setUseThreads; 127 } 128 /// 129 pragma(inline, true) bool opEquals(in HTTPRequest other) const 130 { return _godot_object.ptr is other._godot_object.ptr; } 131 /// 132 pragma(inline, true) typeof(null) opAssign(typeof(null) n) 133 { _godot_object.ptr = n; return null; } 134 /// 135 pragma(inline, true) bool opEquals(typeof(null) n) const 136 { return _godot_object.ptr is n; } 137 /// 138 size_t toHash() const @trusted { return cast(size_t)_godot_object.ptr; } 139 mixin baseCasts; 140 /// Construct a new instance of HTTPRequest. 141 /// Note: use `memnew!HTTPRequest` instead. 142 static HTTPRequest _new() 143 { 144 static godot_class_constructor constructor; 145 if(constructor is null) constructor = _godot_api.godot_get_class_constructor("HTTPRequest"); 146 if(constructor is null) return typeof(this).init; 147 return cast(HTTPRequest)(constructor()); 148 } 149 @disable new(size_t s); 150 /// 151 enum Result : int 152 { 153 /** 154 Request successful. 155 */ 156 resultSuccess = 0, 157 /** 158 159 */ 160 resultChunkedBodySizeMismatch = 1, 161 /** 162 Request failed while connecting. 163 */ 164 resultCantConnect = 2, 165 /** 166 Request failed while resolving. 167 */ 168 resultCantResolve = 3, 169 /** 170 Request failed due to connection (read/write) error. 171 */ 172 resultConnectionError = 4, 173 /** 174 Request failed on SSL handshake. 175 */ 176 resultSslHandshakeError = 5, 177 /** 178 Request does not have a response (yet). 179 */ 180 resultNoResponse = 6, 181 /** 182 Request exceeded its maximum size limit, see $(D bodySizeLimit). 183 */ 184 resultBodySizeLimitExceeded = 7, 185 /** 186 Request failed (currently unused). 187 */ 188 resultRequestFailed = 8, 189 /** 190 HTTPRequest couldn't open the download file. 191 */ 192 resultDownloadFileCantOpen = 9, 193 /** 194 HTTPRequest couldn't write to the download file. 195 */ 196 resultDownloadFileWriteError = 10, 197 /** 198 Request reached its maximum redirect limit, see $(D maxRedirects). 199 */ 200 resultRedirectLimitReached = 11, 201 /** 202 203 */ 204 resultTimeout = 12, 205 } 206 /// 207 enum Constants : int 208 { 209 resultSuccess = 0, 210 resultChunkedBodySizeMismatch = 1, 211 resultCantConnect = 2, 212 resultCantResolve = 3, 213 resultConnectionError = 4, 214 resultSslHandshakeError = 5, 215 resultNoResponse = 6, 216 resultBodySizeLimitExceeded = 7, 217 resultRequestFailed = 8, 218 resultDownloadFileCantOpen = 9, 219 resultDownloadFileWriteError = 10, 220 resultRedirectLimitReached = 11, 221 resultTimeout = 12, 222 } 223 /** 224 225 */ 226 void _redirectRequest(in String arg0) 227 { 228 Array _GODOT_args = Array.make(); 229 _GODOT_args.append(arg0); 230 String _GODOT_method_name = String("_redirect_request"); 231 this.callv(_GODOT_method_name, _GODOT_args); 232 } 233 /** 234 235 */ 236 void _requestDone(in long arg0, in long arg1, in PoolStringArray arg2, in PoolByteArray arg3) 237 { 238 Array _GODOT_args = Array.make(); 239 _GODOT_args.append(arg0); 240 _GODOT_args.append(arg1); 241 _GODOT_args.append(arg2); 242 _GODOT_args.append(arg3); 243 String _GODOT_method_name = String("_request_done"); 244 this.callv(_GODOT_method_name, _GODOT_args); 245 } 246 /** 247 248 */ 249 void _timeout() 250 { 251 Array _GODOT_args = Array.make(); 252 String _GODOT_method_name = String("_timeout"); 253 this.callv(_GODOT_method_name, _GODOT_args); 254 } 255 /** 256 Cancels the current request. 257 */ 258 void cancelRequest() 259 { 260 checkClassBinding!(typeof(this))(); 261 ptrcall!(void)(GDNativeClassBinding.cancelRequest, _godot_object); 262 } 263 /** 264 Returns the response body length. 265 $(B Note:) Some Web servers may not send a body length. In this case, the value returned will be `-1`. If using chunked transfer encoding, the body length will also be `-1`. 266 */ 267 long getBodySize() const 268 { 269 checkClassBinding!(typeof(this))(); 270 return ptrcall!(long)(GDNativeClassBinding.getBodySize, _godot_object); 271 } 272 /** 273 274 */ 275 long getBodySizeLimit() const 276 { 277 checkClassBinding!(typeof(this))(); 278 return ptrcall!(long)(GDNativeClassBinding.getBodySizeLimit, _godot_object); 279 } 280 /** 281 282 */ 283 long getDownloadChunkSize() const 284 { 285 checkClassBinding!(typeof(this))(); 286 return ptrcall!(long)(GDNativeClassBinding.getDownloadChunkSize, _godot_object); 287 } 288 /** 289 290 */ 291 String getDownloadFile() const 292 { 293 checkClassBinding!(typeof(this))(); 294 return ptrcall!(String)(GDNativeClassBinding.getDownloadFile, _godot_object); 295 } 296 /** 297 Returns the amount of bytes this HTTPRequest downloaded. 298 */ 299 long getDownloadedBytes() const 300 { 301 checkClassBinding!(typeof(this))(); 302 return ptrcall!(long)(GDNativeClassBinding.getDownloadedBytes, _godot_object); 303 } 304 /** 305 Returns the current status of the underlying $(D HTTPClient). See $(D HTTPClient.status). 306 */ 307 HTTPClient.Status getHttpClientStatus() const 308 { 309 checkClassBinding!(typeof(this))(); 310 return ptrcall!(HTTPClient.Status)(GDNativeClassBinding.getHttpClientStatus, _godot_object); 311 } 312 /** 313 314 */ 315 long getMaxRedirects() const 316 { 317 checkClassBinding!(typeof(this))(); 318 return ptrcall!(long)(GDNativeClassBinding.getMaxRedirects, _godot_object); 319 } 320 /** 321 322 */ 323 long getTimeout() 324 { 325 checkClassBinding!(typeof(this))(); 326 return ptrcall!(long)(GDNativeClassBinding.getTimeout, _godot_object); 327 } 328 /** 329 330 */ 331 bool isUsingThreads() const 332 { 333 checkClassBinding!(typeof(this))(); 334 return ptrcall!(bool)(GDNativeClassBinding.isUsingThreads, _godot_object); 335 } 336 /** 337 Creates request on the underlying $(D HTTPClient). If there is no configuration errors, it tries to connect using $(D HTTPClient.connectToHost) and passes parameters onto $(D HTTPClient.request). 338 Returns $(D constant OK) if request is successfully created. (Does not imply that the server has responded), $(D constant ERR_UNCONFIGURED) if not in the tree, $(D constant ERR_BUSY) if still processing previous request, $(D constant ERR_INVALID_PARAMETER) if given string is not a valid URL format, or $(D constant ERR_CANT_CONNECT) if not using thread and the $(D HTTPClient) cannot connect to host. 339 $(B Note:) The `request_data` parameter is ignored if `method` is $(D constant HTTPClient.METHOD_GET). This is because GET methods can't contain request data. As a workaround, you can pass request data as a query string in the URL. See $(D String.httpEscape) for an example. 340 */ 341 GodotError request(in String url, in PoolStringArray custom_headers = PoolStringArray.init, in bool ssl_validate_domain = true, in long method = 0, in String request_data = gs!"") 342 { 343 checkClassBinding!(typeof(this))(); 344 return ptrcall!(GodotError)(GDNativeClassBinding.request, _godot_object, url, custom_headers, ssl_validate_domain, method, request_data); 345 } 346 /** 347 348 */ 349 void setBodySizeLimit(in long bytes) 350 { 351 checkClassBinding!(typeof(this))(); 352 ptrcall!(void)(GDNativeClassBinding.setBodySizeLimit, _godot_object, bytes); 353 } 354 /** 355 356 */ 357 void setDownloadChunkSize(in long arg0) 358 { 359 checkClassBinding!(typeof(this))(); 360 ptrcall!(void)(GDNativeClassBinding.setDownloadChunkSize, _godot_object, arg0); 361 } 362 /** 363 364 */ 365 void setDownloadFile(in String path) 366 { 367 checkClassBinding!(typeof(this))(); 368 ptrcall!(void)(GDNativeClassBinding.setDownloadFile, _godot_object, path); 369 } 370 /** 371 372 */ 373 void setMaxRedirects(in long amount) 374 { 375 checkClassBinding!(typeof(this))(); 376 ptrcall!(void)(GDNativeClassBinding.setMaxRedirects, _godot_object, amount); 377 } 378 /** 379 380 */ 381 void setTimeout(in long timeout) 382 { 383 checkClassBinding!(typeof(this))(); 384 ptrcall!(void)(GDNativeClassBinding.setTimeout, _godot_object, timeout); 385 } 386 /** 387 388 */ 389 void setUseThreads(in bool enable) 390 { 391 checkClassBinding!(typeof(this))(); 392 ptrcall!(void)(GDNativeClassBinding.setUseThreads, _godot_object, enable); 393 } 394 /** 395 Maximum allowed size for response bodies. 396 */ 397 @property long bodySizeLimit() 398 { 399 return getBodySizeLimit(); 400 } 401 /// ditto 402 @property void bodySizeLimit(long v) 403 { 404 setBodySizeLimit(v); 405 } 406 /** 407 The size of the buffer used and maximum bytes to read per iteration. See $(D HTTPClient.readChunkSize). 408 Set this to a lower value (e.g. 4096 for 4 KiB) when downloading small files to decrease memory usage at the cost of download speeds. 409 */ 410 @property long downloadChunkSize() 411 { 412 return getDownloadChunkSize(); 413 } 414 /// ditto 415 @property void downloadChunkSize(long v) 416 { 417 setDownloadChunkSize(v); 418 } 419 /** 420 The file to download into. Will output any received file into it. 421 */ 422 @property String downloadFile() 423 { 424 return getDownloadFile(); 425 } 426 /// ditto 427 @property void downloadFile(String v) 428 { 429 setDownloadFile(v); 430 } 431 /** 432 Maximum number of allowed redirects. 433 */ 434 @property long maxRedirects() 435 { 436 return getMaxRedirects(); 437 } 438 /// ditto 439 @property void maxRedirects(long v) 440 { 441 setMaxRedirects(v); 442 } 443 /** 444 445 */ 446 @property long timeout() 447 { 448 return getTimeout(); 449 } 450 /// ditto 451 @property void timeout(long v) 452 { 453 setTimeout(v); 454 } 455 /** 456 If `true`, multithreading is used to improve performance. 457 */ 458 @property bool useThreads() 459 { 460 return isUsingThreads(); 461 } 462 /// ditto 463 @property void useThreads(bool v) 464 { 465 setUseThreads(v); 466 } 467 }