1 module soup.Session;
2 
3 private import gio.AsyncResultIF;
4 private import gio.Cancellable;
5 private import gio.IOStream;
6 private import gio.InputStream;
7 private import glib.ConstructionException;
8 private import glib.ErrorG;
9 private import glib.GException;
10 private import glib.ListSG;
11 private import glib.MainContext;
12 private import glib.Str;
13 private import gobject.ObjectG;
14 private import gobject.Signals;
15 private import soup.Auth;
16 private import soup.Message;
17 private import soup.Request;
18 private import soup.RequestHTTP;
19 private import soup.SessionFeatureIF;
20 private import soup.Socket;
21 private import soup.URI;
22 private import soup.WebsocketConnection;
23 private import soup.c.functions;
24 public  import soup.c.types;
25 private import std.algorithm;
26 
27 
28 /**
29  * #SoupSession is the object that controls client-side HTTP. A
30  * #SoupSession encapsulates all of the state that libsoup is keeping
31  * on behalf of your program; cached HTTP connections, authentication
32  * information, etc. It also keeps track of various global options
33  * and features that you are using.
34  * 
35  * Most applications will only need a single #SoupSession; the primary
36  * reason you might need multiple sessions is if you need to have
37  * multiple independent authentication contexts. (Eg, you are
38  * connecting to a server and authenticating as two different users at
39  * different times; the easiest way to ensure that each #SoupMessage
40  * is sent with the authentication information you intended is to use
41  * one session for the first user, and a second session for the other
42  * user.)
43  * 
44  * In the past, #SoupSession was an abstract class, and users needed
45  * to choose between #SoupSessionAsync (which always uses
46  * #GMainLoop<!-- -->-based I/O), or #SoupSessionSync (which always uses
47  * blocking I/O and can be used from multiple threads simultaneously).
48  * This is no longer necessary; you can (and should) use a plain
49  * #SoupSession, which supports both synchronous and asynchronous use.
50  * (When using a plain #SoupSession, soup_session_queue_message()
51  * behaves like it traditionally did on a #SoupSessionAsync, and
52  * soup_session_send_message() behaves like it traditionally did on a
53  * #SoupSessionSync.)
54  * 
55  * Additional #SoupSession functionality is provided by
56  * #SoupSessionFeature objects, which can be added to a session with
57  * soup_session_add_feature() or soup_session_add_feature_by_type()
58  * (or at construct time with the %SOUP_SESSION_ADD_FEATURE_BY_TYPE
59  * pseudo-property). For example, #SoupLogger provides support for
60  * logging HTTP traffic, #SoupContentDecoder provides support for
61  * compressed response handling, and #SoupContentSniffer provides
62  * support for HTML5-style response body content sniffing.
63  * Additionally, subtypes of #SoupAuth and #SoupRequest can be added
64  * as features, to add support for additional authentication and URI
65  * types.
66  * 
67  * All #SoupSessions are created with a #SoupAuthManager, and support
68  * for %SOUP_TYPE_AUTH_BASIC and %SOUP_TYPE_AUTH_DIGEST. For
69  * #SoupRequest types, #SoupRequestHTTP, #SoupRequestFile, and
70  * #SoupRequestData are supported. Additionally, sessions using the
71  * plain #SoupSession class (rather than one of its deprecated
72  * subtypes) have a #SoupContentDecoder by default.
73  */
74 public class Session : ObjectG
75 {
76 	/** the main Gtk struct */
77 	protected SoupSession* soupSession;
78 
79 	/** Get the main Gtk struct */
80 	public SoupSession* getSessionStruct(bool transferOwnership = false)
81 	{
82 		if (transferOwnership)
83 			ownedRef = false;
84 		return soupSession;
85 	}
86 
87 	/** the main Gtk struct as a void* */
88 	protected override void* getStruct()
89 	{
90 		return cast(void*)soupSession;
91 	}
92 
93 	/**
94 	 * Sets our main struct and passes it to the parent class.
95 	 */
96 	public this (SoupSession* soupSession, bool ownedRef = false)
97 	{
98 		this.soupSession = soupSession;
99 		super(cast(GObject*)soupSession, ownedRef);
100 	}
101 
102 
103 	/** */
104 	public static GType getType()
105 	{
106 		return soup_session_get_type();
107 	}
108 
109 	/**
110 	 * Creates a #SoupSession with the default options.
111 	 *
112 	 * Returns: the new session.
113 	 *
114 	 * Since: 2.42
115 	 *
116 	 * Throws: ConstructionException GTK+ fails to create the object.
117 	 */
118 	public this()
119 	{
120 		auto __p = soup_session_new();
121 
122 		if(__p is null)
123 		{
124 			throw new ConstructionException("null returned by new");
125 		}
126 
127 		this(cast(SoupSession*) __p, true);
128 	}
129 
130 	/**
131 	 * Cancels all pending requests in @session and closes all idle
132 	 * persistent connections.
133 	 *
134 	 * The message cancellation has the same semantics as with
135 	 * soup_session_cancel_message(); asynchronous requests on a
136 	 * #SoupSessionAsync will have their callback called before
137 	 * soup_session_abort() returns. Requests on a plain #SoupSession will
138 	 * not.
139 	 */
140 	public void abort()
141 	{
142 		soup_session_abort(soupSession);
143 	}
144 
145 	/**
146 	 * Adds @feature's functionality to @session. You can also add a
147 	 * feature to the session at construct time by using the
148 	 * %SOUP_SESSION_ADD_FEATURE property.
149 	 *
150 	 * See the main #SoupSession documentation for information on what
151 	 * features are present in sessions by default.
152 	 *
153 	 * Params:
154 	 *     feature = an object that implements #SoupSessionFeature
155 	 *
156 	 * Since: 2.24
157 	 */
158 	public void addFeature(SessionFeatureIF feature)
159 	{
160 		soup_session_add_feature(soupSession, (feature is null) ? null : feature.getSessionFeatureStruct());
161 	}
162 
163 	/**
164 	 * If @feature_type is the type of a class that implements
165 	 * #SoupSessionFeature, this creates a new feature of that type and
166 	 * adds it to @session as with soup_session_add_feature(). You can use
167 	 * this when you don't need to customize the new feature in any way.
168 	 *
169 	 * If @feature_type is not a #SoupSessionFeature type, this gives each
170 	 * existing feature on @session the chance to accept @feature_type as
171 	 * a "subfeature". This can be used to add new #SoupAuth or
172 	 * #SoupRequest types, for instance.
173 	 *
174 	 * You can also add a feature to the session at construct time by
175 	 * using the %SOUP_SESSION_ADD_FEATURE_BY_TYPE property.
176 	 *
177 	 * See the main #SoupSession documentation for information on what
178 	 * features are present in sessions by default.
179 	 *
180 	 * Params:
181 	 *     featureType = a #GType
182 	 *
183 	 * Since: 2.24
184 	 */
185 	public void addFeatureByType(GType featureType)
186 	{
187 		soup_session_add_feature_by_type(soupSession, featureType);
188 	}
189 
190 	/**
191 	 * Causes @session to immediately finish processing @msg (regardless
192 	 * of its current state) with a final status_code of @status_code. You
193 	 * may call this at any time after handing @msg off to @session; if
194 	 * @session has started sending the request but has not yet received
195 	 * the complete response, then it will close the request's connection.
196 	 * Note that with requests that have side effects (eg,
197 	 * <literal>POST</literal>, <literal>PUT</literal>,
198 	 * <literal>DELETE</literal>) it is possible that you might cancel the
199 	 * request after the server acts on it, but before it returns a
200 	 * response, leaving the remote resource in an unknown state.
201 	 *
202 	 * If the message is cancelled while its response body is being read,
203 	 * then the response body in @msg will be left partially-filled-in.
204 	 * The response headers, on the other hand, will always be either
205 	 * empty or complete.
206 	 *
207 	 * Beware that with the deprecated #SoupSessionAsync, messages queued
208 	 * with soup_session_queue_message() will have their callbacks invoked
209 	 * before soup_session_cancel_message() returns. The plain
210 	 * #SoupSession does not have this behavior; cancelling an
211 	 * asynchronous message will merely queue its callback to be run after
212 	 * returning to the main loop.
213 	 *
214 	 * Params:
215 	 *     msg = the message to cancel
216 	 *     statusCode = status code to set on @msg (generally
217 	 *         %SOUP_STATUS_CANCELLED)
218 	 */
219 	public void cancelMessage(Message msg, uint statusCode)
220 	{
221 		soup_session_cancel_message(soupSession, (msg is null) ? null : msg.getMessageStruct(), statusCode);
222 	}
223 
224 	/**
225 	 * Start a connection to @uri. The operation can be monitored by providing a @progress_callback
226 	 * and finishes when the connection is done or an error ocurred.
227 	 *
228 	 * Call soup_session_connect_finish() to get the #GIOStream to communicate with the server.
229 	 *
230 	 * Params:
231 	 *     uri = a #SoupURI to connect to
232 	 *     cancellable = a #GCancellable
233 	 *     progressCallback = a #SoupSessionConnectProgressCallback which
234 	 *         will be called for every network event that occurs during the connection.
235 	 *     callback = the callback to invoke when the operation finishes
236 	 *     userData = data for @progress_callback and @callback
237 	 *
238 	 * Since: 2.62
239 	 */
240 	public void connectAsync(URI uri, Cancellable cancellable, SoupSessionConnectProgressCallback progressCallback, GAsyncReadyCallback callback, void* userData)
241 	{
242 		soup_session_connect_async(soupSession, (uri is null) ? null : uri.getURIStruct(), (cancellable is null) ? null : cancellable.getCancellableStruct(), progressCallback, callback, userData);
243 	}
244 
245 	/**
246 	 * Gets the #GIOStream created for the connection to communicate with the server.
247 	 *
248 	 * Params:
249 	 *     result = the #GAsyncResult passed to your callback
250 	 *
251 	 * Returns: a new #GIOStream, or %NULL on error.
252 	 *
253 	 * Since: 2.62
254 	 *
255 	 * Throws: GException on failure.
256 	 */
257 	public IOStream connectFinish(AsyncResultIF result)
258 	{
259 		GError* err = null;
260 
261 		auto __p = soup_session_connect_finish(soupSession, (result is null) ? null : result.getAsyncResultStruct(), &err);
262 
263 		if (err !is null)
264 		{
265 			throw new GException( new ErrorG(err) );
266 		}
267 
268 		if(__p is null)
269 		{
270 			return null;
271 		}
272 
273 		return ObjectG.getDObject!(IOStream)(cast(GIOStream*) __p, true);
274 	}
275 
276 	/**
277 	 * Gets @session's #SoupSession:async-context. This does not add a ref
278 	 * to the context, so you will need to ref it yourself if you want it
279 	 * to outlive its session.
280 	 *
281 	 * For a modern #SoupSession, this will always just return the
282 	 * thread-default #GMainContext, and so is not especially useful.
283 	 *
284 	 * Returns: @session's #GMainContext,
285 	 *     which may be %NULL
286 	 */
287 	public MainContext getAsyncContext()
288 	{
289 		auto __p = soup_session_get_async_context(soupSession);
290 
291 		if(__p is null)
292 		{
293 			return null;
294 		}
295 
296 		return new MainContext(cast(GMainContext*) __p);
297 	}
298 
299 	/**
300 	 * Gets the first feature in @session of type @feature_type. For
301 	 * features where there may be more than one feature of a given type,
302 	 * use soup_session_get_features().
303 	 *
304 	 * Params:
305 	 *     featureType = the #GType of the feature to get
306 	 *
307 	 * Returns: a #SoupSessionFeature, or
308 	 *     %NULL. The feature is owned by @session.
309 	 *
310 	 * Since: 2.26
311 	 */
312 	public SessionFeatureIF getFeature(GType featureType)
313 	{
314 		auto __p = soup_session_get_feature(soupSession, featureType);
315 
316 		if(__p is null)
317 		{
318 			return null;
319 		}
320 
321 		return ObjectG.getDObject!(SessionFeatureIF)(cast(SoupSessionFeature*) __p);
322 	}
323 
324 	/**
325 	 * Gets the first feature in @session of type @feature_type, provided
326 	 * that it is not disabled for @msg. As with
327 	 * soup_session_get_feature(), this should only be used for features
328 	 * where @feature_type is only expected to match a single feature. In
329 	 * particular, if there are two matching features, and the first is
330 	 * disabled on @msg, and the second is not, then this will return
331 	 * %NULL, not the second feature.
332 	 *
333 	 * Params:
334 	 *     featureType = the #GType of the feature to get
335 	 *     msg = a #SoupMessage
336 	 *
337 	 * Returns: a #SoupSessionFeature, or %NULL. The
338 	 *     feature is owned by @session.
339 	 *
340 	 * Since: 2.28
341 	 */
342 	public SessionFeatureIF getFeatureForMessage(GType featureType, Message msg)
343 	{
344 		auto __p = soup_session_get_feature_for_message(soupSession, featureType, (msg is null) ? null : msg.getMessageStruct());
345 
346 		if(__p is null)
347 		{
348 			return null;
349 		}
350 
351 		return ObjectG.getDObject!(SessionFeatureIF)(cast(SoupSessionFeature*) __p);
352 	}
353 
354 	/**
355 	 * Generates a list of @session's features of type @feature_type. (If
356 	 * you want to see all features, you can pass %SOUP_TYPE_SESSION_FEATURE
357 	 * for @feature_type.)
358 	 *
359 	 * Params:
360 	 *     featureType = the #GType of the class of features to get
361 	 *
362 	 * Returns: a list of features. You must free the list, but not its contents
363 	 *
364 	 * Since: 2.26
365 	 */
366 	public ListSG getFeatures(GType featureType)
367 	{
368 		auto __p = soup_session_get_features(soupSession, featureType);
369 
370 		if(__p is null)
371 		{
372 			return null;
373 		}
374 
375 		return new ListSG(cast(GSList*) __p);
376 	}
377 
378 	/**
379 	 * Tests if @session has at a feature of type @feature_type (which can
380 	 * be the type of either a #SoupSessionFeature, or else a subtype of
381 	 * some class managed by another feature, such as #SoupAuth or
382 	 * #SoupRequest).
383 	 *
384 	 * Params:
385 	 *     featureType = the #GType of the class of features to check for
386 	 *
387 	 * Returns: %TRUE or %FALSE
388 	 *
389 	 * Since: 2.42
390 	 */
391 	public bool hasFeature(GType featureType)
392 	{
393 		return soup_session_has_feature(soupSession, featureType) != 0;
394 	}
395 
396 	/**
397 	 * Pauses HTTP I/O on @msg. Call soup_session_unpause_message() to
398 	 * resume I/O.
399 	 *
400 	 * This may only be called for asynchronous messages (those sent on a
401 	 * #SoupSessionAsync or using soup_session_queue_message()).
402 	 *
403 	 * Params:
404 	 *     msg = a #SoupMessage currently running on @session
405 	 */
406 	public void pauseMessage(Message msg)
407 	{
408 		soup_session_pause_message(soupSession, (msg is null) ? null : msg.getMessageStruct());
409 	}
410 
411 	/**
412 	 * Tells @session that an URI from the given @hostname may be requested
413 	 * shortly, and so the session can try to prepare by resolving the
414 	 * domain name in advance, in order to work more quickly once the URI
415 	 * is actually requested.
416 	 *
417 	 * If @cancellable is non-%NULL, it can be used to cancel the
418 	 * resolution. @callback will still be invoked in this case, with a
419 	 * status of %SOUP_STATUS_CANCELLED.
420 	 *
421 	 * Params:
422 	 *     hostname = a hostname to be resolved
423 	 *     cancellable = a #GCancellable object, or %NULL
424 	 *     callback = callback to call with the
425 	 *         result, or %NULL
426 	 *     userData = data for @callback
427 	 *
428 	 * Since: 2.38
429 	 */
430 	public void prefetchDns(string hostname, Cancellable cancellable, SoupAddressCallback callback, void* userData)
431 	{
432 		soup_session_prefetch_dns(soupSession, Str.toStringz(hostname), (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData);
433 	}
434 
435 	/**
436 	 * Tells @session that @uri may be requested shortly, and so the
437 	 * session can try to prepare (resolving the domain name, obtaining
438 	 * proxy address, etc.) in order to work more quickly once the URI is
439 	 * actually requested.
440 	 *
441 	 * Deprecated: use soup_session_prefetch_dns() instead
442 	 *
443 	 * Params:
444 	 *     uri = a #SoupURI which may be required
445 	 *
446 	 * Since: 2.30
447 	 */
448 	public void prepareForUri(URI uri)
449 	{
450 		soup_session_prepare_for_uri(soupSession, (uri is null) ? null : uri.getURIStruct());
451 	}
452 
453 	/**
454 	 * Queues the message @msg for asynchronously sending the request and
455 	 * receiving a response in the current thread-default #GMainContext.
456 	 * If @msg has been processed before, any resources related to the
457 	 * time it was last sent are freed.
458 	 *
459 	 * Upon message completion, the callback specified in @callback will
460 	 * be invoked. If after returning from this callback the message has not
461 	 * been requeued, @msg will be unreffed.
462 	 *
463 	 * (The behavior above applies to a plain #SoupSession; if you are
464 	 * using #SoupSessionAsync or #SoupSessionSync, then the #GMainContext
465 	 * that is used depends on the settings of #SoupSession:async-context
466 	 * and #SoupSession:use-thread-context, and for #SoupSessionSync, the
467 	 * message will actually be sent and processed in another thread, with
468 	 * only the final callback occurring in the indicated #GMainContext.)
469 	 *
470 	 * Contrast this method with soup_session_send_async(), which also
471 	 * asynchronously sends a message, but returns before reading the
472 	 * response body, and allows you to read the response via a
473 	 * #GInputStream.
474 	 *
475 	 * Params:
476 	 *     msg = the message to queue
477 	 *     callback = a #SoupSessionCallback which will
478 	 *         be called after the message completes or when an unrecoverable error occurs.
479 	 *     userData = a pointer passed to @callback.
480 	 */
481 	public void queueMessage(Message msg, SoupSessionCallback callback, void* userData)
482 	{
483 		soup_session_queue_message(soupSession, (msg is null) ? null : msg.getMessageStruct(), callback, userData);
484 	}
485 
486 	/**
487 	 * Updates @msg's URI according to its status code and "Location"
488 	 * header, and requeues it on @session. Use this when you have set
489 	 * %SOUP_MESSAGE_NO_REDIRECT on a message, but have decided to allow a
490 	 * particular redirection to occur, or if you want to allow a
491 	 * redirection that #SoupSession will not perform automatically (eg,
492 	 * redirecting a non-safe method such as DELETE).
493 	 *
494 	 * If @msg's status code indicates that it should be retried as a GET
495 	 * request, then @msg will be modified accordingly.
496 	 *
497 	 * If @msg has already been redirected too many times, this will
498 	 * cause it to fail with %SOUP_STATUS_TOO_MANY_REDIRECTS.
499 	 *
500 	 * Params:
501 	 *     msg = a #SoupMessage that has received a 3xx response
502 	 *
503 	 * Returns: %TRUE if a redirection was applied, %FALSE if not
504 	 *     (eg, because there was no Location header, or it could not be
505 	 *     parsed).
506 	 *
507 	 * Since: 2.38
508 	 */
509 	public bool redirectMessage(Message msg)
510 	{
511 		return soup_session_redirect_message(soupSession, (msg is null) ? null : msg.getMessageStruct()) != 0;
512 	}
513 
514 	/**
515 	 * Removes @feature's functionality from @session.
516 	 *
517 	 * Params:
518 	 *     feature = a feature that has previously been added to @session
519 	 *
520 	 * Since: 2.24
521 	 */
522 	public void removeFeature(SessionFeatureIF feature)
523 	{
524 		soup_session_remove_feature(soupSession, (feature is null) ? null : feature.getSessionFeatureStruct());
525 	}
526 
527 	/**
528 	 * Removes all features of type @feature_type (or any subclass of
529 	 * @feature_type) from @session. You can also remove standard features
530 	 * from the session at construct time by using the
531 	 * %SOUP_SESSION_REMOVE_FEATURE_BY_TYPE property.
532 	 *
533 	 * Params:
534 	 *     featureType = a #GType
535 	 *
536 	 * Since: 2.24
537 	 */
538 	public void removeFeatureByType(GType featureType)
539 	{
540 		soup_session_remove_feature_by_type(soupSession, featureType);
541 	}
542 
543 	/**
544 	 * Creates a #SoupRequest for retrieving @uri_string.
545 	 *
546 	 * Params:
547 	 *     uriString = a URI, in string form
548 	 *
549 	 * Returns: a new #SoupRequest, or
550 	 *     %NULL on error.
551 	 *
552 	 * Since: 2.42
553 	 *
554 	 * Throws: GException on failure.
555 	 */
556 	public Request request(string uriString)
557 	{
558 		GError* err = null;
559 
560 		auto __p = soup_session_request(soupSession, Str.toStringz(uriString), &err);
561 
562 		if (err !is null)
563 		{
564 			throw new GException( new ErrorG(err) );
565 		}
566 
567 		if(__p is null)
568 		{
569 			return null;
570 		}
571 
572 		return ObjectG.getDObject!(Request)(cast(SoupRequest*) __p, true);
573 	}
574 
575 	/**
576 	 * Creates a #SoupRequest for retrieving @uri_string, which must be an
577 	 * "http" or "https" URI (or another protocol listed in @session's
578 	 * #SoupSession:http-aliases or #SoupSession:https-aliases).
579 	 *
580 	 * Params:
581 	 *     method = an HTTP method
582 	 *     uriString = a URI, in string form
583 	 *
584 	 * Returns: a new #SoupRequestHTTP, or
585 	 *     %NULL on error.
586 	 *
587 	 * Since: 2.42
588 	 *
589 	 * Throws: GException on failure.
590 	 */
591 	public RequestHTTP requestHttp(string method, string uriString)
592 	{
593 		GError* err = null;
594 
595 		auto __p = soup_session_request_http(soupSession, Str.toStringz(method), Str.toStringz(uriString), &err);
596 
597 		if (err !is null)
598 		{
599 			throw new GException( new ErrorG(err) );
600 		}
601 
602 		if(__p is null)
603 		{
604 			return null;
605 		}
606 
607 		return ObjectG.getDObject!(RequestHTTP)(cast(SoupRequestHTTP*) __p, true);
608 	}
609 
610 	/**
611 	 * Creates a #SoupRequest for retrieving @uri, which must be an
612 	 * "http" or "https" URI (or another protocol listed in @session's
613 	 * #SoupSession:http-aliases or #SoupSession:https-aliases).
614 	 *
615 	 * Params:
616 	 *     method = an HTTP method
617 	 *     uri = a #SoupURI representing the URI to retrieve
618 	 *
619 	 * Returns: a new #SoupRequestHTTP, or
620 	 *     %NULL on error.
621 	 *
622 	 * Since: 2.42
623 	 *
624 	 * Throws: GException on failure.
625 	 */
626 	public RequestHTTP requestHttpUri(string method, URI uri)
627 	{
628 		GError* err = null;
629 
630 		auto __p = soup_session_request_http_uri(soupSession, Str.toStringz(method), (uri is null) ? null : uri.getURIStruct(), &err);
631 
632 		if (err !is null)
633 		{
634 			throw new GException( new ErrorG(err) );
635 		}
636 
637 		if(__p is null)
638 		{
639 			return null;
640 		}
641 
642 		return ObjectG.getDObject!(RequestHTTP)(cast(SoupRequestHTTP*) __p, true);
643 	}
644 
645 	/**
646 	 * Creates a #SoupRequest for retrieving @uri.
647 	 *
648 	 * Params:
649 	 *     uri = a #SoupURI representing the URI to retrieve
650 	 *
651 	 * Returns: a new #SoupRequest, or
652 	 *     %NULL on error.
653 	 *
654 	 * Since: 2.42
655 	 *
656 	 * Throws: GException on failure.
657 	 */
658 	public Request requestUri(URI uri)
659 	{
660 		GError* err = null;
661 
662 		auto __p = soup_session_request_uri(soupSession, (uri is null) ? null : uri.getURIStruct(), &err);
663 
664 		if (err !is null)
665 		{
666 			throw new GException( new ErrorG(err) );
667 		}
668 
669 		if(__p is null)
670 		{
671 			return null;
672 		}
673 
674 		return ObjectG.getDObject!(Request)(cast(SoupRequest*) __p, true);
675 	}
676 
677 	/**
678 	 * This causes @msg to be placed back on the queue to be attempted
679 	 * again.
680 	 *
681 	 * Params:
682 	 *     msg = the message to requeue
683 	 */
684 	public void requeueMessage(Message msg)
685 	{
686 		soup_session_requeue_message(soupSession, (msg is null) ? null : msg.getMessageStruct());
687 	}
688 
689 	/**
690 	 * Synchronously sends @msg and waits for the beginning of a response.
691 	 * On success, a #GInputStream will be returned which you can use to
692 	 * read the response body. ("Success" here means only that an HTTP
693 	 * response was received and understood; it does not necessarily mean
694 	 * that a 2xx class status code was received.)
695 	 *
696 	 * If non-%NULL, @cancellable can be used to cancel the request;
697 	 * soup_session_send() will return a %G_IO_ERROR_CANCELLED error. Note
698 	 * that with requests that have side effects (eg,
699 	 * <literal>POST</literal>, <literal>PUT</literal>,
700 	 * <literal>DELETE</literal>) it is possible that you might cancel the
701 	 * request after the server acts on it, but before it returns a
702 	 * response, leaving the remote resource in an unknown state.
703 	 *
704 	 * If @msg is requeued due to a redirect or authentication, the
705 	 * initial (3xx/401/407) response body will be suppressed, and
706 	 * soup_session_send() will only return once a final response has been
707 	 * received.
708 	 *
709 	 * Contrast this method with soup_session_send_message(), which also
710 	 * synchronously sends a #SoupMessage, but doesn't return until the
711 	 * response has been completely read.
712 	 *
713 	 * (Note that this method cannot be called on the deprecated
714 	 * #SoupSessionAsync subclass.)
715 	 *
716 	 * Params:
717 	 *     msg = a #SoupMessage
718 	 *     cancellable = a #GCancellable
719 	 *
720 	 * Returns: a #GInputStream for reading the
721 	 *     response body, or %NULL on error.
722 	 *
723 	 * Since: 2.42
724 	 *
725 	 * Throws: GException on failure.
726 	 */
727 	public InputStream send(Message msg, Cancellable cancellable)
728 	{
729 		GError* err = null;
730 
731 		auto __p = soup_session_send(soupSession, (msg is null) ? null : msg.getMessageStruct(), (cancellable is null) ? null : cancellable.getCancellableStruct(), &err);
732 
733 		if (err !is null)
734 		{
735 			throw new GException( new ErrorG(err) );
736 		}
737 
738 		if(__p is null)
739 		{
740 			return null;
741 		}
742 
743 		return ObjectG.getDObject!(InputStream)(cast(GInputStream*) __p, true);
744 	}
745 
746 	/**
747 	 * Asynchronously sends @msg and waits for the beginning of a
748 	 * response. When @callback is called, then either @msg has been sent,
749 	 * and its response headers received, or else an error has occurred.
750 	 * Call soup_session_send_finish() to get a #GInputStream for reading
751 	 * the response body.
752 	 *
753 	 * See soup_session_send() for more details on the general semantics.
754 	 *
755 	 * Contrast this method with soup_session_queue_message(), which also
756 	 * asynchronously sends a #SoupMessage, but doesn't invoke its
757 	 * callback until the response has been completely read.
758 	 *
759 	 * (Note that this method cannot be called on the deprecated
760 	 * #SoupSessionSync subclass, and can only be called on
761 	 * #SoupSessionAsync if you have set the
762 	 * #SoupSession:use-thread-context property.)
763 	 *
764 	 * Params:
765 	 *     msg = a #SoupMessage
766 	 *     cancellable = a #GCancellable
767 	 *     callback = the callback to invoke
768 	 *     userData = data for @callback
769 	 *
770 	 * Since: 2.42
771 	 */
772 	public void sendAsync(Message msg, Cancellable cancellable, GAsyncReadyCallback callback, void* userData)
773 	{
774 		soup_session_send_async(soupSession, (msg is null) ? null : msg.getMessageStruct(), (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData);
775 	}
776 
777 	/**
778 	 * Gets the response to a soup_session_send_async() call and (if
779 	 * successful), returns a #GInputStream that can be used to read the
780 	 * response body.
781 	 *
782 	 * Params:
783 	 *     result = the #GAsyncResult passed to your callback
784 	 *
785 	 * Returns: a #GInputStream for reading the
786 	 *     response body, or %NULL on error.
787 	 *
788 	 * Since: 2.42
789 	 *
790 	 * Throws: GException on failure.
791 	 */
792 	public InputStream sendFinish(AsyncResultIF result)
793 	{
794 		GError* err = null;
795 
796 		auto __p = soup_session_send_finish(soupSession, (result is null) ? null : result.getAsyncResultStruct(), &err);
797 
798 		if (err !is null)
799 		{
800 			throw new GException( new ErrorG(err) );
801 		}
802 
803 		if(__p is null)
804 		{
805 			return null;
806 		}
807 
808 		return ObjectG.getDObject!(InputStream)(cast(GInputStream*) __p, true);
809 	}
810 
811 	/**
812 	 * Synchronously send @msg. This call will not return until the
813 	 * transfer is finished successfully or there is an unrecoverable
814 	 * error.
815 	 *
816 	 * Unlike with soup_session_queue_message(), @msg is not freed upon
817 	 * return.
818 	 *
819 	 * (Note that if you call this method on a #SoupSessionAsync, it will
820 	 * still use asynchronous I/O internally, running the glib main loop
821 	 * to process the message, which may also cause other events to be
822 	 * processed.)
823 	 *
824 	 * Contrast this method with soup_session_send(), which also
825 	 * synchronously sends a message, but returns before reading the
826 	 * response body, and allows you to read the response via a
827 	 * #GInputStream.
828 	 *
829 	 * Params:
830 	 *     msg = the message to send
831 	 *
832 	 * Returns: the HTTP status code of the response
833 	 */
834 	public uint sendMessage(Message msg)
835 	{
836 		return soup_session_send_message(soupSession, (msg is null) ? null : msg.getMessageStruct());
837 	}
838 
839 	/**
840 	 * "Steals" the HTTP connection associated with @msg from @session.
841 	 * This happens immediately, regardless of the current state of the
842 	 * connection, and @msg's callback will not be called. You can steal
843 	 * the connection from a #SoupMessage signal handler if you need to
844 	 * wait for part or all of the response to be received first.
845 	 *
846 	 * Calling this function may cause @msg to be freed if you are not
847 	 * holding any other reference to it.
848 	 *
849 	 * Params:
850 	 *     msg = the message whose connection is to be stolen
851 	 *
852 	 * Returns: the #GIOStream formerly associated
853 	 *     with @msg (or %NULL if @msg was no longer associated with a
854 	 *     connection). No guarantees are made about what kind of #GIOStream
855 	 *     is returned.
856 	 *
857 	 * Since: 2.50
858 	 */
859 	public IOStream stealConnection(Message msg)
860 	{
861 		auto __p = soup_session_steal_connection(soupSession, (msg is null) ? null : msg.getMessageStruct());
862 
863 		if(__p is null)
864 		{
865 			return null;
866 		}
867 
868 		return ObjectG.getDObject!(IOStream)(cast(GIOStream*) __p, true);
869 	}
870 
871 	/**
872 	 * Resumes HTTP I/O on @msg. Use this to resume after calling
873 	 * soup_session_pause_message().
874 	 *
875 	 * If @msg is being sent via blocking I/O, this will resume reading or
876 	 * writing immediately. If @msg is using non-blocking I/O, then
877 	 * reading or writing won't resume until you return to the main loop.
878 	 *
879 	 * This may only be called for asynchronous messages (those sent on a
880 	 * #SoupSessionAsync or using soup_session_queue_message()).
881 	 *
882 	 * Params:
883 	 *     msg = a #SoupMessage currently running on @session
884 	 */
885 	public void unpauseMessage(Message msg)
886 	{
887 		soup_session_unpause_message(soupSession, (msg is null) ? null : msg.getMessageStruct());
888 	}
889 
890 	/**
891 	 * Asynchronously creates a #SoupWebsocketConnection to communicate
892 	 * with a remote server.
893 	 *
894 	 * All necessary WebSocket-related headers will be added to @msg, and
895 	 * it will then be sent and asynchronously processed normally
896 	 * (including handling of redirection and HTTP authentication).
897 	 *
898 	 * If the server returns "101 Switching Protocols", then @msg's status
899 	 * code and response headers will be updated, and then the WebSocket
900 	 * handshake will be completed. On success,
901 	 * soup_session_websocket_connect_finish() will return a new
902 	 * #SoupWebsocketConnection. On failure it will return a #GError.
903 	 *
904 	 * If the server returns a status other than "101 Switching
905 	 * Protocols", then @msg will contain the complete response headers
906 	 * and body from the server's response, and
907 	 * soup_session_websocket_connect_finish() will return
908 	 * %SOUP_WEBSOCKET_ERROR_NOT_WEBSOCKET.
909 	 *
910 	 * Params:
911 	 *     msg = #SoupMessage indicating the WebSocket server to connect to
912 	 *     origin = origin of the connection
913 	 *     protocols = a
914 	 *         %NULL-terminated array of protocols supported
915 	 *     cancellable = a #GCancellable
916 	 *     callback = the callback to invoke
917 	 *     userData = data for @callback
918 	 *
919 	 * Since: 2.50
920 	 */
921 	public void websocketConnectAsync(Message msg, string origin, string[] protocols, Cancellable cancellable, GAsyncReadyCallback callback, void* userData)
922 	{
923 		soup_session_websocket_connect_async(soupSession, (msg is null) ? null : msg.getMessageStruct(), Str.toStringz(origin), Str.toStringzArray(protocols), (cancellable is null) ? null : cancellable.getCancellableStruct(), callback, userData);
924 	}
925 
926 	/**
927 	 * Gets the #SoupWebsocketConnection response to a
928 	 * soup_session_websocket_connect_async() call and (if successful),
929 	 * returns a #SoupWebsocketConnection that can be used to communicate
930 	 * with the server.
931 	 *
932 	 * Params:
933 	 *     result = the #GAsyncResult passed to your callback
934 	 *
935 	 * Returns: a new #SoupWebsocketConnection, or
936 	 *     %NULL on error.
937 	 *
938 	 * Since: 2.50
939 	 *
940 	 * Throws: GException on failure.
941 	 */
942 	public WebsocketConnection websocketConnectFinish(AsyncResultIF result)
943 	{
944 		GError* err = null;
945 
946 		auto __p = soup_session_websocket_connect_finish(soupSession, (result is null) ? null : result.getAsyncResultStruct(), &err);
947 
948 		if (err !is null)
949 		{
950 			throw new GException( new ErrorG(err) );
951 		}
952 
953 		if(__p is null)
954 		{
955 			return null;
956 		}
957 
958 		return ObjectG.getDObject!(WebsocketConnection)(cast(SoupWebsocketConnection*) __p, true);
959 	}
960 
961 	/**
962 	 * Checks if @msg contains a response that would cause @session to
963 	 * redirect it to a new URL (ignoring @msg's %SOUP_MESSAGE_NO_REDIRECT
964 	 * flag, and the number of times it has already been redirected).
965 	 *
966 	 * Params:
967 	 *     msg = a #SoupMessage that has response headers
968 	 *
969 	 * Returns: whether @msg would be redirected
970 	 *
971 	 * Since: 2.38
972 	 */
973 	public bool wouldRedirect(Message msg)
974 	{
975 		return soup_session_would_redirect(soupSession, (msg is null) ? null : msg.getMessageStruct()) != 0;
976 	}
977 
978 	/**
979 	 * Emitted when the session requires authentication. If
980 	 * credentials are available call soup_auth_authenticate() on
981 	 * @auth. If these credentials fail, the signal will be
982 	 * emitted again, with @retrying set to %TRUE, which will
983 	 * continue until you return without calling
984 	 * soup_auth_authenticate() on @auth.
985 	 *
986 	 * Note that this may be emitted before @msg's body has been
987 	 * fully read.
988 	 *
989 	 * If you call soup_session_pause_message() on @msg before
990 	 * returning, then you can authenticate @auth asynchronously
991 	 * (as long as you g_object_ref() it to make sure it doesn't
992 	 * get destroyed), and then unpause @msg when you are ready
993 	 * for it to continue.
994 	 *
995 	 * Params:
996 	 *     msg = the #SoupMessage being sent
997 	 *     auth = the #SoupAuth to authenticate
998 	 *     retrying = %TRUE if this is the second (or later) attempt
999 	 */
1000 	gulong addOnAuthenticate(void delegate(Message, Auth, bool, Session) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1001 	{
1002 		return Signals.connect(this, "authenticate", dlg, connectFlags ^ ConnectFlags.SWAPPED);
1003 	}
1004 
1005 	/**
1006 	 * Emitted when a new connection is created. This is an
1007 	 * internal signal intended only to be used for debugging
1008 	 * purposes, and may go away in the future.
1009 	 *
1010 	 * Params:
1011 	 *     connection = the connection
1012 	 *
1013 	 * Since: 2.30
1014 	 */
1015 	gulong addOnConnectionCreated(void delegate(ObjectG, Session) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1016 	{
1017 		return Signals.connect(this, "connection-created", dlg, connectFlags ^ ConnectFlags.SWAPPED);
1018 	}
1019 
1020 	/**
1021 	 * Emitted when a request is queued on @session. (Note that
1022 	 * "queued" doesn't just mean soup_session_queue_message();
1023 	 * soup_session_send_message() implicitly queues the message
1024 	 * as well.)
1025 	 *
1026 	 * When sending a request, first #SoupSession::request_queued
1027 	 * is emitted, indicating that the session has become aware of
1028 	 * the request.
1029 	 *
1030 	 * Once a connection is available to send the request on, the
1031 	 * session emits #SoupSession::request_started. Then, various
1032 	 * #SoupMessage signals are emitted as the message is
1033 	 * processed. If the message is requeued, it will emit
1034 	 * #SoupMessage::restarted, which will then be followed by
1035 	 * another #SoupSession::request_started and another set of
1036 	 * #SoupMessage signals when the message is re-sent.
1037 	 *
1038 	 * Eventually, the message will emit #SoupMessage::finished.
1039 	 * Normally, this signals the completion of message
1040 	 * processing. However, it is possible that the application
1041 	 * will requeue the message from the "finished" handler (or
1042 	 * equivalently, from the soup_session_queue_message()
1043 	 * callback). In that case, the process will loop back to
1044 	 * #SoupSession::request_started.
1045 	 *
1046 	 * Eventually, a message will reach "finished" and not be
1047 	 * requeued. At that point, the session will emit
1048 	 * #SoupSession::request_unqueued to indicate that it is done
1049 	 * with the message.
1050 	 *
1051 	 * To sum up: #SoupSession::request_queued and
1052 	 * #SoupSession::request_unqueued are guaranteed to be emitted
1053 	 * exactly once, but #SoupSession::request_started and
1054 	 * #SoupMessage::finished (and all of the other #SoupMessage
1055 	 * signals) may be invoked multiple times for a given message.
1056 	 *
1057 	 * Params:
1058 	 *     msg = the request that was queued
1059 	 *
1060 	 * Since: 2.24
1061 	 */
1062 	gulong addOnRequestQueued(void delegate(Message, Session) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1063 	{
1064 		return Signals.connect(this, "request-queued", dlg, connectFlags ^ ConnectFlags.SWAPPED);
1065 	}
1066 
1067 	/**
1068 	 * Emitted just before a request is sent. See
1069 	 * #SoupSession::request_queued for a detailed description of
1070 	 * the message lifecycle within a session.
1071 	 *
1072 	 * Deprecated: Use #SoupMessage::starting instead.
1073 	 *
1074 	 * Params:
1075 	 *     msg = the request being sent
1076 	 *     socket = the socket the request is being sent on
1077 	 */
1078 	gulong addOnRequestStarted(void delegate(Message, Socket, Session) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1079 	{
1080 		return Signals.connect(this, "request-started", dlg, connectFlags ^ ConnectFlags.SWAPPED);
1081 	}
1082 
1083 	/**
1084 	 * Emitted when a request is removed from @session's queue,
1085 	 * indicating that @session is done with it. See
1086 	 * #SoupSession::request_queued for a detailed description of the
1087 	 * message lifecycle within a session.
1088 	 *
1089 	 * Params:
1090 	 *     msg = the request that was unqueued
1091 	 *
1092 	 * Since: 2.24
1093 	 */
1094 	gulong addOnRequestUnqueued(void delegate(Message, Session) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1095 	{
1096 		return Signals.connect(this, "request-unqueued", dlg, connectFlags ^ ConnectFlags.SWAPPED);
1097 	}
1098 
1099 	/**
1100 	 * Emitted when an SSL tunnel is being created on a proxy
1101 	 * connection. This is an internal signal intended only to be
1102 	 * used for debugging purposes, and may go away in the future.
1103 	 *
1104 	 * Params:
1105 	 *     connection = the connection
1106 	 *
1107 	 * Since: 2.30
1108 	 */
1109 	gulong addOnTunneling(void delegate(ObjectG, Session) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
1110 	{
1111 		return Signals.connect(this, "tunneling", dlg, connectFlags ^ ConnectFlags.SWAPPED);
1112 	}
1113 }