Please note that active projects have migrated to https://github.com/fawkesrobotics.

libwebview: remove duplicate function after merge
[fawkes.git] / src / libs / webview / reply.cpp
1
2 /***************************************************************************
3  *  reply.cpp - Web request reply
4  *
5  *  Created: Thu Oct 23 12:01:05 2008
6  *  Copyright  2006-2009  Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9
10 /*  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU Library General Public License for more details.
19  *
20  *  Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22
23 #include <webview/reply.h>
24
25 #include <core/exception.h>
26 #include <cstdlib>
27 #include <cstdarg>
28 #include <cstdio>
29
30 namespace fawkes {
31 #if 0 /* just to make Emacs auto-indent happy */
32 }
33 #endif
34
35 /** Disable caching on a reply.
36  * This is a convenience wrapper to reply->set_caching(false). It enables
37  * the following call styles:
38  * @code
39  * return no_caching(new StaticWebReply(Reply::HTTP_NOT_FOUND, "Not Found"));
40  *
41  * return no_caching(some_handler());
42  * @endcode
43  * This works on any reply without always patching a boolean flag into
44  * the ctor and without first storing the pointer, calling the function,
45  * and then returning.
46  * @param reply reply to disable caching for
47  * @return this
48  */
49 WebReply *
50 no_caching(WebReply *reply)
51 {
52         reply->set_caching(false);
53         return reply;
54 }
55
56
57 /** @class WebReply <webview/reply.h>
58  * Basic web reply.
59  * The base class for all web replies. Though the WebRequestDispatcher expects
60  * sub-classes of StaticWebReply or DynamicWebReply.
61  * @author Tim Niemueller
62  */
63
64 /// Enable caching for this reply?
65 bool WebReply::caching_default_ = true;
66
67 /** Constructor.
68  * @param code HTTP response code
69  */
70 WebReply::WebReply(Code code)
71 {
72   code_ = code;
73   request_ = NULL;
74
75   caching_ = caching_default_;
76 }
77
78
79 /** Destructor. */
80 WebReply::~WebReply()
81 {
82 }
83
84
85 /** Enable or disable caching default for replies.
86  * This static setting controls whether following replies will allow
87  * for client-side of the web pages or not by default. Disabling this
88  * allows to force clients to always reload the pages.
89  * @param caching true to enable client-side caching, false to disable
90  */
91 void
92 WebReply::set_caching_default(bool caching)
93 {
94   caching_default_ = caching;
95 }
96
97 /** Enable or disable caching for this specific reply.
98  * @param caching true to enable client-side caching, false to disable
99  */
100 void
101 WebReply::set_caching(bool caching)
102 {
103   caching_ = caching;
104 }
105
106
107 /** Get response code.
108  * @return HTTP response code
109  */
110 WebReply::Code
111 WebReply::code() const
112 {
113   return code_;
114 }
115
116 /** Set response code.
117  * @param code HTTP response code
118  */
119 void
120 WebReply::set_code(WebReply::Code code)
121 {
122         code_ = code;
123 }
124
125 /** Add a HTTP header.
126  * @param header header entry name
127  * @param content content of the header field
128  */
129 void
130 WebReply::add_header(const std::string& header, const std::string& content)
131 {
132   headers_[header] = content;
133 }
134
135
136 /** Add a HTTP header.
137  * @param header_string header string of the format "Key: Value".
138  */
139 void
140 WebReply::add_header(const std::string& header_string)
141 {
142   std::string::size_type pos;
143   if ((pos = header_string.find(":")) != std::string::npos) {
144     std::string header = header_string.substr(0, pos);
145     std::string content;
146     if (header_string[pos+1] == ' ') {
147       content = header_string.substr(pos+2);
148     } else {
149       content = header_string.substr(pos+1);
150     }
151     headers_[header] = content;
152   } else {
153     throw Exception("Invalid header '%s'", header_string.c_str());
154   }
155 }
156
157
158 /** get headers.
159  * @return map of header name/content pairs.
160  */
161 const WebReply::HeaderMap &
162 WebReply::headers() const
163 {
164   return headers_;
165 }
166
167
168 /** Get associated request.
169  * This is only valid after set_request() has been called.
170  * @return associated web request
171  */
172 WebRequest *
173 WebReply::get_request() const
174 {
175   return request_;
176 }
177
178
179 /** Set associated request.
180  * @param request associated request
181  */
182 void
183 WebReply::set_request(WebRequest *request)
184 {
185   request_ = request;
186 }
187
188 /** Called just before the reply is sent.
189  * Sets no-caching flags if caching has been disabled. 
190  */
191 void
192 WebReply::pack_caching()
193 {
194   if (! caching_) {
195     // Headers to disable caching
196     headers_["Cache-Control"] = "no-cache, no-store, must-revalidate, max-age=0";
197   }
198 }
199
200 /** @class DynamicWebReply <webview/reply.h>
201  * Dynamic web reply.
202  * A reply of this type is send out in chunks, not all as a whole. It should be
203  * used for payloads that can get very large, like file transfers.
204  * @author Tim Niemueller
205  *
206  * @fn size_t DynamicWebReply::size() = 0
207  * Total size of the web reply.
208  * Return the total size of the reply if known, or -1 if it is not known. In the
209  * latter case your next_chunk() method has to return -1 at some point to end
210  * the transfer. If possible by any means return a meaningful value, as it will
211  * improve the experience of users, especially for long transfers!
212  * @return total size of reply in bytes
213  *
214  * @fn size_t DynamicWebReply::next_chunk(size_t pos, char *buffer, size_t buf_max_size) = 0
215  * Get data of next chunk.
216  * @param pos position in the stream. Note that a certain position may be called
217  * several times.
218  * @param buffer buffer to store data in
219  * @param buf_max_size maximum size in bytes of data that can be put into buffer
220  * @return number of bytes written to buffer, or -1 to immediately stop the
221  * transfer.
222  */
223
224 /** Constructor.
225  * @param code HTTP response code
226  */
227 DynamicWebReply::DynamicWebReply(Code code)
228   : WebReply(code)
229 {
230 }
231
232
233 /** Chunksize.
234  * The size that a single chunk should have. A sub-class may override this if a
235  * specific chunk size is beneficial or even required. The default is 32kb.
236  * @return chunk size in bytes
237  */
238 size_t
239 DynamicWebReply::chunk_size()
240 {
241   // use 32k chunks by default
242   return 32 * 1024;
243 }
244
245
246 /** @class StaticWebReply <webview/reply.h>
247  * Static web reply.
248  * The static web reply is send out as a whole at once and is immediately
249  * deleted after sending. Use it for regular-sized pages and content.
250  * @author Tim Niemueller
251  */
252
253 /** Constructor.
254  * @param code HTTP response code
255  * @param body optional initial body
256  */
257 StaticWebReply::StaticWebReply(Code code, std::string body)
258   : WebReply(code)
259 {
260   _body = body;
261 }
262
263
264 /** Append to body.
265  * @param format format of the text to append. Supports the same format as
266  * printf().
267  */
268 void
269 StaticWebReply::append_body(const char *format, ...)
270 {
271   va_list args;
272   va_start(args, format);
273   char *s;
274   if ( vasprintf(&s, format, args) != -1 ) {
275     _body += s;
276     free(s);
277   }
278   va_end(args);
279 }
280
281 /** Append string to body.
282  * @param s string to add, this may contain null bytes
283  */
284 void
285 StaticWebReply::append_body(const std::string &s)
286 {
287         _body += s;
288 }
289
290
291 /** Append simple text line.
292  * @param text text to append to body
293  * @return reference to this instance
294  */
295 StaticWebReply &
296 StaticWebReply::operator+=(std::string text)
297 {
298   _body += text;
299   return *this;
300 }
301
302
303 /** Get body.
304  * @return reference to body.
305  */
306 const std::string &
307 StaticWebReply::body()
308 {
309   return _body;
310 }
311
312
313 /** Get length of body.
314  * @return body length
315  */
316 std::string::size_type
317 StaticWebReply::body_length()
318 {
319   return _body.length();
320 }
321
322
323 /** Pack the data.
324  * This method is called just before the reply is sent.
325  * You can implement this method if you need to compose your reply before
326  * body() and body_length() provide valid output.
327  */
328 void
329 StaticWebReply::pack()
330 {
331 }
332
333 } // end namespace fawkes