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