Fawkes API  Fawkes Development Version
reply.cpp
00001 
00002 /***************************************************************************
00003  *  reply.cpp - Web request reply
00004  *
00005  *  Created: Thu Oct 23 12:01:05 2008
00006  *  Copyright  2006-2009  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  Read the full text in the LICENSE.GPL file in the doc directory.
00021  */
00022 
00023 #include <webview/reply.h>
00024 
00025 #include <core/exception.h>
00026 #include <cstdlib>
00027 #include <cstdarg>
00028 #include <cstdio>
00029 
00030 namespace fawkes {
00031 #if 0 /* just to make Emacs auto-indent happy */
00032 }
00033 #endif
00034 
00035 /** @class WebReply <webview/reply.h>
00036  * Basic web reply.
00037  * The base class for all web replies. Though the WebRequestDispatcher expects
00038  * sub-classes of StaticWebReply or DynamicWebReply.
00039  * @author Tim Niemueller
00040  */
00041 
00042 /** Constructor.
00043  * @param code HTTP response code
00044  */
00045 WebReply::WebReply(response_code_t code)
00046 {
00047   __code = code;
00048 }
00049 
00050 
00051 /** Destructor. */
00052 WebReply::~WebReply()
00053 {
00054 }
00055 
00056 
00057 /** Get response code.
00058  * @return HTTP response code
00059  */
00060 WebReply::response_code_t
00061 WebReply::code() const
00062 {
00063   return __code;
00064 }
00065 
00066 
00067 /** Add a HTTP header.
00068  * @param header header entry name
00069  * @param content content of the header field
00070  */
00071 void
00072 WebReply::add_header(std::string header, std::string content)
00073 {
00074   __headers[header] = content;
00075 }
00076 
00077 
00078 /** Add a HTTP header.
00079  * @param header_string header string of the format "Key: Value".
00080  */
00081 void
00082 WebReply::add_header(std::string header_string)
00083 {
00084   std::string::size_type pos;
00085   if ((pos = header_string.find(":")) != std::string::npos) {
00086     std::string header = header_string.substr(0, pos);
00087     std::string content;
00088     if (header_string[pos+1] == ' ') {
00089       content = header_string.substr(pos+2);
00090     } else {
00091       content = header_string.substr(pos+1);
00092     }
00093     __headers[header] = content;
00094   } else {
00095     throw Exception("Invalid header '%s'", header_string.c_str());
00096   }
00097 }
00098 
00099 
00100 /** get headers.
00101  * @return map of header name/content pairs.
00102  */
00103 const WebReply::HeaderMap &
00104 WebReply::headers() const
00105 {
00106   return __headers;
00107 }
00108 
00109 
00110 /** @class DynamicWebReply <webview/reply.h>
00111  * Dynamic web reply.
00112  * A reply of this type is send out in chunks, not all as a whole. It should be
00113  * used for payloads that can get very large, like file transfers.
00114  * @author Tim Niemueller
00115  *
00116  * @fn size_t DynamicWebReply::size() = 0
00117  * Total size of the web reply.
00118  * Return the total size of the reply if known, or 0 if it is not known. In the
00119  * latter case your next_chunk() method has to return -1 at some point to end
00120  * the transfer. If possible by any means return a meaningful value, as it will
00121  * improve the experience of users, especially for long transfers!
00122  * @return total size of reply in bytes
00123  *
00124  * @fn size_t DynamicWebReply::next_chunk(size_t pos, char *buffer, size_t buf_max_size) = 0
00125  * Get data of next chunk.
00126  * @param pos position in the stream. Note that a certain position may be called
00127  * several times.
00128  * @param buffer buffer to store data in
00129  * @param buf_max_size maximum size in bytes of data that can be put into buffer
00130  * @return number of bytes written to buffer, or -1 to immediately stop the
00131  * transfer.
00132  */
00133 
00134 /** Constructor.
00135  * @param code HTTP response code
00136  */
00137 DynamicWebReply::DynamicWebReply(response_code_t code)
00138   : WebReply(code)
00139 {
00140 }
00141 
00142 
00143 /** Chunksize.
00144  * The size that a single chunk should have. A sub-class may override this if a
00145  * specific chunk size is beneficial or even required. The default is 32kb.
00146  * @return chunk size in bytes
00147  */
00148 size_t
00149 DynamicWebReply::chunk_size()
00150 {
00151   // use 32k chunks by default
00152   return 32 * 1024;
00153 }
00154 
00155 
00156 /** @class StaticWebReply <webview/reply.h>
00157  * Static web reply.
00158  * The static web reply is send out as a whole at once and is immediately
00159  * deleted after sending. Use it for regular-sized pages and content.
00160  * @author Tim Niemueller
00161  */
00162 
00163 /** Constructor.
00164  * @param code HTTP response code
00165  * @param body optional initial body
00166  */
00167 StaticWebReply::StaticWebReply(response_code_t code, std::string body)
00168   : WebReply(code)
00169 {
00170   _body = body;
00171 }
00172 
00173 
00174 /** Append to body.
00175  * @param format format of the text to append. Supports the same format as
00176  * printf().
00177  */
00178 void
00179 StaticWebReply::append_body(const char *format, ...)
00180 {
00181   va_list args;
00182   va_start(args, format);
00183   char *s;
00184   if ( vasprintf(&s, format, args) != -1 ) {
00185     _body += s;
00186     free(s);
00187   }
00188   va_end(args);
00189 }
00190 
00191 
00192 /** Append simple text line.
00193  * @param text text to append to body
00194  * @return reference to this instance
00195  */
00196 StaticWebReply &
00197 StaticWebReply::operator+=(std::string text)
00198 {
00199   _body += text;
00200   return *this;
00201 }
00202 
00203 
00204 /** Get body.
00205  * @return reference to body.
00206  */
00207 const std::string &
00208 StaticWebReply::body()
00209 {
00210   return _body;
00211 }
00212 
00213 
00214 /** Get length of body.
00215  * @return body length
00216  */
00217 std::string::size_type
00218 StaticWebReply::body_length()
00219 {
00220   return _body.length();
00221 }
00222 
00223 
00224 /** Pack the data.
00225  * This method is called just before the reply is sent.
00226  * You can implement this method if you need to compose your reply before
00227  * body() and body_length() provide valid output.
00228  */
00229 void
00230 StaticWebReply::pack()
00231 {
00232 }
00233 
00234 } // end namespace fawkes