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