00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "request_dispatcher.h"
00024 #include "request_processor.h"
00025 #include "page_reply.h"
00026 #include "error_reply.h"
00027
00028 #include <utils/logging/cache.h>
00029 #include <utils/misc/string_urlescape.h>
00030
00031 #include <microhttpd.h>
00032 #include <cstring>
00033 #include <cstdlib>
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 int
00055 WebRequestDispatcher::process_request_cb(void *callback_data,
00056 struct MHD_Connection * connection,
00057 const char *url,
00058 const char *method,
00059 const char *version,
00060 const char *upload_data,
00061 size_t *upload_data_size,
00062 void **session_data)
00063 {
00064 WebRequestDispatcher *rd = static_cast<WebRequestDispatcher *>(callback_data);
00065 return rd->process_request(connection, url, method, version,
00066 upload_data, upload_data_size, session_data);
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 int
00079 WebRequestDispatcher::dynamic_reply_data_cb(void *reply,
00080 uint64_t pos, char *buf, int max)
00081 {
00082 DynamicWebReply *dreply = static_cast<DynamicWebReply *>(reply);
00083 return dreply->next_chunk(pos, buf, max);
00084 }
00085
00086
00087
00088
00089
00090 void
00091 WebRequestDispatcher::dynamic_reply_free_cb(void *reply)
00092 {
00093 DynamicWebReply *dreply = static_cast<DynamicWebReply *>(reply);
00094 delete dreply;
00095 }
00096
00097
00098
00099
00100
00101
00102
00103 int
00104 WebRequestDispatcher::queue_static_reply(struct MHD_Connection * connection,
00105 StaticWebReply *sreply)
00106 {
00107 struct MHD_Response *response;
00108 sreply->pack();
00109 if (sreply->body_length() > 0) {
00110 response = MHD_create_response_from_data(sreply->body_length(),
00111 (void*) sreply->body().c_str(),
00112 MHD_YES,
00113 MHD_YES);
00114 } else {
00115 response = MHD_create_response_from_data(0, (void*) "",
00116 MHD_NO,
00117 MHD_NO);
00118 }
00119
00120 const WebReply::HeaderMap &headers = sreply->headers();
00121 for (WebReply::HeaderMap::const_iterator i = headers.begin(); i != headers.end(); ++i) {
00122 MHD_add_response_header(response, i->first.c_str(), i->second.c_str());
00123 }
00124
00125 int rv = MHD_queue_response(connection, sreply->code(), response);
00126 MHD_destroy_response(response);
00127 return rv;
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 int
00142 WebRequestDispatcher::process_request(struct MHD_Connection * connection,
00143 const char *url,
00144 const char *method,
00145 const char *version,
00146 const char *upload_data,
00147 size_t *upload_data_size,
00148 void **session_data)
00149 {
00150 std::string surl = url;
00151 static int dummy;
00152 int ret;
00153
00154 if (0 != strcmp(method, "GET"))
00155 return MHD_NO;
00156
00157 if (&dummy != *session_data) {
00158
00159
00160 *session_data = &dummy;
00161 return MHD_YES;
00162 }
00163 *session_data = NULL;
00164
00165 WebRequestProcessor *proc = NULL;
00166 std::map<std::string, WebRequestProcessor *>::iterator __pit;
00167 for (__pit = __processors.begin(); (proc == NULL) && (__pit != __processors.end()); ++__pit) {
00168 if (surl.find(__pit->first) == 0) {
00169 WebPageReply::set_active_baseurl(__pit->first);
00170 proc = __pit->second;
00171 }
00172 }
00173
00174 if ( surl == "/" ) {
00175 if ( __startpage_processor ) {
00176 proc = __startpage_processor;
00177 } else {
00178 WebPageReply preply("Fawkes", "<h1>Welcome to Fawkes.</h1><hr />");
00179 ret = queue_static_reply(connection, &preply);
00180 }
00181 }
00182
00183 if (proc) {
00184 struct MHD_Response *response;
00185
00186 char *urlc = strdup(url);
00187 fawkes::hex_unescape(urlc);
00188
00189 WebReply *reply = proc->process_request(urlc, method, version, upload_data, upload_data_size, session_data);
00190
00191 free(urlc);
00192
00193 if ( reply ) {
00194 StaticWebReply *sreply = dynamic_cast<StaticWebReply *>(reply);
00195 DynamicWebReply *dreply = dynamic_cast<DynamicWebReply *>(reply);
00196 if (sreply) {
00197 ret = queue_static_reply(connection, sreply);
00198 delete reply;
00199 } else if (dreply) {
00200 response = MHD_create_response_from_callback(dreply->size(),
00201 dreply->chunk_size(),
00202 WebRequestDispatcher::dynamic_reply_data_cb,
00203 dreply,
00204 WebRequestDispatcher::dynamic_reply_free_cb);
00205 ret = MHD_queue_response (connection, dreply->code(), response);
00206 MHD_destroy_response (response);
00207 } else {
00208 WebErrorPageReply ereply(WebReply::HTTP_INTERNAL_SERVER_ERROR);
00209 ret = queue_static_reply(connection, &ereply);
00210 delete reply;
00211 }
00212 } else {
00213 WebErrorPageReply ereply(WebReply::HTTP_NOT_FOUND);
00214 ret = queue_static_reply(connection, &ereply);
00215 }
00216 } else {
00217 WebErrorPageReply ereply(WebReply::HTTP_NOT_FOUND);
00218 ret = queue_static_reply(connection, &ereply);
00219 }
00220 return ret;
00221 }
00222
00223
00224
00225
00226
00227 void
00228 WebRequestDispatcher::add_processor(const char *url_prefix,
00229 WebRequestProcessor *processor)
00230 {
00231 if (std::string(url_prefix) == "/") {
00232 __startpage_processor = processor;
00233 } else {
00234 __processors[url_prefix] = processor;
00235 }
00236 }
00237
00238
00239
00240
00241
00242 void
00243 WebRequestDispatcher::remove_processor(const char *url_prefix)
00244 {
00245 if (std::string(url_prefix) == "/") {
00246 __startpage_processor = NULL;
00247 } else {
00248 __processors.erase(url_prefix);
00249 }
00250 }