1 module soup.Logger;
2 
3 private import glib.ConstructionException;
4 private import gobject.ObjectG;
5 private import soup.Session;
6 private import soup.SessionFeatureIF;
7 private import soup.SessionFeatureT;
8 private import soup.c.functions;
9 public  import soup.c.types;
10 
11 
12 /**
13  * #SoupLogger watches a #SoupSession and logs the HTTP traffic that
14  * it generates, for debugging purposes. Many applications use an
15  * environment variable to determine whether or not to use
16  * #SoupLogger, and to determine the amount of debugging output.
17  * 
18  * To use #SoupLogger, first create a logger with soup_logger_new(),
19  * optionally configure it with soup_logger_set_request_filter(),
20  * soup_logger_set_response_filter(), and soup_logger_set_printer(),
21  * and then attach it to a session (or multiple sessions) with
22  * soup_session_add_feature().
23  * 
24  * By default, the debugging output is sent to
25  * <literal>stdout</literal>, and looks something like:
26  * 
27  * <informalexample><screen>
28  * > POST /unauth HTTP/1.1
29  * > Soup-Debug-Timestamp: 1200171744
30  * > Soup-Debug: SoupSessionAsync 1 (0x612190), SoupMessage 1 (0x617000), SoupSocket 1 (0x612220)
31  * > Host: localhost
32  * > Content-Type: text/plain
33  * > Connection: close
34  * >
35  * > This is a test.
36  * 
37  * &lt; HTTP/1.1 201 Created
38  * &lt; Soup-Debug-Timestamp: 1200171744
39  * &lt; Soup-Debug: SoupMessage 1 (0x617000)
40  * &lt; Date: Sun, 12 Jan 2008 21:02:24 GMT
41  * &lt; Content-Length: 0
42  * </screen></informalexample>
43  * 
44  * The <literal>Soup-Debug-Timestamp</literal> line gives the time (as
45  * a <type>time_t</type>) when the request was sent, or the response fully
46  * received.
47  * 
48  * The <literal>Soup-Debug</literal> line gives further debugging
49  * information about the #SoupSession, #SoupMessage, and #SoupSocket
50  * involved; the hex numbers are the addresses of the objects in
51  * question (which may be useful if you are running in a debugger).
52  * The decimal IDs are simply counters that uniquely identify objects
53  * across the lifetime of the #SoupLogger. In particular, this can be
54  * used to identify when multiple messages are sent across the same
55  * connection.
56  * 
57  * Currently, the request half of the message is logged just before
58  * the first byte of the request gets written to the network (from the
59  * #SoupMessage::starting signal), which means that if you have
60  * not made the complete request body available at that point, it will
61  * not be logged.
62  * 
63  * The response is logged just after the last byte of the response
64  * body is read from the network (from the #SoupMessage::got_body or
65  * #SoupMessage::got_informational signal), which means that the
66  * #SoupMessage::got_headers signal, and anything triggered off it
67  * (such as #SoupSession::authenticate) will be emitted
68  * <emphasis>before</emphasis> the response headers are actually
69  * logged.
70  * 
71  * If the response doesn't happen to trigger the
72  * #SoupMessage::got_body nor #SoupMessage::got_informational signals
73  * due to, for example, a cancellation before receiving the last byte
74  * of the response body, the response will still be logged on the
75  * event of the #SoupMessage::finished signal.
76  */
77 public class Logger : ObjectG, SessionFeatureIF
78 {
79 	/** the main Gtk struct */
80 	protected SoupLogger* soupLogger;
81 
82 	/** Get the main Gtk struct */
83 	public SoupLogger* getLoggerStruct(bool transferOwnership = false)
84 	{
85 		if (transferOwnership)
86 			ownedRef = false;
87 		return soupLogger;
88 	}
89 
90 	/** the main Gtk struct as a void* */
91 	protected override void* getStruct()
92 	{
93 		return cast(void*)soupLogger;
94 	}
95 
96 	/**
97 	 * Sets our main struct and passes it to the parent class.
98 	 */
99 	public this (SoupLogger* soupLogger, bool ownedRef = false)
100 	{
101 		this.soupLogger = soupLogger;
102 		super(cast(GObject*)soupLogger, ownedRef);
103 	}
104 
105 	// add the SessionFeature capabilities
106 	mixin SessionFeatureT!(SoupLogger);
107 
108 
109 	/** */
110 	public static GType getType()
111 	{
112 		return soup_logger_get_type();
113 	}
114 
115 	/**
116 	 * Creates a new #SoupLogger with the given debug level. If @level is
117 	 * %SOUP_LOGGER_LOG_BODY, @max_body_size gives the maximum number of
118 	 * bytes of the body that will be logged. (-1 means "no limit".)
119 	 *
120 	 * If you need finer control over what message parts are and aren't
121 	 * logged, use soup_logger_set_request_filter() and
122 	 * soup_logger_set_response_filter().
123 	 *
124 	 * Params:
125 	 *     level = the debug level
126 	 *     maxBodySize = the maximum body size to output, or -1
127 	 *
128 	 * Returns: a new #SoupLogger
129 	 *
130 	 * Throws: ConstructionException GTK+ fails to create the object.
131 	 */
132 	public this(SoupLoggerLogLevel level, int maxBodySize)
133 	{
134 		auto __p = soup_logger_new(level, maxBodySize);
135 
136 		if(__p is null)
137 		{
138 			throw new ConstructionException("null returned by new");
139 		}
140 
141 		this(cast(SoupLogger*) __p, true);
142 	}
143 
144 	/**
145 	 * Sets @logger to watch @session and print debug information for
146 	 * its messages.
147 	 *
148 	 * (The session will take a reference on @logger, which will be
149 	 * removed when you call soup_logger_detach(), or when the session is
150 	 * destroyed.)
151 	 *
152 	 * Deprecated: Use soup_session_add_feature() instead.
153 	 *
154 	 * Params:
155 	 *     session = a #SoupSession
156 	 */
157 	public void attach(Session session)
158 	{
159 		soup_logger_attach(soupLogger, (session is null) ? null : session.getSessionStruct());
160 	}
161 
162 	/**
163 	 * Stops @logger from watching @session.
164 	 *
165 	 * Deprecated: Use soup_session_remove_feature() instead.
166 	 *
167 	 * Params:
168 	 *     session = a #SoupSession
169 	 */
170 	public void detach(Session session)
171 	{
172 		soup_logger_detach(soupLogger, (session is null) ? null : session.getSessionStruct());
173 	}
174 
175 	/**
176 	 * Sets up an alternate log printing routine, if you don't want
177 	 * the log to go to <literal>stdout</literal>.
178 	 *
179 	 * Params:
180 	 *     printer = the callback for printing logging output
181 	 *     printerData = data to pass to the callback
182 	 *     destroy = a #GDestroyNotify to free @printer_data
183 	 */
184 	public void setPrinter(SoupLoggerPrinter printer, void* printerData, GDestroyNotify destroy)
185 	{
186 		soup_logger_set_printer(soupLogger, printer, printerData, destroy);
187 	}
188 
189 	/**
190 	 * Sets up a filter to determine the log level for a given request.
191 	 * For each HTTP request @logger will invoke @request_filter to
192 	 * determine how much (if any) of that request to log. (If you do not
193 	 * set a request filter, @logger will just always log requests at the
194 	 * level passed to soup_logger_new().)
195 	 *
196 	 * Params:
197 	 *     requestFilter = the callback for request debugging
198 	 *     filterData = data to pass to the callback
199 	 *     destroy = a #GDestroyNotify to free @filter_data
200 	 */
201 	public void setRequestFilter(SoupLoggerFilter requestFilter, void* filterData, GDestroyNotify destroy)
202 	{
203 		soup_logger_set_request_filter(soupLogger, requestFilter, filterData, destroy);
204 	}
205 
206 	/**
207 	 * Sets up a filter to determine the log level for a given response.
208 	 * For each HTTP response @logger will invoke @response_filter to
209 	 * determine how much (if any) of that response to log. (If you do not
210 	 * set a response filter, @logger will just always log responses at
211 	 * the level passed to soup_logger_new().)
212 	 *
213 	 * Params:
214 	 *     responseFilter = the callback for response debugging
215 	 *     filterData = data to pass to the callback
216 	 *     destroy = a #GDestroyNotify to free @filter_data
217 	 */
218 	public void setResponseFilter(SoupLoggerFilter responseFilter, void* filterData, GDestroyNotify destroy)
219 	{
220 		soup_logger_set_response_filter(soupLogger, responseFilter, filterData, destroy);
221 	}
222 }