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