| rev | line source | 
| jbe@210 | 1 -- TODO: function incomplete yet | 
| jbe@210 | 2 | 
| jbe@215 | 3 local function file_exists(filename) | 
| jbe@215 | 4   local file = io.open(filename, "r") | 
| jbe@215 | 5   if file then | 
| jbe@215 | 6     io.close(file) | 
| jbe@215 | 7     return true | 
| jbe@215 | 8   else | 
| jbe@215 | 9     return false | 
| jbe@215 | 10   end | 
| jbe@215 | 11 end | 
| jbe@215 | 12 | 
| jbe@216 | 13 function request.process(route) | 
| jbe@216 | 14 | 
| jbe@210 | 15   local success, error_info = xpcall( | 
| jbe@210 | 16     function() | 
| jbe@210 | 17 | 
| jbe@210 | 18       -- restore slots if coming from http redirect | 
| jbe@215 | 19       local tempstore_value = request.get_param{method = "GET", name = "_tempstore"} | 
| jbe@215 | 20       if tempstore_value then | 
| jbe@210 | 21         trace.restore_slots{} | 
| jbe@215 | 22         local blob = tempstore.pop(tempstore_value) | 
| jbe@210 | 23         if blob then slot.restore_all(blob) end | 
| jbe@210 | 24       end | 
| jbe@210 | 25 | 
| jbe@210 | 26 | 
| jbe@210 | 27       if request.is_404() then | 
| jbe@210 | 28         request.set_status("404 Not Found") | 
| jbe@210 | 29         if request.get_404_route() then | 
| jbe@210 | 30           request.forward(request.get_404_route()) | 
| jbe@210 | 31         else | 
| jbe@210 | 32           error("No 404 page set.") | 
| jbe@210 | 33         end | 
| jbe@210 | 34       elseif request.get_action() then | 
| jbe@210 | 35         trace.request{ | 
| jbe@210 | 36           module = request.get_module(), | 
| jbe@210 | 37           action = request.get_action() | 
| jbe@210 | 38         } | 
| jbe@210 | 39         if | 
| jbe@210 | 40           request.get_404_route() and | 
| jbe@210 | 41           not file_exists( | 
| jbe@210 | 42             encode.action_file_path{ | 
| jbe@210 | 43               module = request.get_module(), | 
| jbe@210 | 44               action = request.get_action() | 
| jbe@210 | 45             } | 
| jbe@210 | 46           ) | 
| jbe@210 | 47         then | 
| jbe@210 | 48           request.set_status("404 Not Found") | 
| jbe@210 | 49           request.forward(request.get_404_route()) | 
| jbe@210 | 50         else | 
| jbe@210 | 51           if cgi.method ~= "POST" then | 
| jbe@210 | 52             request.set_status("405 Method Not Allowed") | 
| jbe@210 | 53             cgi.add_header("Allow: POST") | 
| jbe@210 | 54             error("Tried to invoke an action with a GET request.") | 
| jbe@210 | 55           end | 
| jbe@210 | 56           local action_status = execute.filtered_action{ | 
| jbe@210 | 57             module = request.get_module(), | 
| jbe@210 | 58             action = request.get_action(), | 
| jbe@210 | 59           } | 
| jbe@210 | 60           if not request.is_rerouted() then | 
| jbe@210 | 61             local routing_mode, routing_module, routing_view | 
| jbe@210 | 62             routing_mode   = cgi.params["_webmcp_routing." .. action_status .. ".mode"] | 
| jbe@210 | 63             routing_module = cgi.params["_webmcp_routing." .. action_status .. ".module"] | 
| jbe@210 | 64             routing_view   = cgi.params["_webmcp_routing." .. action_status .. ".view"] | 
| jbe@210 | 65             routing_anchor = cgi.params["_webmcp_routing." .. action_status .. ".anchor"] | 
| jbe@210 | 66             if not (routing_mode or routing_module or routing_view) then | 
| jbe@210 | 67               action_status = "default" | 
| jbe@210 | 68               routing_mode   = cgi.params["_webmcp_routing.default.mode"] | 
| jbe@210 | 69               routing_module = cgi.params["_webmcp_routing.default.module"] | 
| jbe@210 | 70               routing_view   = cgi.params["_webmcp_routing.default.view"] | 
| jbe@210 | 71               routing_anchor = cgi.params["_webmcp_routing.default.anchor"] | 
| jbe@210 | 72             end | 
| jbe@210 | 73             assert(routing_module, "Routing information has no module.") | 
| jbe@210 | 74             assert(routing_view,   "Routing information has no view.") | 
| jbe@210 | 75             if routing_mode == "redirect" then | 
| jbe@210 | 76               local routing_params = {} | 
| jbe@210 | 77               for key, value in pairs(cgi.params) do | 
| jbe@210 | 78                 local status, stripped_key = string.match( | 
| jbe@210 | 79                   key, "^_webmcp_routing%.([^%.]*)%.params%.(.*)$" | 
| jbe@210 | 80                 ) | 
| jbe@210 | 81                 if status == action_status then | 
| jbe@210 | 82                   routing_params[stripped_key] = value | 
| jbe@210 | 83                 end | 
| jbe@210 | 84               end | 
| jbe@210 | 85               request.redirect{ | 
| jbe@210 | 86                 module = routing_module, | 
| jbe@210 | 87                 view   = routing_view, | 
| jbe@210 | 88                 id     = cgi.params["_webmcp_routing." .. action_status .. ".id"], | 
| jbe@210 | 89                 params = routing_params, | 
| jbe@210 | 90                 anchor = routing_anchor | 
| jbe@210 | 91               } | 
| jbe@210 | 92             elseif routing_mode == "forward" then | 
| jbe@210 | 93               request.forward{ module = routing_module, view = routing_view } | 
| jbe@210 | 94             else | 
| jbe@210 | 95               error("Missing or unknown routing mode in request parameters.") | 
| jbe@210 | 96             end | 
| jbe@210 | 97           end | 
| jbe@210 | 98         end | 
| jbe@210 | 99       else | 
| jbe@210 | 100         -- no action | 
| jbe@210 | 101         trace.request{ | 
| jbe@210 | 102           module = request.get_module(), | 
| jbe@210 | 103           view   = request.get_view() | 
| jbe@210 | 104         } | 
| jbe@210 | 105         if | 
| jbe@210 | 106           request.get_404_route() and | 
| jbe@210 | 107           not file_exists( | 
| jbe@210 | 108             encode.view_file_path{ | 
| jbe@210 | 109               module = request.get_module(), | 
| jbe@210 | 110               view   = request.get_view() | 
| jbe@210 | 111             } | 
| jbe@210 | 112           ) | 
| jbe@210 | 113         then | 
| jbe@210 | 114           request.set_status("404 Not Found") | 
| jbe@210 | 115           request.forward(request.get_404_route()) | 
| jbe@210 | 116         end | 
| jbe@210 | 117       end | 
| jbe@210 | 118 | 
| jbe@210 | 119       if not request.get_redirect_data() then | 
| jbe@210 | 120         request.process_forward() | 
| jbe@210 | 121         local view = request.get_view() | 
| jbe@210 | 122         if string.find(view, "^_") then | 
| jbe@210 | 123           error("Tried to call a private view (prefixed with underscore).") | 
| jbe@210 | 124         end | 
| jbe@210 | 125         execute.filtered_view{ | 
| jbe@210 | 126           module = request.get_module(), | 
| jbe@210 | 127           view   = view, | 
| jbe@210 | 128         } | 
| jbe@210 | 129       end | 
| jbe@210 | 130 | 
| jbe@210 | 131       -- force error due to missing absolute base URL until its too late to display error message | 
| jbe@210 | 132       --if request.get_redirect_data() then | 
| jbe@210 | 133       --  request.get_absolute_baseurl() | 
| jbe@210 | 134       --end | 
| jbe@210 | 135 | 
| jbe@210 | 136     end, | 
| jbe@210 | 137 | 
| jbe@210 | 138     function(errobj) | 
| jbe@210 | 139       return { | 
| jbe@210 | 140         errobj = errobj, | 
| jbe@210 | 141         stacktrace = string.gsub( | 
| jbe@210 | 142           debug.traceback('', 2), | 
| jbe@210 | 143           "^\r?\n?stack traceback:\r?\n?", "" | 
| jbe@210 | 144         ) | 
| jbe@210 | 145       } | 
| jbe@210 | 146     end | 
| jbe@210 | 147   ) | 
| jbe@210 | 148 | 
| jbe@210 | 149   if not success then trace.error{} end | 
| jbe@210 | 150 | 
| jbe@210 | 151   -- laufzeitermittlung | 
| jbe@210 | 152   trace.exectime{ real = extos.monotonic_hires_time(), cpu = os.clock() } | 
| jbe@210 | 153 | 
| jbe@210 | 154   slot.select('trace', trace.render)  -- render trace information | 
| jbe@210 | 155 | 
| jbe@210 | 156   local redirect_data = request.get_redirect_data() | 
| jbe@210 | 157 | 
| jbe@210 | 158   -- log error and switch to error layout, unless success | 
| jbe@210 | 159   if not success then | 
| jbe@210 | 160     local errobj     = error_info.errobj | 
| jbe@210 | 161     local stacktrace = error_info.stacktrace | 
| jbe@210 | 162     if not request.get_status() and not request.get_json_request_slots() then | 
| jbe@210 | 163       request.set_status("500 Internal Server Error") | 
| jbe@210 | 164     end | 
| jbe@210 | 165     slot.set_layout('system_error') | 
| jbe@210 | 166     slot.select('system_error', function() | 
| jbe@210 | 167       if getmetatable(errobj) == mondelefant.errorobject_metatable then | 
| jbe@210 | 168         slot.put( | 
| jbe@210 | 169           "<p>Database error of class <b>", | 
| jbe@210 | 170           encode.html(errobj.code), | 
| jbe@210 | 171           "</b> occured:<br/><b>", | 
| jbe@210 | 172           encode.html(errobj.message), | 
| jbe@210 | 173           "</b></p>" | 
| jbe@210 | 174         ) | 
| jbe@210 | 175       else | 
| jbe@210 | 176         slot.put("<p><b>", encode.html(tostring(errobj)), "</b></p>") | 
| jbe@210 | 177       end | 
| jbe@210 | 178       slot.put("<p>Stack trace follows:<br/>") | 
| jbe@210 | 179       slot.put(encode.html_newlines(encode.html(stacktrace))) | 
| jbe@210 | 180       slot.put("</p>") | 
| jbe@210 | 181     end) | 
| jbe@210 | 182   elseif redirect_data then | 
| jbe@210 | 183     local redirect_params = {} | 
| jbe@210 | 184     for key, value in pairs(redirect_data.params) do | 
| jbe@210 | 185       redirect_params[key] = value | 
| jbe@210 | 186     end | 
| jbe@210 | 187     local slot_dump = slot.dump_all() | 
| jbe@210 | 188     if slot_dump ~= "" then | 
| jbe@210 | 189       redirect_params.tempstore = tempstore.save(slot_dump) | 
| jbe@210 | 190     end | 
| jbe@210 | 191     local json_request_slots = request.get_json_request_slots() | 
| jbe@210 | 192     if json_request_slots then | 
| jbe@210 | 193       redirect_params["_webmcp_json_slots[]"] = json_request_slots | 
| jbe@210 | 194     end | 
| jbe@210 | 195     cgi.redirect( | 
| jbe@210 | 196       encode.url{ | 
| jbe@210 | 197         base   = request.get_absolute_baseurl(), | 
| jbe@210 | 198         module = redirect_data.module, | 
| jbe@210 | 199         view   = redirect_data.view, | 
| jbe@210 | 200         id     = redirect_data.id, | 
| jbe@210 | 201         params = redirect_params, | 
| jbe@210 | 202         anchor = redirect_data.anchor | 
| jbe@210 | 203       } | 
| jbe@210 | 204     ) | 
| jbe@210 | 205     cgi.send_data() | 
| jbe@210 | 206   end | 
| jbe@210 | 207 | 
| jbe@210 | 208   if not success or not redirect_data then | 
| jbe@210 | 209 | 
| jbe@210 | 210     local http_status = request.get_status() | 
| jbe@210 | 211     if http_status then | 
| jbe@210 | 212       cgi.set_status(http_status) | 
| jbe@210 | 213     end | 
| jbe@210 | 214 | 
| jbe@210 | 215     local json_request_slots = request.get_json_request_slots() | 
| jbe@210 | 216     if json_request_slots then | 
| jbe@210 | 217       cgi.set_content_type('application/json') | 
| jbe@210 | 218       local data = {} | 
| jbe@210 | 219       for idx, slot_ident in ipairs(json_request_slots) do | 
| jbe@210 | 220         data[slot_ident] = slot.get_content(slot_ident) | 
| jbe@210 | 221       end | 
| jbe@210 | 222       cgi.send_data(encode.json(data)) | 
| jbe@210 | 223     else | 
| jbe@210 | 224       cgi.set_content_type(slot.get_content_type()) | 
| jbe@210 | 225       cgi.send_data(slot.render_layout()) | 
| jbe@210 | 226     end | 
| jbe@210 | 227   end | 
| jbe@210 | 228 | 
| jbe@210 | 229 end |