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