1 module soup.Message;
2 
3 private import gio.IOStream;
4 private import gio.TlsCertificate;
5 private import glib.ConstructionException;
6 private import glib.HashTable;
7 private import glib.Str;
8 private import gobject.ObjectG;
9 private import gobject.Signals;
10 private import soup.Address;
11 private import soup.Buffer;
12 private import soup.Request;
13 private import soup.URI;
14 private import soup.c.functions;
15 public  import soup.c.types;
16 private import std.algorithm;
17 
18 
19 /**
20  * A #SoupMessage represents an HTTP message that is being sent or
21  * received.
22  * 
23  * For client-side usage, if you are using the traditional
24  * #SoupSession APIs (soup_session_queue_message() and
25  * soup_session_send_message()), you would create a #SoupMessage with
26  * soup_message_new() or soup_message_new_from_uri(), set up its
27  * fields appropriately, and send it. If you are using the newer
28  * #SoupRequest API, you would create a request with
29  * soup_session_request_http() or soup_session_request_http_uri(), and
30  * the returned #SoupRequestHTTP will already have an associated
31  * #SoupMessage that you can retrieve via
32  * soup_request_http_get_message().
33  * 
34  * For server-side usage, #SoupServer will create #SoupMessage<!--
35  * -->s automatically for incoming requests, which your application
36  * will receive via handlers.
37  * 
38  * Note that libsoup's terminology here does not quite match the HTTP
39  * specification: in RFC 2616, an "HTTP-message" is
40  * <emphasis>either</emphasis> a Request, <emphasis>or</emphasis> a
41  * Response. In libsoup, a #SoupMessage combines both the request and
42  * the response.
43  */
44 public class Message : ObjectG
45 {
46 	/** the main Gtk struct */
47 	protected SoupMessage* soupMessage;
48 
49 	/** Get the main Gtk struct */
50 	public SoupMessage* getMessageStruct(bool transferOwnership = false)
51 	{
52 		if (transferOwnership)
53 			ownedRef = false;
54 		return soupMessage;
55 	}
56 
57 	/** the main Gtk struct as a void* */
58 	protected override void* getStruct()
59 	{
60 		return cast(void*)soupMessage;
61 	}
62 
63 	/**
64 	 * Sets our main struct and passes it to the parent class.
65 	 */
66 	public this (SoupMessage* soupMessage, bool ownedRef = false)
67 	{
68 		this.soupMessage = soupMessage;
69 		super(cast(GObject*)soupMessage, ownedRef);
70 	}
71 
72 
73 	/** */
74 	public static GType getType()
75 	{
76 		return soup_message_get_type();
77 	}
78 
79 	/**
80 	 * Creates a new empty #SoupMessage, which will connect to @uri
81 	 *
82 	 * Params:
83 	 *     method = the HTTP method for the created request
84 	 *     uriString = the destination endpoint (as a string)
85 	 *
86 	 * Returns: the new #SoupMessage (or %NULL if @uri
87 	 *     could not be parsed).
88 	 *
89 	 * Throws: ConstructionException GTK+ fails to create the object.
90 	 */
91 	public this(string method, string uriString)
92 	{
93 		auto __p = soup_message_new(Str.toStringz(method), Str.toStringz(uriString));
94 
95 		if(__p is null)
96 		{
97 			throw new ConstructionException("null returned by new");
98 		}
99 
100 		this(cast(SoupMessage*) __p, true);
101 	}
102 
103 	/**
104 	 * Creates a new empty #SoupMessage, which will connect to @uri
105 	 *
106 	 * Params:
107 	 *     method = the HTTP method for the created request
108 	 *     uri = the destination endpoint (as a #SoupURI)
109 	 *
110 	 * Returns: the new #SoupMessage
111 	 *
112 	 * Throws: ConstructionException GTK+ fails to create the object.
113 	 */
114 	public this(string method, URI uri)
115 	{
116 		auto __p = soup_message_new_from_uri(Str.toStringz(method), (uri is null) ? null : uri.getURIStruct());
117 
118 		if(__p is null)
119 		{
120 			throw new ConstructionException("null returned by new_from_uri");
121 		}
122 
123 		this(cast(SoupMessage*) __p, true);
124 	}
125 
126 	/**
127 	 * Adds a signal handler to @msg for @signal, as with
128 	 * g_signal_connect(), but the @callback will only be run if @msg's
129 	 * incoming messages headers (that is, the
130 	 * <literal>request_headers</literal> for a client #SoupMessage, or
131 	 * the <literal>response_headers</literal> for a server #SoupMessage)
132 	 * contain a header named @header.
133 	 *
134 	 * Params:
135 	 *     signal = signal to connect the handler to.
136 	 *     header = HTTP response header to match against
137 	 *     callback = the header handler
138 	 *     userData = data to pass to @handler_cb
139 	 *
140 	 * Returns: the handler ID from g_signal_connect()
141 	 */
142 	public uint addHeaderHandler(string signal, string header, GCallback callback, void* userData)
143 	{
144 		return soup_message_add_header_handler(soupMessage, Str.toStringz(signal), Str.toStringz(header), callback, userData);
145 	}
146 
147 	/**
148 	 * Adds a signal handler to @msg for @signal, as with
149 	 * g_signal_connect(), but the @callback will only be run if @msg has
150 	 * the status @status_code.
151 	 *
152 	 * @signal must be a signal that will be emitted after @msg's status
153 	 * is set. For a client #SoupMessage, this means it can't be a "wrote"
154 	 * signal. For a server #SoupMessage, this means it can't be a "got"
155 	 * signal.
156 	 *
157 	 * Params:
158 	 *     signal = signal to connect the handler to.
159 	 *     statusCode = status code to match against
160 	 *     callback = the header handler
161 	 *     userData = data to pass to @handler_cb
162 	 *
163 	 * Returns: the handler ID from g_signal_connect()
164 	 */
165 	public uint addStatusCodeHandler(string signal, uint statusCode, GCallback callback, void* userData)
166 	{
167 		return soup_message_add_status_code_handler(soupMessage, Str.toStringz(signal), statusCode, callback, userData);
168 	}
169 
170 	/** */
171 	public void contentSniffed(string contentType, HashTable params)
172 	{
173 		soup_message_content_sniffed(soupMessage, Str.toStringz(contentType), (params is null) ? null : params.getHashTableStruct());
174 	}
175 
176 	/**
177 	 * This disables the actions of #SoupSessionFeature<!-- -->s with the
178 	 * given @feature_type (or a subclass of that type) on @msg, so that
179 	 * @msg is processed as though the feature(s) hadn't been added to the
180 	 * session. Eg, passing #SOUP_TYPE_CONTENT_SNIFFER for @feature_type
181 	 * will disable Content-Type sniffing on the message.
182 	 *
183 	 * You must call this before queueing @msg on a session; calling it on
184 	 * a message that has already been queued is undefined. In particular,
185 	 * you cannot call this on a message that is being requeued after a
186 	 * redirect or authentication.
187 	 *
188 	 * Params:
189 	 *     featureType = the #GType of a #SoupSessionFeature
190 	 *
191 	 * Since: 2.28
192 	 */
193 	public void disableFeature(GType featureType)
194 	{
195 		soup_message_disable_feature(soupMessage, featureType);
196 	}
197 
198 	/** */
199 	public void finished()
200 	{
201 		soup_message_finished(soupMessage);
202 	}
203 
204 	/**
205 	 * Gets the address @msg's URI points to. After first setting the
206 	 * URI on a message, this will be unresolved, although the message's
207 	 * session will resolve it before sending the message.
208 	 *
209 	 * Returns: the address @msg's URI points to
210 	 *
211 	 * Since: 2.26
212 	 */
213 	public Address getAddress()
214 	{
215 		auto __p = soup_message_get_address(soupMessage);
216 
217 		if(__p is null)
218 		{
219 			return null;
220 		}
221 
222 		return ObjectG.getDObject!(Address)(cast(SoupAddress*) __p);
223 	}
224 
225 	/**
226 	 * Gets @msg's first-party #SoupURI
227 	 *
228 	 * Returns: the @msg's first party #SoupURI
229 	 *
230 	 * Since: 2.30
231 	 */
232 	public URI getFirstParty()
233 	{
234 		auto __p = soup_message_get_first_party(soupMessage);
235 
236 		if(__p is null)
237 		{
238 			return null;
239 		}
240 
241 		return ObjectG.getDObject!(URI)(cast(SoupURI*) __p);
242 	}
243 
244 	/**
245 	 * Gets the flags on @msg
246 	 *
247 	 * Returns: the flags
248 	 */
249 	public SoupMessageFlags getFlags()
250 	{
251 		return soup_message_get_flags(soupMessage);
252 	}
253 
254 	/**
255 	 * Gets the HTTP version of @msg. This is the minimum of the
256 	 * version from the request and the version from the response.
257 	 *
258 	 * Returns: the HTTP version
259 	 */
260 	public SoupHTTPVersion getHttpVersion()
261 	{
262 		return soup_message_get_http_version(soupMessage);
263 	}
264 
265 	/**
266 	 * If @msg is using https (or attempted to use https but got
267 	 * %SOUP_STATUS_SSL_FAILED), this retrieves the #GTlsCertificate
268 	 * associated with its connection, and the #GTlsCertificateFlags
269 	 * showing what problems, if any, have been found with that
270 	 * certificate.
271 	 *
272 	 * <note><para>This is only meaningful with messages processed by a #SoupSession and is
273 	 * not useful for messages received by a #SoupServer</para></note>
274 	 *
275 	 * Params:
276 	 *     certificate = @msg's TLS certificate
277 	 *     errors = the verification status of @certificate
278 	 *
279 	 * Returns: %TRUE if @msg used/attempted https, %FALSE if not
280 	 *
281 	 * Since: 2.34
282 	 */
283 	public bool getHttpsStatus(out TlsCertificate certificate, out GTlsCertificateFlags errors)
284 	{
285 		GTlsCertificate* outcertificate = null;
286 
287 		auto __p = soup_message_get_https_status(soupMessage, &outcertificate, &errors) != 0;
288 
289 		certificate = ObjectG.getDObject!(TlsCertificate)(outcertificate);
290 
291 		return __p;
292 	}
293 
294 	/** */
295 	public bool getIsTopLevelNavigation()
296 	{
297 		return soup_message_get_is_top_level_navigation(soupMessage) != 0;
298 	}
299 
300 	/**
301 	 * Retrieves the #SoupMessagePriority. If not set this value defaults
302 	 * to #SOUP_MESSAGE_PRIORITY_NORMAL.
303 	 *
304 	 * Returns: the priority of the message.
305 	 *
306 	 * Since: 2.44
307 	 */
308 	public SoupMessagePriority getPriority()
309 	{
310 		return soup_message_get_priority(soupMessage);
311 	}
312 
313 	/**
314 	 * Gets @msg's site for cookies #SoupURI
315 	 *
316 	 * Returns: the @msg's site for cookies #SoupURI
317 	 *
318 	 * Since: 2.70
319 	 */
320 	public URI getSiteForCookies()
321 	{
322 		auto __p = soup_message_get_site_for_cookies(soupMessage);
323 
324 		if(__p is null)
325 		{
326 			return null;
327 		}
328 
329 		return ObjectG.getDObject!(URI)(cast(SoupURI*) __p);
330 	}
331 
332 	/**
333 	 * If @msg is associated with a #SoupRequest, this returns that
334 	 * request. Otherwise it returns %NULL.
335 	 *
336 	 * Returns: @msg's associated #SoupRequest
337 	 *
338 	 * Since: 2.42
339 	 */
340 	public Request getSoupRequest()
341 	{
342 		auto __p = soup_message_get_soup_request(soupMessage);
343 
344 		if(__p is null)
345 		{
346 			return null;
347 		}
348 
349 		return ObjectG.getDObject!(Request)(cast(SoupRequest*) __p);
350 	}
351 
352 	/**
353 	 * Gets @msg's URI
354 	 *
355 	 * Returns: the URI @msg is targeted for.
356 	 */
357 	public URI getUri()
358 	{
359 		auto __p = soup_message_get_uri(soupMessage);
360 
361 		if(__p is null)
362 		{
363 			return null;
364 		}
365 
366 		return ObjectG.getDObject!(URI)(cast(SoupURI*) __p);
367 	}
368 
369 	/** */
370 	public void gotBody()
371 	{
372 		soup_message_got_body(soupMessage);
373 	}
374 
375 	/** */
376 	public void gotChunk(Buffer chunk)
377 	{
378 		soup_message_got_chunk(soupMessage, (chunk is null) ? null : chunk.getBufferStruct());
379 	}
380 
381 	/** */
382 	public void gotHeaders()
383 	{
384 		soup_message_got_headers(soupMessage);
385 	}
386 
387 	/** */
388 	public void gotInformational()
389 	{
390 		soup_message_got_informational(soupMessage);
391 	}
392 
393 	/**
394 	 * Get whether #SoupSessionFeature<!-- -->s of the given @feature_type
395 	 * (or a subclass of that type) are disabled on @msg.
396 	 * See soup_message_disable_feature().
397 	 *
398 	 * Params:
399 	 *     featureType = the #GType of a #SoupSessionFeature
400 	 *
401 	 * Returns: %TRUE if feature is disabled, or %FALSE otherwise.
402 	 *
403 	 * Since: 2.72
404 	 */
405 	public bool isFeatureDisabled(GType featureType)
406 	{
407 		return soup_message_is_feature_disabled(soupMessage, featureType) != 0;
408 	}
409 
410 	/**
411 	 * Determines whether or not @msg's connection can be kept alive for
412 	 * further requests after processing @msg, based on the HTTP version,
413 	 * Connection header, etc.
414 	 *
415 	 * Returns: %TRUE or %FALSE.
416 	 */
417 	public bool isKeepalive()
418 	{
419 		return soup_message_is_keepalive(soupMessage) != 0;
420 	}
421 
422 	/** */
423 	public void restarted()
424 	{
425 		soup_message_restarted(soupMessage);
426 	}
427 
428 	/**
429 	 * Sets an alternate chunk-allocation function to use when reading
430 	 * @msg's body when using the traditional (ie,
431 	 * non-#SoupRequest<!-- -->-based) API. Every time data is available
432 	 * to read, libsoup will call @allocator, which should return a
433 	 * #SoupBuffer. (See #SoupChunkAllocator for additional details.)
434 	 * Libsoup will then read data from the network into that buffer, and
435 	 * update the buffer's <literal>length</literal> to indicate how much
436 	 * data it read.
437 	 *
438 	 * Generally, a custom chunk allocator would be used in conjunction
439 	 * with soup_message_body_set_accumulate() %FALSE and
440 	 * #SoupMessage::got_chunk, as part of a strategy to avoid unnecessary
441 	 * copying of data. However, you cannot assume that every call to the
442 	 * allocator will be followed by a call to your
443 	 * #SoupMessage::got_chunk handler; if an I/O error occurs, then the
444 	 * buffer will be unreffed without ever having been used. If your
445 	 * buffer-allocation strategy requires special cleanup, use
446 	 * soup_buffer_new_with_owner() rather than doing the cleanup from the
447 	 * #SoupMessage::got_chunk handler.
448 	 *
449 	 * The other thing to remember when using non-accumulating message
450 	 * bodies is that the buffer passed to the #SoupMessage::got_chunk
451 	 * handler will be unreffed after the handler returns, just as it
452 	 * would be in the non-custom-allocated case. If you want to hand the
453 	 * chunk data off to some other part of your program to use later,
454 	 * you'll need to ref the #SoupBuffer (or its owner, in the
455 	 * soup_buffer_new_with_owner() case) to ensure that the data remains
456 	 * valid.
457 	 *
458 	 * Deprecated: #SoupRequest provides a much simpler API that lets you
459 	 * read the response directly into your own buffers without needing to
460 	 * mess with callbacks, pausing/unpausing, etc.
461 	 *
462 	 * Params:
463 	 *     allocator = the chunk allocator callback
464 	 *     userData = data to pass to @allocator
465 	 *     destroyNotify = destroy notifier to free @user_data when @msg is
466 	 *         destroyed
467 	 */
468 	public void setChunkAllocator(SoupChunkAllocator allocator, void* userData, GDestroyNotify destroyNotify)
469 	{
470 		soup_message_set_chunk_allocator(soupMessage, allocator, userData, destroyNotify);
471 	}
472 
473 	/**
474 	 * Sets @first_party as the main document #SoupURI for @msg. For
475 	 * details of when and how this is used refer to the documentation for
476 	 * #SoupCookieJarAcceptPolicy.
477 	 *
478 	 * Params:
479 	 *     firstParty = the #SoupURI for the @msg's first party
480 	 *
481 	 * Since: 2.30
482 	 */
483 	public void setFirstParty(URI firstParty)
484 	{
485 		soup_message_set_first_party(soupMessage, (firstParty is null) ? null : firstParty.getURIStruct());
486 	}
487 
488 	/**
489 	 * Sets the specified flags on @msg.
490 	 *
491 	 * Params:
492 	 *     flags = a set of #SoupMessageFlags values
493 	 */
494 	public void setFlags(SoupMessageFlags flags)
495 	{
496 		soup_message_set_flags(soupMessage, flags);
497 	}
498 
499 	/**
500 	 * Sets the HTTP version on @msg. The default version is
501 	 * %SOUP_HTTP_1_1. Setting it to %SOUP_HTTP_1_0 will prevent certain
502 	 * functionality from being used.
503 	 *
504 	 * Params:
505 	 *     version_ = the HTTP version
506 	 */
507 	public void setHttpVersion(SoupHTTPVersion version_)
508 	{
509 		soup_message_set_http_version(soupMessage, version_);
510 	}
511 
512 	/**
513 	 * See the [same-site spec](https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00)
514 	 * for more information.
515 	 *
516 	 * Params:
517 	 *     isTopLevelNavigation = if %TRUE indicate the current request is a top-level navigation
518 	 *
519 	 * Since: 2.70
520 	 */
521 	public void setIsTopLevelNavigation(bool isTopLevelNavigation)
522 	{
523 		soup_message_set_is_top_level_navigation(soupMessage, isTopLevelNavigation);
524 	}
525 
526 	/**
527 	 * Sets the priority of a message. Note that this won't have any
528 	 * effect unless used before the message is added to the session's
529 	 * message processing queue.
530 	 *
531 	 * The message will be placed just before any other previously added
532 	 * message with lower priority (messages with the same priority are
533 	 * processed on a FIFO basis).
534 	 *
535 	 * Setting priorities does not currently work with #SoupSessionSync
536 	 * (or with synchronous messages on a plain #SoupSession) because in
537 	 * the synchronous/blocking case, priority ends up being determined
538 	 * semi-randomly by thread scheduling.
539 	 *
540 	 * Params:
541 	 *     priority = the #SoupMessagePriority
542 	 *
543 	 * Since: 2.44
544 	 */
545 	public void setPriority(SoupMessagePriority priority)
546 	{
547 		soup_message_set_priority(soupMessage, priority);
548 	}
549 
550 	/**
551 	 * Sets @msg's status_code to @status_code and adds a Location header
552 	 * pointing to @redirect_uri. Use this from a #SoupServer when you
553 	 * want to redirect the client to another URI.
554 	 *
555 	 * @redirect_uri can be a relative URI, in which case it is
556 	 * interpreted relative to @msg's current URI. In particular, if
557 	 * @redirect_uri is just a path, it will replace the path
558 	 * <emphasis>and query</emphasis> of @msg's URI.
559 	 *
560 	 * Params:
561 	 *     statusCode = a 3xx status code
562 	 *     redirectUri = the URI to redirect @msg to
563 	 *
564 	 * Since: 2.38
565 	 */
566 	public void setRedirect(uint statusCode, string redirectUri)
567 	{
568 		soup_message_set_redirect(soupMessage, statusCode, Str.toStringz(redirectUri));
569 	}
570 
571 	/**
572 	 * Convenience function to set the request body of a #SoupMessage. If
573 	 * @content_type is %NULL, the request body must be empty as well.
574 	 *
575 	 * Params:
576 	 *     contentType = MIME Content-Type of the body
577 	 *     reqUse = a #SoupMemoryUse describing how to handle @req_body
578 	 *     reqBody = a data buffer containing the body of the message request.
579 	 */
580 	public void setRequest(string contentType, SoupMemoryUse reqUse, string reqBody)
581 	{
582 		soup_message_set_request(soupMessage, Str.toStringz(contentType), reqUse, Str.toStringz(reqBody), cast(size_t)reqBody.length);
583 	}
584 
585 	/**
586 	 * Convenience function to set the response body of a #SoupMessage. If
587 	 * @content_type is %NULL, the response body must be empty as well.
588 	 *
589 	 * Params:
590 	 *     contentType = MIME Content-Type of the body
591 	 *     respUse = a #SoupMemoryUse describing how to handle @resp_body
592 	 *     respBody = a data buffer containing the body of the message response.
593 	 */
594 	public void setResponse(string contentType, SoupMemoryUse respUse, string respBody)
595 	{
596 		soup_message_set_response(soupMessage, Str.toStringz(contentType), respUse, Str.toStringz(respBody), cast(size_t)respBody.length);
597 	}
598 
599 	/**
600 	 * Sets @site_for_cookies as the policy URL for same-site cookies for @msg.
601 	 *
602 	 * It is either the URL of the top-level document or %NULL depending on whether the registrable
603 	 * domain of this document's URL matches the registrable domain of its parent's/opener's
604 	 * URL. For the top-level document it is set to the document's URL.
605 	 *
606 	 * See the [same-site spec](https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00)
607 	 * for more information.
608 	 *
609 	 * Params:
610 	 *     siteForCookies = the #SoupURI for the @msg's site for cookies
611 	 *
612 	 * Since: 2.70
613 	 */
614 	public void setSiteForCookies(URI siteForCookies)
615 	{
616 		soup_message_set_site_for_cookies(soupMessage, (siteForCookies is null) ? null : siteForCookies.getURIStruct());
617 	}
618 
619 	/**
620 	 * Sets @msg's status code to @status_code. If @status_code is a
621 	 * known value, it will also set @msg's reason_phrase.
622 	 *
623 	 * Params:
624 	 *     statusCode = an HTTP status code
625 	 */
626 	public void setStatus(uint statusCode)
627 	{
628 		soup_message_set_status(soupMessage, statusCode);
629 	}
630 
631 	/**
632 	 * Sets @msg's status code and reason phrase.
633 	 *
634 	 * Params:
635 	 *     statusCode = an HTTP status code
636 	 *     reasonPhrase = a description of the status
637 	 */
638 	public void setStatusFull(uint statusCode, string reasonPhrase)
639 	{
640 		soup_message_set_status_full(soupMessage, statusCode, Str.toStringz(reasonPhrase));
641 	}
642 
643 	/**
644 	 * Sets @msg's URI to @uri. If @msg has already been sent and you want
645 	 * to re-send it with the new URI, you need to call
646 	 * soup_session_requeue_message().
647 	 *
648 	 * Params:
649 	 *     uri = the new #SoupURI
650 	 */
651 	public void setUri(URI uri)
652 	{
653 		soup_message_set_uri(soupMessage, (uri is null) ? null : uri.getURIStruct());
654 	}
655 
656 	/** */
657 	public void starting()
658 	{
659 		soup_message_starting(soupMessage);
660 	}
661 
662 	/** */
663 	public void wroteBody()
664 	{
665 		soup_message_wrote_body(soupMessage);
666 	}
667 
668 	/** */
669 	public void wroteBodyData(Buffer chunk)
670 	{
671 		soup_message_wrote_body_data(soupMessage, (chunk is null) ? null : chunk.getBufferStruct());
672 	}
673 
674 	/** */
675 	public void wroteChunk()
676 	{
677 		soup_message_wrote_chunk(soupMessage);
678 	}
679 
680 	/** */
681 	public void wroteHeaders()
682 	{
683 		soup_message_wrote_headers(soupMessage);
684 	}
685 
686 	/** */
687 	public void wroteInformational()
688 	{
689 		soup_message_wrote_informational(soupMessage);
690 	}
691 
692 	/**
693 	 * This signal is emitted after #SoupMessage::got-headers, and
694 	 * before the first #SoupMessage::got-chunk. If content
695 	 * sniffing is disabled, or no content sniffing will be
696 	 * performed, due to the sniffer deciding to trust the
697 	 * Content-Type sent by the server, this signal is emitted
698 	 * immediately after #SoupMessage::got-headers, and @type is
699 	 * %NULL.
700 	 *
701 	 * If the #SoupContentSniffer feature is enabled, and the
702 	 * sniffer decided to perform sniffing, the first
703 	 * #SoupMessage::got-chunk emission may be delayed, so that the
704 	 * sniffer has enough data to correctly sniff the content. It
705 	 * notified the library user that the content has been
706 	 * sniffed, and allows it to change the header contents in the
707 	 * message, if desired.
708 	 *
709 	 * After this signal is emitted, the data that was spooled so
710 	 * that sniffing could be done is delivered on the first
711 	 * emission of #SoupMessage::got-chunk.
712 	 *
713 	 * Params:
714 	 *     type = the content type that we got from sniffing
715 	 *     params = a #GHashTable with the parameters
716 	 *
717 	 * Since: 2.28
718 	 */
719 	gulong addOnContentSniffed(void delegate(string, HashTable, Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
720 	{
721 		return Signals.connect(this, "content-sniffed", dlg, connectFlags ^ ConnectFlags.SWAPPED);
722 	}
723 
724 	/**
725 	 * Emitted when all HTTP processing is finished for a message.
726 	 * (After #SoupMessage::got_body for client-side messages, or
727 	 * after #SoupMessage::wrote_body for server-side messages.)
728 	 */
729 	gulong addOnFinished(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
730 	{
731 		return Signals.connect(this, "finished", dlg, connectFlags ^ ConnectFlags.SWAPPED);
732 	}
733 
734 	/**
735 	 * Emitted after receiving the complete message body. (For a
736 	 * server-side message, this means it has received the request
737 	 * body. For a client-side message, this means it has received
738 	 * the response body and is nearly done with the message.)
739 	 *
740 	 * See also soup_message_add_header_handler() and
741 	 * soup_message_add_status_code_handler(), which can be used
742 	 * to connect to a subset of emissions of this signal.
743 	 */
744 	gulong addOnGotBody(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
745 	{
746 		return Signals.connect(this, "got-body", dlg, connectFlags ^ ConnectFlags.SWAPPED);
747 	}
748 
749 	/**
750 	 * Emitted after receiving a chunk of a message body. Note
751 	 * that "chunk" in this context means any subpiece of the
752 	 * body, not necessarily the specific HTTP 1.1 chunks sent by
753 	 * the other side.
754 	 *
755 	 * If you cancel or requeue @msg while processing this signal,
756 	 * then the current HTTP I/O will be stopped after this signal
757 	 * emission finished, and @msg's connection will be closed.
758 	 *
759 	 * Params:
760 	 *     chunk = the just-read chunk
761 	 */
762 	gulong addOnGotChunk(void delegate(Buffer, Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
763 	{
764 		return Signals.connect(this, "got-chunk", dlg, connectFlags ^ ConnectFlags.SWAPPED);
765 	}
766 
767 	/**
768 	 * Emitted after receiving all message headers for a message.
769 	 * (For a client-side message, this is after receiving the
770 	 * Status-Line and response headers; for a server-side
771 	 * message, it is after receiving the Request-Line and request
772 	 * headers.)
773 	 *
774 	 * See also soup_message_add_header_handler() and
775 	 * soup_message_add_status_code_handler(), which can be used
776 	 * to connect to a subset of emissions of this signal.
777 	 *
778 	 * If you cancel or requeue @msg while processing this signal,
779 	 * then the current HTTP I/O will be stopped after this signal
780 	 * emission finished, and @msg's connection will be closed.
781 	 * (If you need to requeue a message--eg, after handling
782 	 * authentication or redirection--it is usually better to
783 	 * requeue it from a #SoupMessage::got_body handler rather
784 	 * than a #SoupMessage::got_headers handler, so that the
785 	 * existing HTTP connection can be reused.)
786 	 */
787 	gulong addOnGotHeaders(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
788 	{
789 		return Signals.connect(this, "got-headers", dlg, connectFlags ^ ConnectFlags.SWAPPED);
790 	}
791 
792 	/**
793 	 * Emitted after receiving a 1xx (Informational) response for
794 	 * a (client-side) message. The response_headers will be
795 	 * filled in with the headers associated with the
796 	 * informational response; however, those header values will
797 	 * be erased after this signal is done.
798 	 *
799 	 * If you cancel or requeue @msg while processing this signal,
800 	 * then the current HTTP I/O will be stopped after this signal
801 	 * emission finished, and @msg's connection will be closed.
802 	 */
803 	gulong addOnGotInformational(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
804 	{
805 		return Signals.connect(this, "got-informational", dlg, connectFlags ^ ConnectFlags.SWAPPED);
806 	}
807 
808 	/**
809 	 * Emitted to indicate that some network-related event
810 	 * related to @msg has occurred. This essentially proxies the
811 	 * #GSocketClient::event signal, but only for events that
812 	 * occur while @msg "owns" the connection; if @msg is sent on
813 	 * an existing persistent connection, then this signal will
814 	 * not be emitted. (If you want to force the message to be
815 	 * sent on a new connection, set the
816 	 * %SOUP_MESSAGE_NEW_CONNECTION flag on it.)
817 	 *
818 	 * See #GSocketClient::event for more information on what
819 	 * the different values of @event correspond to, and what
820 	 * @connection will be in each case.
821 	 *
822 	 * Params:
823 	 *     event = the network event
824 	 *     connection = the current state of the network connection
825 	 *
826 	 * Since: 2.38
827 	 */
828 	gulong addOnNetwork(void delegate(GSocketClientEvent, IOStream, Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
829 	{
830 		return Signals.connect(this, "network-event", dlg, connectFlags ^ ConnectFlags.SWAPPED);
831 	}
832 
833 	/**
834 	 * Emitted when a request that was already sent once is now
835 	 * being sent again (eg, because the first attempt received a
836 	 * redirection response, or because we needed to use
837 	 * authentication).
838 	 */
839 	gulong addOnRestarted(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
840 	{
841 		return Signals.connect(this, "restarted", dlg, connectFlags ^ ConnectFlags.SWAPPED);
842 	}
843 
844 	/**
845 	 * Emitted just before a message is sent.
846 	 *
847 	 * Since: 2.50
848 	 */
849 	gulong addOnStarting(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
850 	{
851 		return Signals.connect(this, "starting", dlg, connectFlags ^ ConnectFlags.SWAPPED);
852 	}
853 
854 	/**
855 	 * Emitted immediately after writing the complete body for a
856 	 * message. (For a client-side message, this means that
857 	 * libsoup is done writing and is now waiting for the response
858 	 * from the server. For a server-side message, this means that
859 	 * libsoup has finished writing the response and is nearly
860 	 * done with the message.)
861 	 */
862 	gulong addOnWroteBody(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
863 	{
864 		return Signals.connect(this, "wrote-body", dlg, connectFlags ^ ConnectFlags.SWAPPED);
865 	}
866 
867 	/**
868 	 * Emitted immediately after writing a portion of the message
869 	 * body to the network.
870 	 *
871 	 * Unlike #SoupMessage::wrote_chunk, this is emitted after
872 	 * every successful write() call, not only after finishing a
873 	 * complete "chunk".
874 	 *
875 	 * Params:
876 	 *     chunk = the data written
877 	 *
878 	 * Since: 2.24
879 	 */
880 	gulong addOnWroteBodyData(void delegate(Buffer, Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
881 	{
882 		return Signals.connect(this, "wrote-body-data", dlg, connectFlags ^ ConnectFlags.SWAPPED);
883 	}
884 
885 	/**
886 	 * Emitted immediately after writing a body chunk for a message.
887 	 *
888 	 * Note that this signal is not parallel to
889 	 * #SoupMessage::got_chunk; it is emitted only when a complete
890 	 * chunk (added with soup_message_body_append() or
891 	 * soup_message_body_append_buffer()) has been written. To get
892 	 * more useful continuous progress information, use
893 	 * #SoupMessage::wrote_body_data.
894 	 */
895 	gulong addOnWroteChunk(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
896 	{
897 		return Signals.connect(this, "wrote-chunk", dlg, connectFlags ^ ConnectFlags.SWAPPED);
898 	}
899 
900 	/**
901 	 * Emitted immediately after writing the headers for a
902 	 * message. (For a client-side message, this is after writing
903 	 * the request headers; for a server-side message, it is after
904 	 * writing the response headers.)
905 	 */
906 	gulong addOnWroteHeaders(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
907 	{
908 		return Signals.connect(this, "wrote-headers", dlg, connectFlags ^ ConnectFlags.SWAPPED);
909 	}
910 
911 	/**
912 	 * Emitted immediately after writing a 1xx (Informational)
913 	 * response for a (server-side) message.
914 	 */
915 	gulong addOnWroteInformational(void delegate(Message) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
916 	{
917 		return Signals.connect(this, "wrote-informational", dlg, connectFlags ^ ConnectFlags.SWAPPED);
918 	}
919 }