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 }