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