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